1 // Copyright 2012 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "src/builtins.h" 6 7 #include "src/api.h" 8 #include "src/api-natives.h" 9 #include "src/arguments.h" 10 #include "src/base/once.h" 11 #include "src/bootstrapper.h" 12 #include "src/dateparser-inl.h" 13 #include "src/elements.h" 14 #include "src/frames-inl.h" 15 #include "src/gdb-jit.h" 16 #include "src/ic/handler-compiler.h" 17 #include "src/ic/ic.h" 18 #include "src/isolate-inl.h" 19 #include "src/messages.h" 20 #include "src/profiler/cpu-profiler.h" 21 #include "src/property-descriptor.h" 22 #include "src/prototype.h" 23 #include "src/string-builder.h" 24 #include "src/vm-state-inl.h" 25 26 namespace v8 { 27 namespace internal { 28 29 namespace { 30 31 // Arguments object passed to C++ builtins. 32 template <BuiltinExtraArguments extra_args> 33 class BuiltinArguments : public Arguments { 34 public: 35 BuiltinArguments(int length, Object** arguments) 36 : Arguments(length, arguments) { 37 // Check we have at least the receiver. 38 DCHECK_LE(1, this->length()); 39 } 40 41 Object*& operator[] (int index) { 42 DCHECK(index < length()); 43 return Arguments::operator[](index); 44 } 45 46 template <class S> Handle<S> at(int index) { 47 DCHECK(index < length()); 48 return Arguments::at<S>(index); 49 } 50 51 Handle<Object> atOrUndefined(Isolate* isolate, int index) { 52 if (index >= length()) { 53 return isolate->factory()->undefined_value(); 54 } 55 return at<Object>(index); 56 } 57 58 Handle<Object> receiver() { 59 return Arguments::at<Object>(0); 60 } 61 62 Handle<JSFunction> target(); 63 Handle<HeapObject> new_target(); 64 65 // Gets the total number of arguments including the receiver (but 66 // excluding extra arguments). 67 int length() const; 68 }; 69 70 71 // Specialize BuiltinArguments for the extra arguments. 72 73 template <> 74 int BuiltinArguments<BuiltinExtraArguments::kNone>::length() const { 75 return Arguments::length(); 76 } 77 78 template <> 79 int BuiltinArguments<BuiltinExtraArguments::kTarget>::length() const { 80 return Arguments::length() - 1; 81 } 82 83 template <> 84 Handle<JSFunction> BuiltinArguments<BuiltinExtraArguments::kTarget>::target() { 85 return Arguments::at<JSFunction>(Arguments::length() - 1); 86 } 87 88 template <> 89 int BuiltinArguments<BuiltinExtraArguments::kNewTarget>::length() const { 90 return Arguments::length() - 1; 91 } 92 93 template <> 94 Handle<HeapObject> 95 BuiltinArguments<BuiltinExtraArguments::kNewTarget>::new_target() { 96 return Arguments::at<HeapObject>(Arguments::length() - 1); 97 } 98 99 template <> 100 int BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>::length() 101 const { 102 return Arguments::length() - 2; 103 } 104 105 template <> 106 Handle<JSFunction> 107 BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>::target() { 108 return Arguments::at<JSFunction>(Arguments::length() - 2); 109 } 110 111 template <> 112 Handle<HeapObject> 113 BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>::new_target() { 114 return Arguments::at<HeapObject>(Arguments::length() - 1); 115 } 116 117 118 #define DEF_ARG_TYPE(name, spec) \ 119 typedef BuiltinArguments<BuiltinExtraArguments::spec> name##ArgumentsType; 120 BUILTIN_LIST_C(DEF_ARG_TYPE) 121 #undef DEF_ARG_TYPE 122 123 124 // ---------------------------------------------------------------------------- 125 // Support macro for defining builtins in C++. 126 // ---------------------------------------------------------------------------- 127 // 128 // A builtin function is defined by writing: 129 // 130 // BUILTIN(name) { 131 // ... 132 // } 133 // 134 // In the body of the builtin function the arguments can be accessed 135 // through the BuiltinArguments object args. 136 137 #define BUILTIN(name) \ 138 MUST_USE_RESULT static Object* Builtin_Impl_##name( \ 139 name##ArgumentsType args, Isolate* isolate); \ 140 MUST_USE_RESULT static Object* Builtin_##name( \ 141 int args_length, Object** args_object, Isolate* isolate) { \ 142 name##ArgumentsType args(args_length, args_object); \ 143 return Builtin_Impl_##name(args, isolate); \ 144 } \ 145 MUST_USE_RESULT static Object* Builtin_Impl_##name( \ 146 name##ArgumentsType args, Isolate* isolate) 147 148 149 // ---------------------------------------------------------------------------- 150 151 152 #define CHECK_RECEIVER(Type, name, method) \ 153 if (!args.receiver()->Is##Type()) { \ 154 THROW_NEW_ERROR_RETURN_FAILURE( \ 155 isolate, \ 156 NewTypeError(MessageTemplate::kIncompatibleMethodReceiver, \ 157 isolate->factory()->NewStringFromAsciiChecked(method), \ 158 args.receiver())); \ 159 } \ 160 Handle<Type> name = Handle<Type>::cast(args.receiver()) 161 162 163 inline bool ClampedToInteger(Object* object, int* out) { 164 // This is an extended version of ECMA-262 7.1.11 handling signed values 165 // Try to convert object to a number and clamp values to [kMinInt, kMaxInt] 166 if (object->IsSmi()) { 167 *out = Smi::cast(object)->value(); 168 return true; 169 } else if (object->IsHeapNumber()) { 170 double value = HeapNumber::cast(object)->value(); 171 if (std::isnan(value)) { 172 *out = 0; 173 } else if (value > kMaxInt) { 174 *out = kMaxInt; 175 } else if (value < kMinInt) { 176 *out = kMinInt; 177 } else { 178 *out = static_cast<int>(value); 179 } 180 return true; 181 } else if (object->IsUndefined() || object->IsNull()) { 182 *out = 0; 183 return true; 184 } else if (object->IsBoolean()) { 185 *out = object->IsTrue(); 186 return true; 187 } 188 return false; 189 } 190 191 192 inline bool GetSloppyArgumentsLength(Isolate* isolate, Handle<JSObject> object, 193 int* out) { 194 Map* arguments_map = isolate->native_context()->sloppy_arguments_map(); 195 if (object->map() != arguments_map) return false; 196 DCHECK(object->HasFastElements()); 197 Object* len_obj = object->InObjectPropertyAt(Heap::kArgumentsLengthIndex); 198 if (!len_obj->IsSmi()) return false; 199 *out = Max(0, Smi::cast(len_obj)->value()); 200 return *out <= object->elements()->length(); 201 } 202 203 204 inline bool PrototypeHasNoElements(PrototypeIterator* iter) { 205 DisallowHeapAllocation no_gc; 206 for (; !iter->IsAtEnd(); iter->Advance()) { 207 if (iter->GetCurrent()->IsJSProxy()) return false; 208 JSObject* current = iter->GetCurrent<JSObject>(); 209 if (current->IsAccessCheckNeeded()) return false; 210 if (current->HasIndexedInterceptor()) return false; 211 if (current->elements()->length() != 0) return false; 212 } 213 return true; 214 } 215 216 217 inline bool IsJSArrayFastElementMovingAllowed(Isolate* isolate, 218 JSArray* receiver) { 219 DisallowHeapAllocation no_gc; 220 // If the array prototype chain is intact (and free of elements), and if the 221 // receiver's prototype is the array prototype, then we are done. 222 Object* prototype = receiver->map()->prototype(); 223 if (prototype->IsJSArray() && 224 isolate->is_initial_array_prototype(JSArray::cast(prototype)) && 225 isolate->IsFastArrayConstructorPrototypeChainIntact()) { 226 return true; 227 } 228 229 // Slow case. 230 PrototypeIterator iter(isolate, receiver); 231 return PrototypeHasNoElements(&iter); 232 } 233 234 235 // Returns empty handle if not applicable. 236 MUST_USE_RESULT 237 inline MaybeHandle<FixedArrayBase> EnsureJSArrayWithWritableFastElements( 238 Isolate* isolate, Handle<Object> receiver, Arguments* args, 239 int first_added_arg) { 240 if (!receiver->IsJSArray()) return MaybeHandle<FixedArrayBase>(); 241 Handle<JSArray> array = Handle<JSArray>::cast(receiver); 242 // If there may be elements accessors in the prototype chain, the fast path 243 // cannot be used if there arguments to add to the array. 244 Heap* heap = isolate->heap(); 245 if (args != NULL && !IsJSArrayFastElementMovingAllowed(isolate, *array)) { 246 return MaybeHandle<FixedArrayBase>(); 247 } 248 if (array->map()->is_observed()) return MaybeHandle<FixedArrayBase>(); 249 if (!array->map()->is_extensible()) return MaybeHandle<FixedArrayBase>(); 250 Handle<FixedArrayBase> elms(array->elements(), isolate); 251 Map* map = elms->map(); 252 if (map == heap->fixed_array_map()) { 253 if (args == NULL || array->HasFastObjectElements()) return elms; 254 } else if (map == heap->fixed_cow_array_map()) { 255 elms = JSObject::EnsureWritableFastElements(array); 256 if (args == NULL || array->HasFastObjectElements()) return elms; 257 } else if (map == heap->fixed_double_array_map()) { 258 if (args == NULL) return elms; 259 } else { 260 return MaybeHandle<FixedArrayBase>(); 261 } 262 263 // Adding elements to the array prototype would break code that makes sure 264 // it has no elements. Handle that elsewhere. 265 if (isolate->IsAnyInitialArrayPrototype(array)) { 266 return MaybeHandle<FixedArrayBase>(); 267 } 268 269 // Need to ensure that the arguments passed in args can be contained in 270 // the array. 271 int args_length = args->length(); 272 if (first_added_arg >= args_length) return handle(array->elements(), isolate); 273 274 ElementsKind origin_kind = array->map()->elements_kind(); 275 DCHECK(!IsFastObjectElementsKind(origin_kind)); 276 ElementsKind target_kind = origin_kind; 277 { 278 DisallowHeapAllocation no_gc; 279 int arg_count = args_length - first_added_arg; 280 Object** arguments = args->arguments() - first_added_arg - (arg_count - 1); 281 for (int i = 0; i < arg_count; i++) { 282 Object* arg = arguments[i]; 283 if (arg->IsHeapObject()) { 284 if (arg->IsHeapNumber()) { 285 target_kind = FAST_DOUBLE_ELEMENTS; 286 } else { 287 target_kind = FAST_ELEMENTS; 288 break; 289 } 290 } 291 } 292 } 293 if (target_kind != origin_kind) { 294 JSObject::TransitionElementsKind(array, target_kind); 295 return handle(array->elements(), isolate); 296 } 297 return elms; 298 } 299 300 301 MUST_USE_RESULT static Object* CallJsIntrinsic( 302 Isolate* isolate, Handle<JSFunction> function, 303 BuiltinArguments<BuiltinExtraArguments::kNone> args) { 304 HandleScope handleScope(isolate); 305 int argc = args.length() - 1; 306 ScopedVector<Handle<Object> > argv(argc); 307 for (int i = 0; i < argc; ++i) { 308 argv[i] = args.at<Object>(i + 1); 309 } 310 Handle<Object> result; 311 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 312 isolate, result, 313 Execution::Call(isolate, 314 function, 315 args.receiver(), 316 argc, 317 argv.start())); 318 return *result; 319 } 320 321 322 } // namespace 323 324 325 BUILTIN(Illegal) { 326 UNREACHABLE(); 327 return isolate->heap()->undefined_value(); // Make compiler happy. 328 } 329 330 331 BUILTIN(EmptyFunction) { return isolate->heap()->undefined_value(); } 332 333 334 BUILTIN(ArrayPush) { 335 HandleScope scope(isolate); 336 Handle<Object> receiver = args.receiver(); 337 MaybeHandle<FixedArrayBase> maybe_elms_obj = 338 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1); 339 Handle<FixedArrayBase> elms_obj; 340 if (!maybe_elms_obj.ToHandle(&elms_obj)) { 341 return CallJsIntrinsic(isolate, isolate->array_push(), args); 342 } 343 // Fast Elements Path 344 int push_size = args.length() - 1; 345 Handle<JSArray> array = Handle<JSArray>::cast(receiver); 346 int len = Smi::cast(array->length())->value(); 347 if (push_size == 0) { 348 return Smi::FromInt(len); 349 } 350 if (push_size > 0 && 351 JSArray::WouldChangeReadOnlyLength(array, len + push_size)) { 352 return CallJsIntrinsic(isolate, isolate->array_push(), args); 353 } 354 DCHECK(!array->map()->is_observed()); 355 ElementsAccessor* accessor = array->GetElementsAccessor(); 356 int new_length = accessor->Push(array, elms_obj, &args, push_size); 357 return Smi::FromInt(new_length); 358 } 359 360 361 BUILTIN(ArrayPop) { 362 HandleScope scope(isolate); 363 Handle<Object> receiver = args.receiver(); 364 MaybeHandle<FixedArrayBase> maybe_elms_obj = 365 EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0); 366 Handle<FixedArrayBase> elms_obj; 367 if (!maybe_elms_obj.ToHandle(&elms_obj)) { 368 return CallJsIntrinsic(isolate, isolate->array_pop(), args); 369 } 370 371 Handle<JSArray> array = Handle<JSArray>::cast(receiver); 372 DCHECK(!array->map()->is_observed()); 373 374 uint32_t len = static_cast<uint32_t>(Smi::cast(array->length())->value()); 375 if (len == 0) return isolate->heap()->undefined_value(); 376 377 if (JSArray::HasReadOnlyLength(array)) { 378 return CallJsIntrinsic(isolate, isolate->array_pop(), args); 379 } 380 381 Handle<Object> result; 382 if (IsJSArrayFastElementMovingAllowed(isolate, JSArray::cast(*receiver))) { 383 // Fast Elements Path 384 result = array->GetElementsAccessor()->Pop(array, elms_obj); 385 } else { 386 // Use Slow Lookup otherwise 387 uint32_t new_length = len - 1; 388 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 389 isolate, result, Object::GetElement(isolate, array, new_length)); 390 JSArray::SetLength(array, new_length); 391 } 392 return *result; 393 } 394 395 396 BUILTIN(ArrayShift) { 397 HandleScope scope(isolate); 398 Heap* heap = isolate->heap(); 399 Handle<Object> receiver = args.receiver(); 400 MaybeHandle<FixedArrayBase> maybe_elms_obj = 401 EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0); 402 Handle<FixedArrayBase> elms_obj; 403 if (!maybe_elms_obj.ToHandle(&elms_obj) || 404 !IsJSArrayFastElementMovingAllowed(isolate, JSArray::cast(*receiver))) { 405 return CallJsIntrinsic(isolate, isolate->array_shift(), args); 406 } 407 Handle<JSArray> array = Handle<JSArray>::cast(receiver); 408 DCHECK(!array->map()->is_observed()); 409 410 int len = Smi::cast(array->length())->value(); 411 if (len == 0) return heap->undefined_value(); 412 413 if (JSArray::HasReadOnlyLength(array)) { 414 return CallJsIntrinsic(isolate, isolate->array_shift(), args); 415 } 416 417 Handle<Object> first = array->GetElementsAccessor()->Shift(array, elms_obj); 418 return *first; 419 } 420 421 422 BUILTIN(ArrayUnshift) { 423 HandleScope scope(isolate); 424 Handle<Object> receiver = args.receiver(); 425 MaybeHandle<FixedArrayBase> maybe_elms_obj = 426 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1); 427 Handle<FixedArrayBase> elms_obj; 428 if (!maybe_elms_obj.ToHandle(&elms_obj)) { 429 return CallJsIntrinsic(isolate, isolate->array_unshift(), args); 430 } 431 Handle<JSArray> array = Handle<JSArray>::cast(receiver); 432 DCHECK(!array->map()->is_observed()); 433 int to_add = args.length() - 1; 434 if (to_add == 0) { 435 return array->length(); 436 } 437 // Currently fixed arrays cannot grow too big, so 438 // we should never hit this case. 439 DCHECK(to_add <= (Smi::kMaxValue - Smi::cast(array->length())->value())); 440 441 if (to_add > 0 && JSArray::HasReadOnlyLength(array)) { 442 return CallJsIntrinsic(isolate, isolate->array_unshift(), args); 443 } 444 445 ElementsAccessor* accessor = array->GetElementsAccessor(); 446 int new_length = accessor->Unshift(array, elms_obj, &args, to_add); 447 return Smi::FromInt(new_length); 448 } 449 450 451 BUILTIN(ArraySlice) { 452 HandleScope scope(isolate); 453 Handle<Object> receiver = args.receiver(); 454 Handle<JSObject> object; 455 Handle<FixedArrayBase> elms_obj; 456 int len = -1; 457 int relative_start = 0; 458 int relative_end = 0; 459 bool is_sloppy_arguments = false; 460 461 // TODO(littledan): Look up @@species only once, not once here and 462 // again in the JS builtin. Pass the species out? 463 Handle<Object> species; 464 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 465 isolate, species, Object::ArraySpeciesConstructor(isolate, receiver)); 466 if (*species != isolate->context()->native_context()->array_function()) { 467 return CallJsIntrinsic(isolate, isolate->array_slice(), args); 468 } 469 if (receiver->IsJSArray()) { 470 DisallowHeapAllocation no_gc; 471 JSArray* array = JSArray::cast(*receiver); 472 if (!array->HasFastElements() || 473 !IsJSArrayFastElementMovingAllowed(isolate, array)) { 474 AllowHeapAllocation allow_allocation; 475 return CallJsIntrinsic(isolate, isolate->array_slice(), args); 476 } 477 len = Smi::cast(array->length())->value(); 478 object = Handle<JSObject>::cast(receiver); 479 elms_obj = handle(array->elements(), isolate); 480 } else if (receiver->IsJSObject() && 481 GetSloppyArgumentsLength(isolate, Handle<JSObject>::cast(receiver), 482 &len)) { 483 // Array.prototype.slice(arguments, ...) is quite a common idiom 484 // (notably more than 50% of invocations in Web apps). 485 // Treat it in C++ as well. 486 is_sloppy_arguments = true; 487 object = Handle<JSObject>::cast(receiver); 488 elms_obj = handle(object->elements(), isolate); 489 } else { 490 AllowHeapAllocation allow_allocation; 491 return CallJsIntrinsic(isolate, isolate->array_slice(), args); 492 } 493 DCHECK(len >= 0); 494 int argument_count = args.length() - 1; 495 // Note carefully chosen defaults---if argument is missing, 496 // it's undefined which gets converted to 0 for relative_start 497 // and to len for relative_end. 498 relative_start = 0; 499 relative_end = len; 500 if (argument_count > 0) { 501 DisallowHeapAllocation no_gc; 502 if (!ClampedToInteger(args[1], &relative_start)) { 503 AllowHeapAllocation allow_allocation; 504 return CallJsIntrinsic(isolate, isolate->array_slice(), args); 505 } 506 if (argument_count > 1) { 507 Object* end_arg = args[2]; 508 // slice handles the end_arg specially 509 if (end_arg->IsUndefined()) { 510 relative_end = len; 511 } else if (!ClampedToInteger(end_arg, &relative_end)) { 512 AllowHeapAllocation allow_allocation; 513 return CallJsIntrinsic(isolate, isolate->array_slice(), args); 514 } 515 } 516 } 517 518 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 6. 519 uint32_t actual_start = (relative_start < 0) ? Max(len + relative_start, 0) 520 : Min(relative_start, len); 521 522 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 8. 523 uint32_t actual_end = 524 (relative_end < 0) ? Max(len + relative_end, 0) : Min(relative_end, len); 525 526 if (actual_end <= actual_start) { 527 Handle<JSArray> result_array = isolate->factory()->NewJSArray( 528 GetPackedElementsKind(object->GetElementsKind()), 0, 0); 529 return *result_array; 530 } 531 532 ElementsAccessor* accessor = object->GetElementsAccessor(); 533 if (is_sloppy_arguments && 534 !accessor->IsPacked(object, elms_obj, actual_start, actual_end)) { 535 // Don't deal with arguments with holes in C++ 536 AllowHeapAllocation allow_allocation; 537 return CallJsIntrinsic(isolate, isolate->array_slice(), args); 538 } 539 Handle<JSArray> result_array = 540 accessor->Slice(object, elms_obj, actual_start, actual_end); 541 return *result_array; 542 } 543 544 545 BUILTIN(ArraySplice) { 546 HandleScope scope(isolate); 547 Handle<Object> receiver = args.receiver(); 548 MaybeHandle<FixedArrayBase> maybe_elms_obj = 549 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 3); 550 Handle<FixedArrayBase> elms_obj; 551 if (!maybe_elms_obj.ToHandle(&elms_obj)) { 552 return CallJsIntrinsic(isolate, isolate->array_splice(), args); 553 } 554 // TODO(littledan): Look up @@species only once, not once here and 555 // again in the JS builtin. Pass the species out? 556 Handle<Object> species; 557 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 558 isolate, species, Object::ArraySpeciesConstructor(isolate, receiver)); 559 if (*species != isolate->context()->native_context()->array_function()) { 560 return CallJsIntrinsic(isolate, isolate->array_splice(), args); 561 } 562 Handle<JSArray> array = Handle<JSArray>::cast(receiver); 563 DCHECK(!array->map()->is_observed()); 564 565 int argument_count = args.length() - 1; 566 int relative_start = 0; 567 if (argument_count > 0) { 568 DisallowHeapAllocation no_gc; 569 if (!ClampedToInteger(args[1], &relative_start)) { 570 AllowHeapAllocation allow_allocation; 571 return CallJsIntrinsic(isolate, isolate->array_splice(), args); 572 } 573 } 574 int len = Smi::cast(array->length())->value(); 575 // clip relative start to [0, len] 576 int actual_start = (relative_start < 0) ? Max(len + relative_start, 0) 577 : Min(relative_start, len); 578 579 int actual_delete_count; 580 if (argument_count == 1) { 581 // SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is 582 // given as a request to delete all the elements from the start. 583 // And it differs from the case of undefined delete count. 584 // This does not follow ECMA-262, but we do the same for compatibility. 585 DCHECK(len - actual_start >= 0); 586 actual_delete_count = len - actual_start; 587 } else { 588 int delete_count = 0; 589 DisallowHeapAllocation no_gc; 590 if (argument_count > 1) { 591 if (!ClampedToInteger(args[2], &delete_count)) { 592 AllowHeapAllocation allow_allocation; 593 return CallJsIntrinsic(isolate, isolate->array_splice(), args); 594 } 595 } 596 actual_delete_count = Min(Max(delete_count, 0), len - actual_start); 597 } 598 599 int add_count = (argument_count > 1) ? (argument_count - 2) : 0; 600 int new_length = len - actual_delete_count + add_count; 601 602 if (new_length != len && JSArray::HasReadOnlyLength(array)) { 603 AllowHeapAllocation allow_allocation; 604 return CallJsIntrinsic(isolate, isolate->array_splice(), args); 605 } 606 ElementsAccessor* accessor = array->GetElementsAccessor(); 607 Handle<JSArray> result_array = accessor->Splice( 608 array, elms_obj, actual_start, actual_delete_count, &args, add_count); 609 return *result_array; 610 } 611 612 613 // Array Concat ------------------------------------------------------------- 614 615 namespace { 616 617 /** 618 * A simple visitor visits every element of Array's. 619 * The backend storage can be a fixed array for fast elements case, 620 * or a dictionary for sparse array. Since Dictionary is a subtype 621 * of FixedArray, the class can be used by both fast and slow cases. 622 * The second parameter of the constructor, fast_elements, specifies 623 * whether the storage is a FixedArray or Dictionary. 624 * 625 * An index limit is used to deal with the situation that a result array 626 * length overflows 32-bit non-negative integer. 627 */ 628 class ArrayConcatVisitor { 629 public: 630 ArrayConcatVisitor(Isolate* isolate, Handle<FixedArray> storage, 631 bool fast_elements) 632 : isolate_(isolate), 633 storage_(Handle<FixedArray>::cast( 634 isolate->global_handles()->Create(*storage))), 635 index_offset_(0u), 636 bit_field_(FastElementsField::encode(fast_elements) | 637 ExceedsLimitField::encode(false)) {} 638 639 ~ArrayConcatVisitor() { clear_storage(); } 640 641 void visit(uint32_t i, Handle<Object> elm) { 642 if (i >= JSObject::kMaxElementCount - index_offset_) { 643 set_exceeds_array_limit(true); 644 return; 645 } 646 uint32_t index = index_offset_ + i; 647 648 if (fast_elements()) { 649 if (index < static_cast<uint32_t>(storage_->length())) { 650 storage_->set(index, *elm); 651 return; 652 } 653 // Our initial estimate of length was foiled, possibly by 654 // getters on the arrays increasing the length of later arrays 655 // during iteration. 656 // This shouldn't happen in anything but pathological cases. 657 SetDictionaryMode(); 658 // Fall-through to dictionary mode. 659 } 660 DCHECK(!fast_elements()); 661 Handle<SeededNumberDictionary> dict( 662 SeededNumberDictionary::cast(*storage_)); 663 // The object holding this backing store has just been allocated, so 664 // it cannot yet be used as a prototype. 665 Handle<SeededNumberDictionary> result = 666 SeededNumberDictionary::AtNumberPut(dict, index, elm, false); 667 if (!result.is_identical_to(dict)) { 668 // Dictionary needed to grow. 669 clear_storage(); 670 set_storage(*result); 671 } 672 } 673 674 void increase_index_offset(uint32_t delta) { 675 if (JSObject::kMaxElementCount - index_offset_ < delta) { 676 index_offset_ = JSObject::kMaxElementCount; 677 } else { 678 index_offset_ += delta; 679 } 680 // If the initial length estimate was off (see special case in visit()), 681 // but the array blowing the limit didn't contain elements beyond the 682 // provided-for index range, go to dictionary mode now. 683 if (fast_elements() && 684 index_offset_ > 685 static_cast<uint32_t>(FixedArrayBase::cast(*storage_)->length())) { 686 SetDictionaryMode(); 687 } 688 } 689 690 bool exceeds_array_limit() const { 691 return ExceedsLimitField::decode(bit_field_); 692 } 693 694 Handle<JSArray> ToArray() { 695 Handle<JSArray> array = isolate_->factory()->NewJSArray(0); 696 Handle<Object> length = 697 isolate_->factory()->NewNumber(static_cast<double>(index_offset_)); 698 Handle<Map> map = JSObject::GetElementsTransitionMap( 699 array, fast_elements() ? FAST_HOLEY_ELEMENTS : DICTIONARY_ELEMENTS); 700 array->set_map(*map); 701 array->set_length(*length); 702 array->set_elements(*storage_); 703 return array; 704 } 705 706 private: 707 // Convert storage to dictionary mode. 708 void SetDictionaryMode() { 709 DCHECK(fast_elements()); 710 Handle<FixedArray> current_storage(*storage_); 711 Handle<SeededNumberDictionary> slow_storage( 712 SeededNumberDictionary::New(isolate_, current_storage->length())); 713 uint32_t current_length = static_cast<uint32_t>(current_storage->length()); 714 for (uint32_t i = 0; i < current_length; i++) { 715 HandleScope loop_scope(isolate_); 716 Handle<Object> element(current_storage->get(i), isolate_); 717 if (!element->IsTheHole()) { 718 // The object holding this backing store has just been allocated, so 719 // it cannot yet be used as a prototype. 720 Handle<SeededNumberDictionary> new_storage = 721 SeededNumberDictionary::AtNumberPut(slow_storage, i, element, 722 false); 723 if (!new_storage.is_identical_to(slow_storage)) { 724 slow_storage = loop_scope.CloseAndEscape(new_storage); 725 } 726 } 727 } 728 clear_storage(); 729 set_storage(*slow_storage); 730 set_fast_elements(false); 731 } 732 733 inline void clear_storage() { 734 GlobalHandles::Destroy(Handle<Object>::cast(storage_).location()); 735 } 736 737 inline void set_storage(FixedArray* storage) { 738 storage_ = 739 Handle<FixedArray>::cast(isolate_->global_handles()->Create(storage)); 740 } 741 742 class FastElementsField : public BitField<bool, 0, 1> {}; 743 class ExceedsLimitField : public BitField<bool, 1, 1> {}; 744 745 bool fast_elements() const { return FastElementsField::decode(bit_field_); } 746 void set_fast_elements(bool fast) { 747 bit_field_ = FastElementsField::update(bit_field_, fast); 748 } 749 void set_exceeds_array_limit(bool exceeds) { 750 bit_field_ = ExceedsLimitField::update(bit_field_, exceeds); 751 } 752 753 Isolate* isolate_; 754 Handle<FixedArray> storage_; // Always a global handle. 755 // Index after last seen index. Always less than or equal to 756 // JSObject::kMaxElementCount. 757 uint32_t index_offset_; 758 uint32_t bit_field_; 759 }; 760 761 762 uint32_t EstimateElementCount(Handle<JSArray> array) { 763 uint32_t length = static_cast<uint32_t>(array->length()->Number()); 764 int element_count = 0; 765 switch (array->GetElementsKind()) { 766 case FAST_SMI_ELEMENTS: 767 case FAST_HOLEY_SMI_ELEMENTS: 768 case FAST_ELEMENTS: 769 case FAST_HOLEY_ELEMENTS: { 770 // Fast elements can't have lengths that are not representable by 771 // a 32-bit signed integer. 772 DCHECK(static_cast<int32_t>(FixedArray::kMaxLength) >= 0); 773 int fast_length = static_cast<int>(length); 774 Handle<FixedArray> elements(FixedArray::cast(array->elements())); 775 for (int i = 0; i < fast_length; i++) { 776 if (!elements->get(i)->IsTheHole()) element_count++; 777 } 778 break; 779 } 780 case FAST_DOUBLE_ELEMENTS: 781 case FAST_HOLEY_DOUBLE_ELEMENTS: { 782 // Fast elements can't have lengths that are not representable by 783 // a 32-bit signed integer. 784 DCHECK(static_cast<int32_t>(FixedDoubleArray::kMaxLength) >= 0); 785 int fast_length = static_cast<int>(length); 786 if (array->elements()->IsFixedArray()) { 787 DCHECK(FixedArray::cast(array->elements())->length() == 0); 788 break; 789 } 790 Handle<FixedDoubleArray> elements( 791 FixedDoubleArray::cast(array->elements())); 792 for (int i = 0; i < fast_length; i++) { 793 if (!elements->is_the_hole(i)) element_count++; 794 } 795 break; 796 } 797 case DICTIONARY_ELEMENTS: { 798 Handle<SeededNumberDictionary> dictionary( 799 SeededNumberDictionary::cast(array->elements())); 800 int capacity = dictionary->Capacity(); 801 for (int i = 0; i < capacity; i++) { 802 Handle<Object> key(dictionary->KeyAt(i), array->GetIsolate()); 803 if (dictionary->IsKey(*key)) { 804 element_count++; 805 } 806 } 807 break; 808 } 809 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: 810 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: 811 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) case TYPE##_ELEMENTS: 812 813 TYPED_ARRAYS(TYPED_ARRAY_CASE) 814 #undef TYPED_ARRAY_CASE 815 // External arrays are always dense. 816 return length; 817 } 818 // As an estimate, we assume that the prototype doesn't contain any 819 // inherited elements. 820 return element_count; 821 } 822 823 824 template <class ExternalArrayClass, class ElementType> 825 void IterateTypedArrayElements(Isolate* isolate, Handle<JSObject> receiver, 826 bool elements_are_ints, 827 bool elements_are_guaranteed_smis, 828 ArrayConcatVisitor* visitor) { 829 Handle<ExternalArrayClass> array( 830 ExternalArrayClass::cast(receiver->elements())); 831 uint32_t len = static_cast<uint32_t>(array->length()); 832 833 DCHECK(visitor != NULL); 834 if (elements_are_ints) { 835 if (elements_are_guaranteed_smis) { 836 for (uint32_t j = 0; j < len; j++) { 837 HandleScope loop_scope(isolate); 838 Handle<Smi> e(Smi::FromInt(static_cast<int>(array->get_scalar(j))), 839 isolate); 840 visitor->visit(j, e); 841 } 842 } else { 843 for (uint32_t j = 0; j < len; j++) { 844 HandleScope loop_scope(isolate); 845 int64_t val = static_cast<int64_t>(array->get_scalar(j)); 846 if (Smi::IsValid(static_cast<intptr_t>(val))) { 847 Handle<Smi> e(Smi::FromInt(static_cast<int>(val)), isolate); 848 visitor->visit(j, e); 849 } else { 850 Handle<Object> e = 851 isolate->factory()->NewNumber(static_cast<ElementType>(val)); 852 visitor->visit(j, e); 853 } 854 } 855 } 856 } else { 857 for (uint32_t j = 0; j < len; j++) { 858 HandleScope loop_scope(isolate); 859 Handle<Object> e = isolate->factory()->NewNumber(array->get_scalar(j)); 860 visitor->visit(j, e); 861 } 862 } 863 } 864 865 866 // Used for sorting indices in a List<uint32_t>. 867 int compareUInt32(const uint32_t* ap, const uint32_t* bp) { 868 uint32_t a = *ap; 869 uint32_t b = *bp; 870 return (a == b) ? 0 : (a < b) ? -1 : 1; 871 } 872 873 874 void CollectElementIndices(Handle<JSObject> object, uint32_t range, 875 List<uint32_t>* indices) { 876 Isolate* isolate = object->GetIsolate(); 877 ElementsKind kind = object->GetElementsKind(); 878 switch (kind) { 879 case FAST_SMI_ELEMENTS: 880 case FAST_ELEMENTS: 881 case FAST_HOLEY_SMI_ELEMENTS: 882 case FAST_HOLEY_ELEMENTS: { 883 Handle<FixedArray> elements(FixedArray::cast(object->elements())); 884 uint32_t length = static_cast<uint32_t>(elements->length()); 885 if (range < length) length = range; 886 for (uint32_t i = 0; i < length; i++) { 887 if (!elements->get(i)->IsTheHole()) { 888 indices->Add(i); 889 } 890 } 891 break; 892 } 893 case FAST_HOLEY_DOUBLE_ELEMENTS: 894 case FAST_DOUBLE_ELEMENTS: { 895 if (object->elements()->IsFixedArray()) { 896 DCHECK(object->elements()->length() == 0); 897 break; 898 } 899 Handle<FixedDoubleArray> elements( 900 FixedDoubleArray::cast(object->elements())); 901 uint32_t length = static_cast<uint32_t>(elements->length()); 902 if (range < length) length = range; 903 for (uint32_t i = 0; i < length; i++) { 904 if (!elements->is_the_hole(i)) { 905 indices->Add(i); 906 } 907 } 908 break; 909 } 910 case DICTIONARY_ELEMENTS: { 911 Handle<SeededNumberDictionary> dict( 912 SeededNumberDictionary::cast(object->elements())); 913 uint32_t capacity = dict->Capacity(); 914 for (uint32_t j = 0; j < capacity; j++) { 915 HandleScope loop_scope(isolate); 916 Handle<Object> k(dict->KeyAt(j), isolate); 917 if (dict->IsKey(*k)) { 918 DCHECK(k->IsNumber()); 919 uint32_t index = static_cast<uint32_t>(k->Number()); 920 if (index < range) { 921 indices->Add(index); 922 } 923 } 924 } 925 break; 926 } 927 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) case TYPE##_ELEMENTS: 928 929 TYPED_ARRAYS(TYPED_ARRAY_CASE) 930 #undef TYPED_ARRAY_CASE 931 { 932 uint32_t length = static_cast<uint32_t>( 933 FixedArrayBase::cast(object->elements())->length()); 934 if (range <= length) { 935 length = range; 936 // We will add all indices, so we might as well clear it first 937 // and avoid duplicates. 938 indices->Clear(); 939 } 940 for (uint32_t i = 0; i < length; i++) { 941 indices->Add(i); 942 } 943 if (length == range) return; // All indices accounted for already. 944 break; 945 } 946 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: 947 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: { 948 ElementsAccessor* accessor = object->GetElementsAccessor(); 949 for (uint32_t i = 0; i < range; i++) { 950 if (accessor->HasElement(object, i)) { 951 indices->Add(i); 952 } 953 } 954 break; 955 } 956 } 957 958 PrototypeIterator iter(isolate, object); 959 if (!iter.IsAtEnd()) { 960 // The prototype will usually have no inherited element indices, 961 // but we have to check. 962 CollectElementIndices(PrototypeIterator::GetCurrent<JSObject>(iter), range, 963 indices); 964 } 965 } 966 967 968 bool IterateElementsSlow(Isolate* isolate, Handle<JSReceiver> receiver, 969 uint32_t length, ArrayConcatVisitor* visitor) { 970 for (uint32_t i = 0; i < length; ++i) { 971 HandleScope loop_scope(isolate); 972 Maybe<bool> maybe = JSReceiver::HasElement(receiver, i); 973 if (!maybe.IsJust()) return false; 974 if (maybe.FromJust()) { 975 Handle<Object> element_value; 976 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, element_value, 977 Object::GetElement(isolate, receiver, i), 978 false); 979 visitor->visit(i, element_value); 980 } 981 } 982 visitor->increase_index_offset(length); 983 return true; 984 } 985 986 987 /** 988 * A helper function that visits "array" elements of a JSReceiver in numerical 989 * order. 990 * 991 * The visitor argument called for each existing element in the array 992 * with the element index and the element's value. 993 * Afterwards it increments the base-index of the visitor by the array 994 * length. 995 * Returns false if any access threw an exception, otherwise true. 996 */ 997 bool IterateElements(Isolate* isolate, Handle<JSReceiver> receiver, 998 ArrayConcatVisitor* visitor) { 999 uint32_t length = 0; 1000 1001 if (receiver->IsJSArray()) { 1002 Handle<JSArray> array = Handle<JSArray>::cast(receiver); 1003 length = static_cast<uint32_t>(array->length()->Number()); 1004 } else { 1005 Handle<Object> val; 1006 Handle<Object> key = isolate->factory()->length_string(); 1007 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 1008 isolate, val, Runtime::GetObjectProperty(isolate, receiver, key), 1009 false); 1010 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, val, 1011 Object::ToLength(isolate, val), false); 1012 // TODO(caitp): Support larger element indexes (up to 2^53-1). 1013 if (!val->ToUint32(&length)) { 1014 length = 0; 1015 } 1016 } 1017 1018 if (!(receiver->IsJSArray() || receiver->IsJSTypedArray())) { 1019 // For classes which are not known to be safe to access via elements alone, 1020 // use the slow case. 1021 return IterateElementsSlow(isolate, receiver, length, visitor); 1022 } 1023 Handle<JSObject> array = Handle<JSObject>::cast(receiver); 1024 1025 switch (array->GetElementsKind()) { 1026 case FAST_SMI_ELEMENTS: 1027 case FAST_ELEMENTS: 1028 case FAST_HOLEY_SMI_ELEMENTS: 1029 case FAST_HOLEY_ELEMENTS: { 1030 // Run through the elements FixedArray and use HasElement and GetElement 1031 // to check the prototype for missing elements. 1032 Handle<FixedArray> elements(FixedArray::cast(array->elements())); 1033 int fast_length = static_cast<int>(length); 1034 DCHECK(fast_length <= elements->length()); 1035 for (int j = 0; j < fast_length; j++) { 1036 HandleScope loop_scope(isolate); 1037 Handle<Object> element_value(elements->get(j), isolate); 1038 if (!element_value->IsTheHole()) { 1039 visitor->visit(j, element_value); 1040 } else { 1041 Maybe<bool> maybe = JSReceiver::HasElement(array, j); 1042 if (!maybe.IsJust()) return false; 1043 if (maybe.FromJust()) { 1044 // Call GetElement on array, not its prototype, or getters won't 1045 // have the correct receiver. 1046 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 1047 isolate, element_value, Object::GetElement(isolate, array, j), 1048 false); 1049 visitor->visit(j, element_value); 1050 } 1051 } 1052 } 1053 break; 1054 } 1055 case FAST_HOLEY_DOUBLE_ELEMENTS: 1056 case FAST_DOUBLE_ELEMENTS: { 1057 // Empty array is FixedArray but not FixedDoubleArray. 1058 if (length == 0) break; 1059 // Run through the elements FixedArray and use HasElement and GetElement 1060 // to check the prototype for missing elements. 1061 if (array->elements()->IsFixedArray()) { 1062 DCHECK(array->elements()->length() == 0); 1063 break; 1064 } 1065 Handle<FixedDoubleArray> elements( 1066 FixedDoubleArray::cast(array->elements())); 1067 int fast_length = static_cast<int>(length); 1068 DCHECK(fast_length <= elements->length()); 1069 for (int j = 0; j < fast_length; j++) { 1070 HandleScope loop_scope(isolate); 1071 if (!elements->is_the_hole(j)) { 1072 double double_value = elements->get_scalar(j); 1073 Handle<Object> element_value = 1074 isolate->factory()->NewNumber(double_value); 1075 visitor->visit(j, element_value); 1076 } else { 1077 Maybe<bool> maybe = JSReceiver::HasElement(array, j); 1078 if (!maybe.IsJust()) return false; 1079 if (maybe.FromJust()) { 1080 // Call GetElement on array, not its prototype, or getters won't 1081 // have the correct receiver. 1082 Handle<Object> element_value; 1083 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 1084 isolate, element_value, Object::GetElement(isolate, array, j), 1085 false); 1086 visitor->visit(j, element_value); 1087 } 1088 } 1089 } 1090 break; 1091 } 1092 case DICTIONARY_ELEMENTS: { 1093 // CollectElementIndices() can't be called when there's a JSProxy 1094 // on the prototype chain. 1095 for (PrototypeIterator iter(isolate, array); !iter.IsAtEnd(); 1096 iter.Advance()) { 1097 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { 1098 return IterateElementsSlow(isolate, array, length, visitor); 1099 } 1100 } 1101 Handle<SeededNumberDictionary> dict(array->element_dictionary()); 1102 List<uint32_t> indices(dict->Capacity() / 2); 1103 // Collect all indices in the object and the prototypes less 1104 // than length. This might introduce duplicates in the indices list. 1105 CollectElementIndices(array, length, &indices); 1106 indices.Sort(&compareUInt32); 1107 int j = 0; 1108 int n = indices.length(); 1109 while (j < n) { 1110 HandleScope loop_scope(isolate); 1111 uint32_t index = indices[j]; 1112 Handle<Object> element; 1113 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 1114 isolate, element, Object::GetElement(isolate, array, index), false); 1115 visitor->visit(index, element); 1116 // Skip to next different index (i.e., omit duplicates). 1117 do { 1118 j++; 1119 } while (j < n && indices[j] == index); 1120 } 1121 break; 1122 } 1123 case UINT8_CLAMPED_ELEMENTS: { 1124 Handle<FixedUint8ClampedArray> pixels( 1125 FixedUint8ClampedArray::cast(array->elements())); 1126 for (uint32_t j = 0; j < length; j++) { 1127 Handle<Smi> e(Smi::FromInt(pixels->get_scalar(j)), isolate); 1128 visitor->visit(j, e); 1129 } 1130 break; 1131 } 1132 case INT8_ELEMENTS: { 1133 IterateTypedArrayElements<FixedInt8Array, int8_t>(isolate, array, true, 1134 true, visitor); 1135 break; 1136 } 1137 case UINT8_ELEMENTS: { 1138 IterateTypedArrayElements<FixedUint8Array, uint8_t>(isolate, array, true, 1139 true, visitor); 1140 break; 1141 } 1142 case INT16_ELEMENTS: { 1143 IterateTypedArrayElements<FixedInt16Array, int16_t>(isolate, array, true, 1144 true, visitor); 1145 break; 1146 } 1147 case UINT16_ELEMENTS: { 1148 IterateTypedArrayElements<FixedUint16Array, uint16_t>( 1149 isolate, array, true, true, visitor); 1150 break; 1151 } 1152 case INT32_ELEMENTS: { 1153 IterateTypedArrayElements<FixedInt32Array, int32_t>(isolate, array, true, 1154 false, visitor); 1155 break; 1156 } 1157 case UINT32_ELEMENTS: { 1158 IterateTypedArrayElements<FixedUint32Array, uint32_t>( 1159 isolate, array, true, false, visitor); 1160 break; 1161 } 1162 case FLOAT32_ELEMENTS: { 1163 IterateTypedArrayElements<FixedFloat32Array, float>(isolate, array, false, 1164 false, visitor); 1165 break; 1166 } 1167 case FLOAT64_ELEMENTS: { 1168 IterateTypedArrayElements<FixedFloat64Array, double>( 1169 isolate, array, false, false, visitor); 1170 break; 1171 } 1172 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: 1173 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: { 1174 for (uint32_t index = 0; index < length; index++) { 1175 HandleScope loop_scope(isolate); 1176 Handle<Object> element; 1177 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 1178 isolate, element, Object::GetElement(isolate, array, index), false); 1179 visitor->visit(index, element); 1180 } 1181 break; 1182 } 1183 } 1184 visitor->increase_index_offset(length); 1185 return true; 1186 } 1187 1188 1189 bool HasConcatSpreadableModifier(Isolate* isolate, Handle<JSArray> obj) { 1190 DCHECK(isolate->IsFastArrayConstructorPrototypeChainIntact()); 1191 if (!FLAG_harmony_concat_spreadable) return false; 1192 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol()); 1193 Maybe<bool> maybe = JSReceiver::HasProperty(obj, key); 1194 return maybe.FromMaybe(false); 1195 } 1196 1197 1198 static Maybe<bool> IsConcatSpreadable(Isolate* isolate, Handle<Object> obj) { 1199 HandleScope handle_scope(isolate); 1200 if (!obj->IsJSReceiver()) return Just(false); 1201 if (FLAG_harmony_concat_spreadable) { 1202 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol()); 1203 Handle<Object> value; 1204 MaybeHandle<Object> maybeValue = 1205 i::Runtime::GetObjectProperty(isolate, obj, key); 1206 if (!maybeValue.ToHandle(&value)) return Nothing<bool>(); 1207 if (!value->IsUndefined()) return Just(value->BooleanValue()); 1208 } 1209 return Object::IsArray(obj); 1210 } 1211 1212 1213 Object* Slow_ArrayConcat(Arguments* args, Isolate* isolate) { 1214 int argument_count = args->length(); 1215 1216 // Pass 1: estimate the length and number of elements of the result. 1217 // The actual length can be larger if any of the arguments have getters 1218 // that mutate other arguments (but will otherwise be precise). 1219 // The number of elements is precise if there are no inherited elements. 1220 1221 ElementsKind kind = FAST_SMI_ELEMENTS; 1222 1223 uint32_t estimate_result_length = 0; 1224 uint32_t estimate_nof_elements = 0; 1225 for (int i = 0; i < argument_count; i++) { 1226 HandleScope loop_scope(isolate); 1227 Handle<Object> obj((*args)[i], isolate); 1228 uint32_t length_estimate; 1229 uint32_t element_estimate; 1230 if (obj->IsJSArray()) { 1231 Handle<JSArray> array(Handle<JSArray>::cast(obj)); 1232 length_estimate = static_cast<uint32_t>(array->length()->Number()); 1233 if (length_estimate != 0) { 1234 ElementsKind array_kind = 1235 GetPackedElementsKind(array->map()->elements_kind()); 1236 kind = GetMoreGeneralElementsKind(kind, array_kind); 1237 } 1238 element_estimate = EstimateElementCount(array); 1239 } else { 1240 if (obj->IsHeapObject()) { 1241 if (obj->IsNumber()) { 1242 kind = GetMoreGeneralElementsKind(kind, FAST_DOUBLE_ELEMENTS); 1243 } else { 1244 kind = GetMoreGeneralElementsKind(kind, FAST_ELEMENTS); 1245 } 1246 } 1247 length_estimate = 1; 1248 element_estimate = 1; 1249 } 1250 // Avoid overflows by capping at kMaxElementCount. 1251 if (JSObject::kMaxElementCount - estimate_result_length < length_estimate) { 1252 estimate_result_length = JSObject::kMaxElementCount; 1253 } else { 1254 estimate_result_length += length_estimate; 1255 } 1256 if (JSObject::kMaxElementCount - estimate_nof_elements < element_estimate) { 1257 estimate_nof_elements = JSObject::kMaxElementCount; 1258 } else { 1259 estimate_nof_elements += element_estimate; 1260 } 1261 } 1262 1263 // If estimated number of elements is more than half of length, a 1264 // fixed array (fast case) is more time and space-efficient than a 1265 // dictionary. 1266 bool fast_case = (estimate_nof_elements * 2) >= estimate_result_length; 1267 1268 if (fast_case && kind == FAST_DOUBLE_ELEMENTS) { 1269 Handle<FixedArrayBase> storage = 1270 isolate->factory()->NewFixedDoubleArray(estimate_result_length); 1271 int j = 0; 1272 bool failure = false; 1273 if (estimate_result_length > 0) { 1274 Handle<FixedDoubleArray> double_storage = 1275 Handle<FixedDoubleArray>::cast(storage); 1276 for (int i = 0; i < argument_count; i++) { 1277 Handle<Object> obj((*args)[i], isolate); 1278 if (obj->IsSmi()) { 1279 double_storage->set(j, Smi::cast(*obj)->value()); 1280 j++; 1281 } else if (obj->IsNumber()) { 1282 double_storage->set(j, obj->Number()); 1283 j++; 1284 } else { 1285 JSArray* array = JSArray::cast(*obj); 1286 uint32_t length = static_cast<uint32_t>(array->length()->Number()); 1287 switch (array->map()->elements_kind()) { 1288 case FAST_HOLEY_DOUBLE_ELEMENTS: 1289 case FAST_DOUBLE_ELEMENTS: { 1290 // Empty array is FixedArray but not FixedDoubleArray. 1291 if (length == 0) break; 1292 FixedDoubleArray* elements = 1293 FixedDoubleArray::cast(array->elements()); 1294 for (uint32_t i = 0; i < length; i++) { 1295 if (elements->is_the_hole(i)) { 1296 // TODO(jkummerow/verwaest): We could be a bit more clever 1297 // here: Check if there are no elements/getters on the 1298 // prototype chain, and if so, allow creation of a holey 1299 // result array. 1300 // Same thing below (holey smi case). 1301 failure = true; 1302 break; 1303 } 1304 double double_value = elements->get_scalar(i); 1305 double_storage->set(j, double_value); 1306 j++; 1307 } 1308 break; 1309 } 1310 case FAST_HOLEY_SMI_ELEMENTS: 1311 case FAST_SMI_ELEMENTS: { 1312 FixedArray* elements(FixedArray::cast(array->elements())); 1313 for (uint32_t i = 0; i < length; i++) { 1314 Object* element = elements->get(i); 1315 if (element->IsTheHole()) { 1316 failure = true; 1317 break; 1318 } 1319 int32_t int_value = Smi::cast(element)->value(); 1320 double_storage->set(j, int_value); 1321 j++; 1322 } 1323 break; 1324 } 1325 case FAST_HOLEY_ELEMENTS: 1326 case FAST_ELEMENTS: 1327 case DICTIONARY_ELEMENTS: 1328 DCHECK_EQ(0u, length); 1329 break; 1330 default: 1331 UNREACHABLE(); 1332 } 1333 } 1334 if (failure) break; 1335 } 1336 } 1337 if (!failure) { 1338 Handle<JSArray> array = isolate->factory()->NewJSArray(0); 1339 Smi* length = Smi::FromInt(j); 1340 Handle<Map> map; 1341 map = JSObject::GetElementsTransitionMap(array, kind); 1342 array->set_map(*map); 1343 array->set_length(length); 1344 array->set_elements(*storage); 1345 return *array; 1346 } 1347 // In case of failure, fall through. 1348 } 1349 1350 Handle<FixedArray> storage; 1351 if (fast_case) { 1352 // The backing storage array must have non-existing elements to preserve 1353 // holes across concat operations. 1354 storage = 1355 isolate->factory()->NewFixedArrayWithHoles(estimate_result_length); 1356 } else { 1357 // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate 1358 uint32_t at_least_space_for = 1359 estimate_nof_elements + (estimate_nof_elements >> 2); 1360 storage = Handle<FixedArray>::cast( 1361 SeededNumberDictionary::New(isolate, at_least_space_for)); 1362 } 1363 1364 ArrayConcatVisitor visitor(isolate, storage, fast_case); 1365 1366 for (int i = 0; i < argument_count; i++) { 1367 Handle<Object> obj((*args)[i], isolate); 1368 Maybe<bool> spreadable = IsConcatSpreadable(isolate, obj); 1369 MAYBE_RETURN(spreadable, isolate->heap()->exception()); 1370 if (spreadable.FromJust()) { 1371 Handle<JSReceiver> object = Handle<JSReceiver>::cast(obj); 1372 if (!IterateElements(isolate, object, &visitor)) { 1373 return isolate->heap()->exception(); 1374 } 1375 } else { 1376 visitor.visit(0, obj); 1377 visitor.increase_index_offset(1); 1378 } 1379 } 1380 1381 if (visitor.exceeds_array_limit()) { 1382 THROW_NEW_ERROR_RETURN_FAILURE( 1383 isolate, NewRangeError(MessageTemplate::kInvalidArrayLength)); 1384 } 1385 return *visitor.ToArray(); 1386 } 1387 1388 1389 MaybeHandle<JSArray> Fast_ArrayConcat(Isolate* isolate, Arguments* args) { 1390 if (!isolate->IsFastArrayConstructorPrototypeChainIntact()) { 1391 return MaybeHandle<JSArray>(); 1392 } 1393 int n_arguments = args->length(); 1394 int result_len = 0; 1395 { 1396 DisallowHeapAllocation no_gc; 1397 Object* array_proto = isolate->array_function()->prototype(); 1398 // Iterate through all the arguments performing checks 1399 // and calculating total length. 1400 for (int i = 0; i < n_arguments; i++) { 1401 Object* arg = (*args)[i]; 1402 if (!arg->IsJSArray()) return MaybeHandle<JSArray>(); 1403 Handle<JSArray> array(JSArray::cast(arg), isolate); 1404 if (!array->HasFastElements()) return MaybeHandle<JSArray>(); 1405 PrototypeIterator iter(isolate, arg); 1406 if (iter.GetCurrent() != array_proto) return MaybeHandle<JSArray>(); 1407 if (HasConcatSpreadableModifier(isolate, array)) { 1408 return MaybeHandle<JSArray>(); 1409 } 1410 int len = Smi::cast(array->length())->value(); 1411 1412 // We shouldn't overflow when adding another len. 1413 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2); 1414 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt); 1415 USE(kHalfOfMaxInt); 1416 result_len += len; 1417 DCHECK(result_len >= 0); 1418 // Throw an Error if we overflow the FixedArray limits 1419 if (FixedArray::kMaxLength < result_len) { 1420 THROW_NEW_ERROR(isolate, 1421 NewRangeError(MessageTemplate::kInvalidArrayLength), 1422 JSArray); 1423 } 1424 } 1425 } 1426 return ElementsAccessor::Concat(isolate, args, n_arguments); 1427 } 1428 1429 } // namespace 1430 1431 // ES6 22.1.3.1 Array.prototype.concat 1432 BUILTIN(ArrayConcat) { 1433 HandleScope scope(isolate); 1434 1435 Handle<Object> receiver; 1436 if (!Object::ToObject(isolate, handle(args[0], isolate)) 1437 .ToHandle(&receiver)) { 1438 THROW_NEW_ERROR_RETURN_FAILURE( 1439 isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined, 1440 isolate->factory()->NewStringFromAsciiChecked( 1441 "Array.prototype.concat"))); 1442 } 1443 args[0] = *receiver; 1444 1445 Handle<JSArray> result_array; 1446 if (Fast_ArrayConcat(isolate, &args).ToHandle(&result_array)) { 1447 return *result_array; 1448 } 1449 if (isolate->has_pending_exception()) return isolate->heap()->exception(); 1450 return Slow_ArrayConcat(&args, isolate); 1451 } 1452 1453 1454 // ES6 22.1.2.2 Array.isArray 1455 BUILTIN(ArrayIsArray) { 1456 HandleScope scope(isolate); 1457 DCHECK_EQ(2, args.length()); 1458 Handle<Object> object = args.at<Object>(1); 1459 Maybe<bool> result = Object::IsArray(object); 1460 MAYBE_RETURN(result, isolate->heap()->exception()); 1461 return *isolate->factory()->ToBoolean(result.FromJust()); 1462 } 1463 1464 1465 // ES6 19.1.2.1 Object.assign 1466 BUILTIN(ObjectAssign) { 1467 HandleScope scope(isolate); 1468 Handle<Object> target = args.atOrUndefined(isolate, 1); 1469 1470 // 1. Let to be ? ToObject(target). 1471 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, target, 1472 Execution::ToObject(isolate, target)); 1473 Handle<JSReceiver> to = Handle<JSReceiver>::cast(target); 1474 // 2. If only one argument was passed, return to. 1475 if (args.length() == 2) return *to; 1476 // 3. Let sources be the List of argument values starting with the 1477 // second argument. 1478 // 4. For each element nextSource of sources, in ascending index order, 1479 for (int i = 2; i < args.length(); ++i) { 1480 Handle<Object> next_source = args.at<Object>(i); 1481 // 4a. If nextSource is undefined or null, let keys be an empty List. 1482 if (next_source->IsUndefined() || next_source->IsNull()) continue; 1483 // 4b. Else, 1484 // 4b i. Let from be ToObject(nextSource). 1485 Handle<JSReceiver> from = 1486 Object::ToObject(isolate, next_source).ToHandleChecked(); 1487 // 4b ii. Let keys be ? from.[[OwnPropertyKeys]](). 1488 Handle<FixedArray> keys; 1489 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1490 isolate, keys, JSReceiver::GetKeys(from, JSReceiver::OWN_ONLY, 1491 ALL_PROPERTIES, KEEP_NUMBERS)); 1492 // 4c. Repeat for each element nextKey of keys in List order, 1493 for (int j = 0; j < keys->length(); ++j) { 1494 Handle<Object> next_key(keys->get(j), isolate); 1495 // 4c i. Let desc be ? from.[[GetOwnProperty]](nextKey). 1496 PropertyDescriptor desc; 1497 Maybe<bool> found = 1498 JSReceiver::GetOwnPropertyDescriptor(isolate, from, next_key, &desc); 1499 if (found.IsNothing()) return isolate->heap()->exception(); 1500 // 4c ii. If desc is not undefined and desc.[[Enumerable]] is true, then 1501 if (found.FromJust() && desc.enumerable()) { 1502 // 4c ii 1. Let propValue be ? Get(from, nextKey). 1503 Handle<Object> prop_value; 1504 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1505 isolate, prop_value, 1506 Runtime::GetObjectProperty(isolate, from, next_key, STRICT)); 1507 // 4c ii 2. Let status be ? Set(to, nextKey, propValue, true). 1508 Handle<Object> status; 1509 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1510 isolate, status, Runtime::SetObjectProperty(isolate, to, next_key, 1511 prop_value, STRICT)); 1512 } 1513 } 1514 } 1515 // 5. Return to. 1516 return *to; 1517 } 1518 1519 1520 // ES6 section 19.1.2.2 Object.create ( O [ , Properties ] ) 1521 BUILTIN(ObjectCreate) { 1522 HandleScope scope(isolate); 1523 Handle<Object> prototype = args.atOrUndefined(isolate, 1); 1524 if (!prototype->IsNull() && !prototype->IsJSReceiver()) { 1525 THROW_NEW_ERROR_RETURN_FAILURE( 1526 isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, prototype)); 1527 } 1528 1529 // Generate the map with the specified {prototype} based on the Object 1530 // function's initial map from the current native context. 1531 // TODO(bmeurer): Use a dedicated cache for Object.create; think about 1532 // slack tracking for Object.create. 1533 Handle<Map> map(isolate->native_context()->object_function()->initial_map(), 1534 isolate); 1535 if (map->prototype() != *prototype) { 1536 map = Map::TransitionToPrototype(map, prototype, FAST_PROTOTYPE); 1537 } 1538 1539 // Actually allocate the object. 1540 Handle<JSObject> object = isolate->factory()->NewJSObjectFromMap(map); 1541 1542 // Define the properties if properties was specified and is not undefined. 1543 Handle<Object> properties = args.atOrUndefined(isolate, 2); 1544 if (!properties->IsUndefined()) { 1545 RETURN_FAILURE_ON_EXCEPTION( 1546 isolate, JSReceiver::DefineProperties(isolate, object, properties)); 1547 } 1548 1549 return *object; 1550 } 1551 1552 1553 // ES6 section 19.1.2.5 Object.freeze ( O ) 1554 BUILTIN(ObjectFreeze) { 1555 HandleScope scope(isolate); 1556 Handle<Object> object = args.atOrUndefined(isolate, 1); 1557 if (object->IsJSReceiver()) { 1558 MAYBE_RETURN(JSReceiver::SetIntegrityLevel(Handle<JSReceiver>::cast(object), 1559 FROZEN, Object::THROW_ON_ERROR), 1560 isolate->heap()->exception()); 1561 } 1562 return *object; 1563 } 1564 1565 1566 // ES6 section 19.1.2.11 Object.isExtensible ( O ) 1567 BUILTIN(ObjectIsExtensible) { 1568 HandleScope scope(isolate); 1569 Handle<Object> object = args.atOrUndefined(isolate, 1); 1570 Maybe<bool> result = 1571 object->IsJSReceiver() 1572 ? JSReceiver::IsExtensible(Handle<JSReceiver>::cast(object)) 1573 : Just(false); 1574 MAYBE_RETURN(result, isolate->heap()->exception()); 1575 return isolate->heap()->ToBoolean(result.FromJust()); 1576 } 1577 1578 1579 // ES6 section 19.1.2.12 Object.isFrozen ( O ) 1580 BUILTIN(ObjectIsFrozen) { 1581 HandleScope scope(isolate); 1582 Handle<Object> object = args.atOrUndefined(isolate, 1); 1583 Maybe<bool> result = object->IsJSReceiver() 1584 ? JSReceiver::TestIntegrityLevel( 1585 Handle<JSReceiver>::cast(object), FROZEN) 1586 : Just(true); 1587 MAYBE_RETURN(result, isolate->heap()->exception()); 1588 return isolate->heap()->ToBoolean(result.FromJust()); 1589 } 1590 1591 1592 // ES6 section 19.1.2.13 Object.isSealed ( O ) 1593 BUILTIN(ObjectIsSealed) { 1594 HandleScope scope(isolate); 1595 Handle<Object> object = args.atOrUndefined(isolate, 1); 1596 Maybe<bool> result = object->IsJSReceiver() 1597 ? JSReceiver::TestIntegrityLevel( 1598 Handle<JSReceiver>::cast(object), SEALED) 1599 : Just(true); 1600 MAYBE_RETURN(result, isolate->heap()->exception()); 1601 return isolate->heap()->ToBoolean(result.FromJust()); 1602 } 1603 1604 1605 // ES6 section 19.1.2.14 Object.keys ( O ) 1606 BUILTIN(ObjectKeys) { 1607 HandleScope scope(isolate); 1608 Handle<Object> object = args.atOrUndefined(isolate, 1); 1609 Handle<JSReceiver> receiver; 1610 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver, 1611 Execution::ToObject(isolate, object)); 1612 Handle<FixedArray> keys; 1613 1614 int enum_length = receiver->map()->EnumLength(); 1615 if (enum_length != kInvalidEnumCacheSentinel && 1616 JSObject::cast(*receiver)->elements() == 1617 isolate->heap()->empty_fixed_array()) { 1618 DCHECK(receiver->IsJSObject()); 1619 DCHECK(!JSObject::cast(*receiver)->HasNamedInterceptor()); 1620 DCHECK(!JSObject::cast(*receiver)->IsAccessCheckNeeded()); 1621 DCHECK(!HeapObject::cast(receiver->map()->prototype()) 1622 ->map() 1623 ->is_hidden_prototype()); 1624 DCHECK(JSObject::cast(*receiver)->HasFastProperties()); 1625 if (enum_length == 0) { 1626 keys = isolate->factory()->empty_fixed_array(); 1627 } else { 1628 Handle<FixedArray> cache( 1629 receiver->map()->instance_descriptors()->GetEnumCache()); 1630 keys = isolate->factory()->NewFixedArray(enum_length); 1631 for (int i = 0; i < enum_length; i++) { 1632 keys->set(i, cache->get(i)); 1633 } 1634 } 1635 } else { 1636 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1637 isolate, keys, 1638 JSReceiver::GetKeys(receiver, JSReceiver::OWN_ONLY, ENUMERABLE_STRINGS, 1639 CONVERT_TO_STRING)); 1640 } 1641 return *isolate->factory()->NewJSArrayWithElements(keys, FAST_ELEMENTS); 1642 } 1643 1644 1645 // ES6 section 19.1.2.15 Object.preventExtensions ( O ) 1646 BUILTIN(ObjectPreventExtensions) { 1647 HandleScope scope(isolate); 1648 Handle<Object> object = args.atOrUndefined(isolate, 1); 1649 if (object->IsJSReceiver()) { 1650 MAYBE_RETURN(JSReceiver::PreventExtensions(Handle<JSReceiver>::cast(object), 1651 Object::THROW_ON_ERROR), 1652 isolate->heap()->exception()); 1653 } 1654 return *object; 1655 } 1656 1657 1658 // ES6 section 19.1.2.17 Object.seal ( O ) 1659 BUILTIN(ObjectSeal) { 1660 HandleScope scope(isolate); 1661 Handle<Object> object = args.atOrUndefined(isolate, 1); 1662 if (object->IsJSReceiver()) { 1663 MAYBE_RETURN(JSReceiver::SetIntegrityLevel(Handle<JSReceiver>::cast(object), 1664 SEALED, Object::THROW_ON_ERROR), 1665 isolate->heap()->exception()); 1666 } 1667 return *object; 1668 } 1669 1670 1671 namespace { 1672 1673 bool CodeGenerationFromStringsAllowed(Isolate* isolate, 1674 Handle<Context> context) { 1675 DCHECK(context->allow_code_gen_from_strings()->IsFalse()); 1676 // Check with callback if set. 1677 AllowCodeGenerationFromStringsCallback callback = 1678 isolate->allow_code_gen_callback(); 1679 if (callback == NULL) { 1680 // No callback set and code generation disallowed. 1681 return false; 1682 } else { 1683 // Callback set. Let it decide if code generation is allowed. 1684 VMState<EXTERNAL> state(isolate); 1685 return callback(v8::Utils::ToLocal(context)); 1686 } 1687 } 1688 1689 1690 MaybeHandle<JSFunction> CompileString(Handle<Context> context, 1691 Handle<String> source, 1692 ParseRestriction restriction) { 1693 Isolate* const isolate = context->GetIsolate(); 1694 Handle<Context> native_context(context->native_context(), isolate); 1695 1696 // Check if native context allows code generation from 1697 // strings. Throw an exception if it doesn't. 1698 if (native_context->allow_code_gen_from_strings()->IsFalse() && 1699 !CodeGenerationFromStringsAllowed(isolate, native_context)) { 1700 Handle<Object> error_message = 1701 native_context->ErrorMessageForCodeGenerationFromStrings(); 1702 THROW_NEW_ERROR(isolate, NewEvalError(MessageTemplate::kCodeGenFromStrings, 1703 error_message), 1704 JSFunction); 1705 } 1706 1707 // Compile source string in the native context. 1708 Handle<SharedFunctionInfo> outer_info(native_context->closure()->shared(), 1709 isolate); 1710 return Compiler::GetFunctionFromEval(source, outer_info, native_context, 1711 SLOPPY, restriction, 1712 RelocInfo::kNoPosition); 1713 } 1714 1715 } // namespace 1716 1717 1718 // ES6 section 18.2.1 eval (x) 1719 BUILTIN(GlobalEval) { 1720 HandleScope scope(isolate); 1721 Handle<Object> x = args.atOrUndefined(isolate, 1); 1722 Handle<JSFunction> target = args.target(); 1723 Handle<JSObject> target_global_proxy(target->global_proxy(), isolate); 1724 if (!x->IsString()) return *x; 1725 Handle<JSFunction> function; 1726 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1727 isolate, function, 1728 CompileString(handle(target->native_context(), isolate), 1729 Handle<String>::cast(x), NO_PARSE_RESTRICTION)); 1730 Handle<Object> result; 1731 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1732 isolate, result, 1733 Execution::Call(isolate, function, target_global_proxy, 0, nullptr)); 1734 return *result; 1735 } 1736 1737 1738 // ES6 section 26.1.3 Reflect.defineProperty 1739 BUILTIN(ReflectDefineProperty) { 1740 HandleScope scope(isolate); 1741 DCHECK_EQ(4, args.length()); 1742 Handle<Object> target = args.at<Object>(1); 1743 Handle<Object> key = args.at<Object>(2); 1744 Handle<Object> attributes = args.at<Object>(3); 1745 1746 if (!target->IsJSReceiver()) { 1747 THROW_NEW_ERROR_RETURN_FAILURE( 1748 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject, 1749 isolate->factory()->NewStringFromAsciiChecked( 1750 "Reflect.defineProperty"))); 1751 } 1752 1753 Handle<Name> name; 1754 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name, 1755 Object::ToName(isolate, key)); 1756 1757 PropertyDescriptor desc; 1758 if (!PropertyDescriptor::ToPropertyDescriptor(isolate, attributes, &desc)) { 1759 return isolate->heap()->exception(); 1760 } 1761 1762 Maybe<bool> result = 1763 JSReceiver::DefineOwnProperty(isolate, Handle<JSReceiver>::cast(target), 1764 name, &desc, Object::DONT_THROW); 1765 MAYBE_RETURN(result, isolate->heap()->exception()); 1766 return *isolate->factory()->ToBoolean(result.FromJust()); 1767 } 1768 1769 1770 // ES6 section 26.1.4 Reflect.deleteProperty 1771 BUILTIN(ReflectDeleteProperty) { 1772 HandleScope scope(isolate); 1773 DCHECK_EQ(3, args.length()); 1774 Handle<Object> target = args.at<Object>(1); 1775 Handle<Object> key = args.at<Object>(2); 1776 1777 if (!target->IsJSReceiver()) { 1778 THROW_NEW_ERROR_RETURN_FAILURE( 1779 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject, 1780 isolate->factory()->NewStringFromAsciiChecked( 1781 "Reflect.deleteProperty"))); 1782 } 1783 1784 Handle<Name> name; 1785 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name, 1786 Object::ToName(isolate, key)); 1787 1788 Maybe<bool> result = JSReceiver::DeletePropertyOrElement( 1789 Handle<JSReceiver>::cast(target), name, SLOPPY); 1790 MAYBE_RETURN(result, isolate->heap()->exception()); 1791 return *isolate->factory()->ToBoolean(result.FromJust()); 1792 } 1793 1794 1795 // ES6 section 26.1.6 Reflect.get 1796 BUILTIN(ReflectGet) { 1797 HandleScope scope(isolate); 1798 Handle<Object> target = args.atOrUndefined(isolate, 1); 1799 Handle<Object> key = args.atOrUndefined(isolate, 2); 1800 Handle<Object> receiver = args.length() > 3 ? args.at<Object>(3) : target; 1801 1802 if (!target->IsJSReceiver()) { 1803 THROW_NEW_ERROR_RETURN_FAILURE( 1804 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject, 1805 isolate->factory()->NewStringFromAsciiChecked( 1806 "Reflect.get"))); 1807 } 1808 1809 Handle<Name> name; 1810 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name, 1811 Object::ToName(isolate, key)); 1812 1813 Handle<Object> result; 1814 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1815 isolate, result, Object::GetPropertyOrElement( 1816 Handle<JSReceiver>::cast(target), name, receiver)); 1817 1818 return *result; 1819 } 1820 1821 1822 // ES6 section 26.1.7 Reflect.getOwnPropertyDescriptor 1823 BUILTIN(ReflectGetOwnPropertyDescriptor) { 1824 HandleScope scope(isolate); 1825 DCHECK_EQ(3, args.length()); 1826 Handle<Object> target = args.at<Object>(1); 1827 Handle<Object> key = args.at<Object>(2); 1828 1829 if (!target->IsJSReceiver()) { 1830 THROW_NEW_ERROR_RETURN_FAILURE( 1831 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject, 1832 isolate->factory()->NewStringFromAsciiChecked( 1833 "Reflect.getOwnPropertyDescriptor"))); 1834 } 1835 1836 Handle<Name> name; 1837 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name, 1838 Object::ToName(isolate, key)); 1839 1840 PropertyDescriptor desc; 1841 Maybe<bool> found = JSReceiver::GetOwnPropertyDescriptor( 1842 isolate, Handle<JSReceiver>::cast(target), name, &desc); 1843 MAYBE_RETURN(found, isolate->heap()->exception()); 1844 if (!found.FromJust()) return isolate->heap()->undefined_value(); 1845 return *desc.ToObject(isolate); 1846 } 1847 1848 1849 // ES6 section 26.1.8 Reflect.getPrototypeOf 1850 BUILTIN(ReflectGetPrototypeOf) { 1851 HandleScope scope(isolate); 1852 DCHECK_EQ(2, args.length()); 1853 Handle<Object> target = args.at<Object>(1); 1854 1855 if (!target->IsJSReceiver()) { 1856 THROW_NEW_ERROR_RETURN_FAILURE( 1857 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject, 1858 isolate->factory()->NewStringFromAsciiChecked( 1859 "Reflect.getPrototypeOf"))); 1860 } 1861 Handle<Object> prototype; 1862 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, prototype, 1863 Object::GetPrototype(isolate, target)); 1864 return *prototype; 1865 } 1866 1867 1868 // ES6 section 26.1.9 Reflect.has 1869 BUILTIN(ReflectHas) { 1870 HandleScope scope(isolate); 1871 DCHECK_EQ(3, args.length()); 1872 Handle<Object> target = args.at<Object>(1); 1873 Handle<Object> key = args.at<Object>(2); 1874 1875 if (!target->IsJSReceiver()) { 1876 THROW_NEW_ERROR_RETURN_FAILURE( 1877 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject, 1878 isolate->factory()->NewStringFromAsciiChecked( 1879 "Reflect.has"))); 1880 } 1881 1882 Handle<Name> name; 1883 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name, 1884 Object::ToName(isolate, key)); 1885 1886 Maybe<bool> result = 1887 JSReceiver::HasProperty(Handle<JSReceiver>::cast(target), name); 1888 return result.IsJust() ? *isolate->factory()->ToBoolean(result.FromJust()) 1889 : isolate->heap()->exception(); 1890 } 1891 1892 1893 // ES6 section 26.1.10 Reflect.isExtensible 1894 BUILTIN(ReflectIsExtensible) { 1895 HandleScope scope(isolate); 1896 DCHECK_EQ(2, args.length()); 1897 Handle<Object> target = args.at<Object>(1); 1898 1899 if (!target->IsJSReceiver()) { 1900 THROW_NEW_ERROR_RETURN_FAILURE( 1901 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject, 1902 isolate->factory()->NewStringFromAsciiChecked( 1903 "Reflect.isExtensible"))); 1904 } 1905 1906 Maybe<bool> result = 1907 JSReceiver::IsExtensible(Handle<JSReceiver>::cast(target)); 1908 MAYBE_RETURN(result, isolate->heap()->exception()); 1909 return *isolate->factory()->ToBoolean(result.FromJust()); 1910 } 1911 1912 1913 // ES6 section 26.1.11 Reflect.ownKeys 1914 BUILTIN(ReflectOwnKeys) { 1915 HandleScope scope(isolate); 1916 DCHECK_EQ(2, args.length()); 1917 Handle<Object> target = args.at<Object>(1); 1918 1919 if (!target->IsJSReceiver()) { 1920 THROW_NEW_ERROR_RETURN_FAILURE( 1921 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject, 1922 isolate->factory()->NewStringFromAsciiChecked( 1923 "Reflect.ownKeys"))); 1924 } 1925 1926 Handle<FixedArray> keys; 1927 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1928 isolate, keys, JSReceiver::GetKeys(Handle<JSReceiver>::cast(target), 1929 JSReceiver::OWN_ONLY, ALL_PROPERTIES, 1930 CONVERT_TO_STRING)); 1931 return *isolate->factory()->NewJSArrayWithElements(keys); 1932 } 1933 1934 1935 // ES6 section 26.1.12 Reflect.preventExtensions 1936 BUILTIN(ReflectPreventExtensions) { 1937 HandleScope scope(isolate); 1938 DCHECK_EQ(2, args.length()); 1939 Handle<Object> target = args.at<Object>(1); 1940 1941 if (!target->IsJSReceiver()) { 1942 THROW_NEW_ERROR_RETURN_FAILURE( 1943 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject, 1944 isolate->factory()->NewStringFromAsciiChecked( 1945 "Reflect.preventExtensions"))); 1946 } 1947 1948 Maybe<bool> result = JSReceiver::PreventExtensions( 1949 Handle<JSReceiver>::cast(target), Object::DONT_THROW); 1950 MAYBE_RETURN(result, isolate->heap()->exception()); 1951 return *isolate->factory()->ToBoolean(result.FromJust()); 1952 } 1953 1954 1955 // ES6 section 26.1.13 Reflect.set 1956 BUILTIN(ReflectSet) { 1957 HandleScope scope(isolate); 1958 Handle<Object> target = args.atOrUndefined(isolate, 1); 1959 Handle<Object> key = args.atOrUndefined(isolate, 2); 1960 Handle<Object> value = args.atOrUndefined(isolate, 3); 1961 Handle<Object> receiver = args.length() > 4 ? args.at<Object>(4) : target; 1962 1963 if (!target->IsJSReceiver()) { 1964 THROW_NEW_ERROR_RETURN_FAILURE( 1965 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject, 1966 isolate->factory()->NewStringFromAsciiChecked( 1967 "Reflect.set"))); 1968 } 1969 1970 Handle<Name> name; 1971 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name, 1972 Object::ToName(isolate, key)); 1973 1974 LookupIterator it = LookupIterator::PropertyOrElement( 1975 isolate, receiver, name, Handle<JSReceiver>::cast(target)); 1976 Maybe<bool> result = Object::SetSuperProperty( 1977 &it, value, SLOPPY, Object::MAY_BE_STORE_FROM_KEYED); 1978 MAYBE_RETURN(result, isolate->heap()->exception()); 1979 return *isolate->factory()->ToBoolean(result.FromJust()); 1980 } 1981 1982 1983 // ES6 section 26.1.14 Reflect.setPrototypeOf 1984 BUILTIN(ReflectSetPrototypeOf) { 1985 HandleScope scope(isolate); 1986 DCHECK_EQ(3, args.length()); 1987 Handle<Object> target = args.at<Object>(1); 1988 Handle<Object> proto = args.at<Object>(2); 1989 1990 if (!target->IsJSReceiver()) { 1991 THROW_NEW_ERROR_RETURN_FAILURE( 1992 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject, 1993 isolate->factory()->NewStringFromAsciiChecked( 1994 "Reflect.setPrototypeOf"))); 1995 } 1996 1997 if (!proto->IsJSReceiver() && !proto->IsNull()) { 1998 THROW_NEW_ERROR_RETURN_FAILURE( 1999 isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, proto)); 2000 } 2001 2002 Maybe<bool> result = JSReceiver::SetPrototype( 2003 Handle<JSReceiver>::cast(target), proto, true, Object::DONT_THROW); 2004 MAYBE_RETURN(result, isolate->heap()->exception()); 2005 return *isolate->factory()->ToBoolean(result.FromJust()); 2006 } 2007 2008 2009 // ----------------------------------------------------------------------------- 2010 // ES6 section 20.3 Date Objects 2011 2012 2013 namespace { 2014 2015 // ES6 section 20.3.1.1 Time Values and Time Range 2016 const double kMinYear = -1000000.0; 2017 const double kMaxYear = -kMinYear; 2018 const double kMinMonth = -10000000.0; 2019 const double kMaxMonth = -kMinMonth; 2020 2021 2022 // 20.3.1.2 Day Number and Time within Day 2023 const double kMsPerDay = 86400000.0; 2024 2025 2026 // ES6 section 20.3.1.11 Hours, Minutes, Second, and Milliseconds 2027 const double kMsPerSecond = 1000.0; 2028 const double kMsPerMinute = 60000.0; 2029 const double kMsPerHour = 3600000.0; 2030 2031 2032 // ES6 section 20.3.1.14 MakeDate (day, time) 2033 double MakeDate(double day, double time) { 2034 if (std::isfinite(day) && std::isfinite(time)) { 2035 return time + day * kMsPerDay; 2036 } 2037 return std::numeric_limits<double>::quiet_NaN(); 2038 } 2039 2040 2041 // ES6 section 20.3.1.13 MakeDay (year, month, date) 2042 double MakeDay(double year, double month, double date) { 2043 if ((kMinYear <= year && year <= kMaxYear) && 2044 (kMinMonth <= month && month <= kMaxMonth) && std::isfinite(date)) { 2045 int y = FastD2I(year); 2046 int m = FastD2I(month); 2047 y += m / 12; 2048 m %= 12; 2049 if (m < 0) { 2050 m += 12; 2051 y -= 1; 2052 } 2053 DCHECK_LE(0, m); 2054 DCHECK_LT(m, 12); 2055 2056 // kYearDelta is an arbitrary number such that: 2057 // a) kYearDelta = -1 (mod 400) 2058 // b) year + kYearDelta > 0 for years in the range defined by 2059 // ECMA 262 - 15.9.1.1, i.e. upto 100,000,000 days on either side of 2060 // Jan 1 1970. This is required so that we don't run into integer 2061 // division of negative numbers. 2062 // c) there shouldn't be an overflow for 32-bit integers in the following 2063 // operations. 2064 static const int kYearDelta = 399999; 2065 static const int kBaseDay = 2066 365 * (1970 + kYearDelta) + (1970 + kYearDelta) / 4 - 2067 (1970 + kYearDelta) / 100 + (1970 + kYearDelta) / 400; 2068 int day_from_year = 365 * (y + kYearDelta) + (y + kYearDelta) / 4 - 2069 (y + kYearDelta) / 100 + (y + kYearDelta) / 400 - 2070 kBaseDay; 2071 if ((y % 4 != 0) || (y % 100 == 0 && y % 400 != 0)) { 2072 static const int kDayFromMonth[] = {0, 31, 59, 90, 120, 151, 2073 181, 212, 243, 273, 304, 334}; 2074 day_from_year += kDayFromMonth[m]; 2075 } else { 2076 static const int kDayFromMonth[] = {0, 31, 60, 91, 121, 152, 2077 182, 213, 244, 274, 305, 335}; 2078 day_from_year += kDayFromMonth[m]; 2079 } 2080 return static_cast<double>(day_from_year - 1) + date; 2081 } 2082 return std::numeric_limits<double>::quiet_NaN(); 2083 } 2084 2085 2086 // ES6 section 20.3.1.12 MakeTime (hour, min, sec, ms) 2087 double MakeTime(double hour, double min, double sec, double ms) { 2088 if (std::isfinite(hour) && std::isfinite(min) && std::isfinite(sec) && 2089 std::isfinite(ms)) { 2090 double const h = DoubleToInteger(hour); 2091 double const m = DoubleToInteger(min); 2092 double const s = DoubleToInteger(sec); 2093 double const milli = DoubleToInteger(ms); 2094 return h * kMsPerHour + m * kMsPerMinute + s * kMsPerSecond + milli; 2095 } 2096 return std::numeric_limits<double>::quiet_NaN(); 2097 } 2098 2099 2100 // ES6 section 20.3.1.15 TimeClip (time) 2101 double TimeClip(double time) { 2102 if (-DateCache::kMaxTimeInMs <= time && time <= DateCache::kMaxTimeInMs) { 2103 return DoubleToInteger(time) + 0.0; 2104 } 2105 return std::numeric_limits<double>::quiet_NaN(); 2106 } 2107 2108 2109 const char* kShortWeekDays[] = {"Sun", "Mon", "Tue", "Wed", 2110 "Thu", "Fri", "Sat"}; 2111 const char* kShortMonths[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", 2112 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; 2113 2114 2115 // ES6 section 20.3.1.16 Date Time String Format 2116 double ParseDateTimeString(Handle<String> str) { 2117 Isolate* const isolate = str->GetIsolate(); 2118 str = String::Flatten(str); 2119 // TODO(bmeurer): Change DateParser to not use the FixedArray. 2120 Handle<FixedArray> tmp = 2121 isolate->factory()->NewFixedArray(DateParser::OUTPUT_SIZE); 2122 DisallowHeapAllocation no_gc; 2123 String::FlatContent str_content = str->GetFlatContent(); 2124 bool result; 2125 if (str_content.IsOneByte()) { 2126 result = DateParser::Parse(str_content.ToOneByteVector(), *tmp, 2127 isolate->unicode_cache()); 2128 } else { 2129 result = DateParser::Parse(str_content.ToUC16Vector(), *tmp, 2130 isolate->unicode_cache()); 2131 } 2132 if (!result) return std::numeric_limits<double>::quiet_NaN(); 2133 double const day = MakeDay(tmp->get(0)->Number(), tmp->get(1)->Number(), 2134 tmp->get(2)->Number()); 2135 double const time = MakeTime(tmp->get(3)->Number(), tmp->get(4)->Number(), 2136 tmp->get(5)->Number(), tmp->get(6)->Number()); 2137 double date = MakeDate(day, time); 2138 if (tmp->get(7)->IsNull()) { 2139 if (!std::isnan(date)) { 2140 date = isolate->date_cache()->ToUTC(static_cast<int64_t>(date)); 2141 } 2142 } else { 2143 date -= tmp->get(7)->Number() * 1000.0; 2144 } 2145 return date; 2146 } 2147 2148 2149 enum ToDateStringMode { kDateOnly, kTimeOnly, kDateAndTime }; 2150 2151 2152 // ES6 section 20.3.4.41.1 ToDateString(tv) 2153 void ToDateString(double time_val, Vector<char> str, DateCache* date_cache, 2154 ToDateStringMode mode = kDateAndTime) { 2155 if (std::isnan(time_val)) { 2156 SNPrintF(str, "Invalid Date"); 2157 return; 2158 } 2159 int64_t time_ms = static_cast<int64_t>(time_val); 2160 int64_t local_time_ms = date_cache->ToLocal(time_ms); 2161 int year, month, day, weekday, hour, min, sec, ms; 2162 date_cache->BreakDownTime(local_time_ms, &year, &month, &day, &weekday, &hour, 2163 &min, &sec, &ms); 2164 int timezone_offset = -date_cache->TimezoneOffset(time_ms); 2165 int timezone_hour = std::abs(timezone_offset) / 60; 2166 int timezone_min = std::abs(timezone_offset) % 60; 2167 const char* local_timezone = date_cache->LocalTimezone(time_ms); 2168 switch (mode) { 2169 case kDateOnly: 2170 SNPrintF(str, "%s %s %02d %4d", kShortWeekDays[weekday], 2171 kShortMonths[month], day, year); 2172 return; 2173 case kTimeOnly: 2174 SNPrintF(str, "%02d:%02d:%02d GMT%c%02d%02d (%s)", hour, min, sec, 2175 (timezone_offset < 0) ? '-' : '+', timezone_hour, timezone_min, 2176 local_timezone); 2177 return; 2178 case kDateAndTime: 2179 SNPrintF(str, "%s %s %02d %4d %02d:%02d:%02d GMT%c%02d%02d (%s)", 2180 kShortWeekDays[weekday], kShortMonths[month], day, year, hour, 2181 min, sec, (timezone_offset < 0) ? '-' : '+', timezone_hour, 2182 timezone_min, local_timezone); 2183 return; 2184 } 2185 UNREACHABLE(); 2186 } 2187 2188 2189 Object* SetLocalDateValue(Handle<JSDate> date, double time_val) { 2190 if (time_val >= -DateCache::kMaxTimeBeforeUTCInMs && 2191 time_val <= DateCache::kMaxTimeBeforeUTCInMs) { 2192 Isolate* const isolate = date->GetIsolate(); 2193 time_val = isolate->date_cache()->ToUTC(static_cast<int64_t>(time_val)); 2194 } else { 2195 time_val = std::numeric_limits<double>::quiet_NaN(); 2196 } 2197 return *JSDate::SetValue(date, TimeClip(time_val)); 2198 } 2199 2200 } // namespace 2201 2202 2203 // ES6 section 20.3.2 The Date Constructor for the [[Call]] case. 2204 BUILTIN(DateConstructor) { 2205 HandleScope scope(isolate); 2206 double const time_val = JSDate::CurrentTimeValue(isolate); 2207 char buffer[128]; 2208 Vector<char> str(buffer, arraysize(buffer)); 2209 ToDateString(time_val, str, isolate->date_cache()); 2210 return *isolate->factory()->NewStringFromAsciiChecked(str.start()); 2211 } 2212 2213 2214 // ES6 section 20.3.2 The Date Constructor for the [[Construct]] case. 2215 BUILTIN(DateConstructor_ConstructStub) { 2216 HandleScope scope(isolate); 2217 int const argc = args.length() - 1; 2218 Handle<JSFunction> target = args.target(); 2219 Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target()); 2220 double time_val; 2221 if (argc == 0) { 2222 time_val = JSDate::CurrentTimeValue(isolate); 2223 } else if (argc == 1) { 2224 Handle<Object> value = args.at<Object>(1); 2225 if (value->IsJSDate()) { 2226 time_val = Handle<JSDate>::cast(value)->value()->Number(); 2227 } else { 2228 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, 2229 Object::ToPrimitive(value)); 2230 if (value->IsString()) { 2231 time_val = ParseDateTimeString(Handle<String>::cast(value)); 2232 } else { 2233 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, 2234 Object::ToNumber(value)); 2235 time_val = value->Number(); 2236 } 2237 } 2238 } else { 2239 Handle<Object> year_object; 2240 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year_object, 2241 Object::ToNumber(args.at<Object>(1))); 2242 Handle<Object> month_object; 2243 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month_object, 2244 Object::ToNumber(args.at<Object>(2))); 2245 double year = year_object->Number(); 2246 double month = month_object->Number(); 2247 double date = 1.0, hours = 0.0, minutes = 0.0, seconds = 0.0, ms = 0.0; 2248 if (argc >= 3) { 2249 Handle<Object> date_object; 2250 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date_object, 2251 Object::ToNumber(args.at<Object>(3))); 2252 date = date_object->Number(); 2253 if (argc >= 4) { 2254 Handle<Object> hours_object; 2255 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 2256 isolate, hours_object, Object::ToNumber(args.at<Object>(4))); 2257 hours = hours_object->Number(); 2258 if (argc >= 5) { 2259 Handle<Object> minutes_object; 2260 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 2261 isolate, minutes_object, Object::ToNumber(args.at<Object>(5))); 2262 minutes = minutes_object->Number(); 2263 if (argc >= 6) { 2264 Handle<Object> seconds_object; 2265 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 2266 isolate, seconds_object, Object::ToNumber(args.at<Object>(6))); 2267 seconds = seconds_object->Number(); 2268 if (argc >= 7) { 2269 Handle<Object> ms_object; 2270 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 2271 isolate, ms_object, Object::ToNumber(args.at<Object>(7))); 2272 ms = ms_object->Number(); 2273 } 2274 } 2275 } 2276 } 2277 } 2278 if (!std::isnan(year)) { 2279 double const y = DoubleToInteger(year); 2280 if (0.0 <= y && y <= 99) year = 1900 + y; 2281 } 2282 double const day = MakeDay(year, month, date); 2283 double const time = MakeTime(hours, minutes, seconds, ms); 2284 time_val = MakeDate(day, time); 2285 if (time_val >= -DateCache::kMaxTimeBeforeUTCInMs && 2286 time_val <= DateCache::kMaxTimeBeforeUTCInMs) { 2287 time_val = isolate->date_cache()->ToUTC(static_cast<int64_t>(time_val)); 2288 } else { 2289 time_val = std::numeric_limits<double>::quiet_NaN(); 2290 } 2291 } 2292 Handle<JSDate> result; 2293 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, 2294 JSDate::New(target, new_target, time_val)); 2295 return *result; 2296 } 2297 2298 2299 // ES6 section 20.3.3.1 Date.now ( ) 2300 BUILTIN(DateNow) { 2301 HandleScope scope(isolate); 2302 return *isolate->factory()->NewNumber(JSDate::CurrentTimeValue(isolate)); 2303 } 2304 2305 2306 // ES6 section 20.3.3.2 Date.parse ( string ) 2307 BUILTIN(DateParse) { 2308 HandleScope scope(isolate); 2309 Handle<String> string; 2310 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 2311 isolate, string, 2312 Object::ToString(isolate, args.atOrUndefined(isolate, 1))); 2313 return *isolate->factory()->NewNumber(ParseDateTimeString(string)); 2314 } 2315 2316 2317 // ES6 section 20.3.3.4 Date.UTC (year,month,date,hours,minutes,seconds,ms) 2318 BUILTIN(DateUTC) { 2319 HandleScope scope(isolate); 2320 int const argc = args.length() - 1; 2321 double year = std::numeric_limits<double>::quiet_NaN(); 2322 double month = std::numeric_limits<double>::quiet_NaN(); 2323 double date = 1.0, hours = 0.0, minutes = 0.0, seconds = 0.0, ms = 0.0; 2324 if (argc >= 1) { 2325 Handle<Object> year_object; 2326 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year_object, 2327 Object::ToNumber(args.at<Object>(1))); 2328 year = year_object->Number(); 2329 if (argc >= 2) { 2330 Handle<Object> month_object; 2331 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month_object, 2332 Object::ToNumber(args.at<Object>(2))); 2333 month = month_object->Number(); 2334 if (argc >= 3) { 2335 Handle<Object> date_object; 2336 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 2337 isolate, date_object, Object::ToNumber(args.at<Object>(3))); 2338 date = date_object->Number(); 2339 if (argc >= 4) { 2340 Handle<Object> hours_object; 2341 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 2342 isolate, hours_object, Object::ToNumber(args.at<Object>(4))); 2343 hours = hours_object->Number(); 2344 if (argc >= 5) { 2345 Handle<Object> minutes_object; 2346 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 2347 isolate, minutes_object, Object::ToNumber(args.at<Object>(5))); 2348 minutes = minutes_object->Number(); 2349 if (argc >= 6) { 2350 Handle<Object> seconds_object; 2351 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 2352 isolate, seconds_object, 2353 Object::ToNumber(args.at<Object>(6))); 2354 seconds = seconds_object->Number(); 2355 if (argc >= 7) { 2356 Handle<Object> ms_object; 2357 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 2358 isolate, ms_object, Object::ToNumber(args.at<Object>(7))); 2359 ms = ms_object->Number(); 2360 } 2361 } 2362 } 2363 } 2364 } 2365 } 2366 } 2367 if (!std::isnan(year)) { 2368 double const y = DoubleToInteger(year); 2369 if (0.0 <= y && y <= 99) year = 1900 + y; 2370 } 2371 double const day = MakeDay(year, month, date); 2372 double const time = MakeTime(hours, minutes, seconds, ms); 2373 return *isolate->factory()->NewNumber(TimeClip(MakeDate(day, time))); 2374 } 2375 2376 2377 // ES6 section 20.3.4.20 Date.prototype.setDate ( date ) 2378 BUILTIN(DatePrototypeSetDate) { 2379 HandleScope scope(isolate); 2380 CHECK_RECEIVER(JSDate, date, "Date.prototype.setDate"); 2381 Handle<Object> value = args.atOrUndefined(isolate, 1); 2382 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(value)); 2383 double time_val = date->value()->Number(); 2384 if (!std::isnan(time_val)) { 2385 int64_t const time_ms = static_cast<int64_t>(time_val); 2386 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); 2387 int const days = isolate->date_cache()->DaysFromTime(local_time_ms); 2388 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days); 2389 int year, month, day; 2390 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day); 2391 time_val = MakeDate(MakeDay(year, month, value->Number()), time_within_day); 2392 } 2393 return SetLocalDateValue(date, time_val); 2394 } 2395 2396 2397 // ES6 section 20.3.4.21 Date.prototype.setFullYear (year, month, date) 2398 BUILTIN(DatePrototypeSetFullYear) { 2399 HandleScope scope(isolate); 2400 CHECK_RECEIVER(JSDate, date, "Date.prototype.setFullYear"); 2401 int const argc = args.length() - 1; 2402 Handle<Object> year = args.atOrUndefined(isolate, 1); 2403 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, Object::ToNumber(year)); 2404 double y = year->Number(), m = 0.0, dt = 1.0; 2405 int time_within_day = 0; 2406 if (!std::isnan(date->value()->Number())) { 2407 int64_t const time_ms = static_cast<int64_t>(date->value()->Number()); 2408 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); 2409 int const days = isolate->date_cache()->DaysFromTime(local_time_ms); 2410 time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days); 2411 int year, month, day; 2412 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day); 2413 m = month; 2414 dt = day; 2415 } 2416 if (argc >= 2) { 2417 Handle<Object> month = args.at<Object>(2); 2418 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month)); 2419 m = month->Number(); 2420 if (argc >= 3) { 2421 Handle<Object> date = args.at<Object>(3); 2422 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date)); 2423 dt = date->Number(); 2424 } 2425 } 2426 double time_val = MakeDate(MakeDay(y, m, dt), time_within_day); 2427 return SetLocalDateValue(date, time_val); 2428 } 2429 2430 2431 // ES6 section 20.3.4.22 Date.prototype.setHours(hour, min, sec, ms) 2432 BUILTIN(DatePrototypeSetHours) { 2433 HandleScope scope(isolate); 2434 CHECK_RECEIVER(JSDate, date, "Date.prototype.setHours"); 2435 int const argc = args.length() - 1; 2436 Handle<Object> hour = args.atOrUndefined(isolate, 1); 2437 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, hour, Object::ToNumber(hour)); 2438 double h = hour->Number(); 2439 double time_val = date->value()->Number(); 2440 if (!std::isnan(time_val)) { 2441 int64_t const time_ms = static_cast<int64_t>(time_val); 2442 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); 2443 int day = isolate->date_cache()->DaysFromTime(local_time_ms); 2444 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day); 2445 double m = (time_within_day / (60 * 1000)) % 60; 2446 double s = (time_within_day / 1000) % 60; 2447 double milli = time_within_day % 1000; 2448 if (argc >= 2) { 2449 Handle<Object> min = args.at<Object>(2); 2450 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min)); 2451 m = min->Number(); 2452 if (argc >= 3) { 2453 Handle<Object> sec = args.at<Object>(3); 2454 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec)); 2455 s = sec->Number(); 2456 if (argc >= 4) { 2457 Handle<Object> ms = args.at<Object>(4); 2458 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms)); 2459 milli = ms->Number(); 2460 } 2461 } 2462 } 2463 time_val = MakeDate(day, MakeTime(h, m, s, milli)); 2464 } 2465 return SetLocalDateValue(date, time_val); 2466 } 2467 2468 2469 // ES6 section 20.3.4.23 Date.prototype.setMilliseconds(ms) 2470 BUILTIN(DatePrototypeSetMilliseconds) { 2471 HandleScope scope(isolate); 2472 CHECK_RECEIVER(JSDate, date, "Date.prototype.setMilliseconds"); 2473 Handle<Object> ms = args.atOrUndefined(isolate, 1); 2474 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms)); 2475 double time_val = date->value()->Number(); 2476 if (!std::isnan(time_val)) { 2477 int64_t const time_ms = static_cast<int64_t>(time_val); 2478 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); 2479 int day = isolate->date_cache()->DaysFromTime(local_time_ms); 2480 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day); 2481 int h = time_within_day / (60 * 60 * 1000); 2482 int m = (time_within_day / (60 * 1000)) % 60; 2483 int s = (time_within_day / 1000) % 60; 2484 time_val = MakeDate(day, MakeTime(h, m, s, ms->Number())); 2485 } 2486 return SetLocalDateValue(date, time_val); 2487 } 2488 2489 2490 // ES6 section 20.3.4.24 Date.prototype.setMinutes ( min, sec, ms ) 2491 BUILTIN(DatePrototypeSetMinutes) { 2492 HandleScope scope(isolate); 2493 CHECK_RECEIVER(JSDate, date, "Date.prototype.setMinutes"); 2494 int const argc = args.length() - 1; 2495 Handle<Object> min = args.atOrUndefined(isolate, 1); 2496 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min)); 2497 double time_val = date->value()->Number(); 2498 if (!std::isnan(time_val)) { 2499 int64_t const time_ms = static_cast<int64_t>(time_val); 2500 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); 2501 int day = isolate->date_cache()->DaysFromTime(local_time_ms); 2502 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day); 2503 int h = time_within_day / (60 * 60 * 1000); 2504 double m = min->Number(); 2505 double s = (time_within_day / 1000) % 60; 2506 double milli = time_within_day % 1000; 2507 if (argc >= 2) { 2508 Handle<Object> sec = args.at<Object>(2); 2509 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec)); 2510 s = sec->Number(); 2511 if (argc >= 3) { 2512 Handle<Object> ms = args.at<Object>(3); 2513 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms)); 2514 milli = ms->Number(); 2515 } 2516 } 2517 time_val = MakeDate(day, MakeTime(h, m, s, milli)); 2518 } 2519 return SetLocalDateValue(date, time_val); 2520 } 2521 2522 2523 // ES6 section 20.3.4.25 Date.prototype.setMonth ( month, date ) 2524 BUILTIN(DatePrototypeSetMonth) { 2525 HandleScope scope(isolate); 2526 CHECK_RECEIVER(JSDate, date, "Date.prototype.setMonth"); 2527 int const argc = args.length() - 1; 2528 Handle<Object> month = args.atOrUndefined(isolate, 1); 2529 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month)); 2530 double time_val = date->value()->Number(); 2531 if (!std::isnan(time_val)) { 2532 int64_t const time_ms = static_cast<int64_t>(time_val); 2533 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); 2534 int days = isolate->date_cache()->DaysFromTime(local_time_ms); 2535 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days); 2536 int year, unused, day; 2537 isolate->date_cache()->YearMonthDayFromDays(days, &year, &unused, &day); 2538 double m = month->Number(); 2539 double dt = day; 2540 if (argc >= 2) { 2541 Handle<Object> date = args.at<Object>(2); 2542 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date)); 2543 dt = date->Number(); 2544 } 2545 time_val = MakeDate(MakeDay(year, m, dt), time_within_day); 2546 } 2547 return SetLocalDateValue(date, time_val); 2548 } 2549 2550 2551 // ES6 section 20.3.4.26 Date.prototype.setSeconds ( sec, ms ) 2552 BUILTIN(DatePrototypeSetSeconds) { 2553 HandleScope scope(isolate); 2554 CHECK_RECEIVER(JSDate, date, "Date.prototype.setSeconds"); 2555 int const argc = args.length() - 1; 2556 Handle<Object> sec = args.atOrUndefined(isolate, 1); 2557 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec)); 2558 double time_val = date->value()->Number(); 2559 if (!std::isnan(time_val)) { 2560 int64_t const time_ms = static_cast<int64_t>(time_val); 2561 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); 2562 int day = isolate->date_cache()->DaysFromTime(local_time_ms); 2563 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day); 2564 int h = time_within_day / (60 * 60 * 1000); 2565 double m = (time_within_day / (60 * 1000)) % 60; 2566 double s = sec->Number(); 2567 double milli = time_within_day % 1000; 2568 if (argc >= 2) { 2569 Handle<Object> ms = args.at<Object>(2); 2570 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms)); 2571 milli = ms->Number(); 2572 } 2573 time_val = MakeDate(day, MakeTime(h, m, s, milli)); 2574 } 2575 return SetLocalDateValue(date, time_val); 2576 } 2577 2578 2579 // ES6 section 20.3.4.27 Date.prototype.setTime ( time ) 2580 BUILTIN(DatePrototypeSetTime) { 2581 HandleScope scope(isolate); 2582 CHECK_RECEIVER(JSDate, date, "Date.prototype.setTime"); 2583 Handle<Object> value = args.atOrUndefined(isolate, 1); 2584 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(value)); 2585 return *JSDate::SetValue(date, TimeClip(value->Number())); 2586 } 2587 2588 2589 // ES6 section 20.3.4.28 Date.prototype.setUTCDate ( date ) 2590 BUILTIN(DatePrototypeSetUTCDate) { 2591 HandleScope scope(isolate); 2592 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCDate"); 2593 Handle<Object> value = args.atOrUndefined(isolate, 1); 2594 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(value)); 2595 if (std::isnan(date->value()->Number())) return date->value(); 2596 int64_t const time_ms = static_cast<int64_t>(date->value()->Number()); 2597 int const days = isolate->date_cache()->DaysFromTime(time_ms); 2598 int const time_within_day = isolate->date_cache()->TimeInDay(time_ms, days); 2599 int year, month, day; 2600 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day); 2601 double const time_val = 2602 MakeDate(MakeDay(year, month, value->Number()), time_within_day); 2603 return *JSDate::SetValue(date, TimeClip(time_val)); 2604 } 2605 2606 2607 // ES6 section 20.3.4.29 Date.prototype.setUTCFullYear (year, month, date) 2608 BUILTIN(DatePrototypeSetUTCFullYear) { 2609 HandleScope scope(isolate); 2610 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCFullYear"); 2611 int const argc = args.length() - 1; 2612 Handle<Object> year = args.atOrUndefined(isolate, 1); 2613 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, Object::ToNumber(year)); 2614 double y = year->Number(), m = 0.0, dt = 1.0; 2615 int time_within_day = 0; 2616 if (!std::isnan(date->value()->Number())) { 2617 int64_t const time_ms = static_cast<int64_t>(date->value()->Number()); 2618 int const days = isolate->date_cache()->DaysFromTime(time_ms); 2619 time_within_day = isolate->date_cache()->TimeInDay(time_ms, days); 2620 int year, month, day; 2621 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day); 2622 m = month; 2623 dt = day; 2624 } 2625 if (argc >= 2) { 2626 Handle<Object> month = args.at<Object>(2); 2627 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month)); 2628 m = month->Number(); 2629 if (argc >= 3) { 2630 Handle<Object> date = args.at<Object>(3); 2631 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date)); 2632 dt = date->Number(); 2633 } 2634 } 2635 double const time_val = MakeDate(MakeDay(y, m, dt), time_within_day); 2636 return *JSDate::SetValue(date, TimeClip(time_val)); 2637 } 2638 2639 2640 // ES6 section 20.3.4.30 Date.prototype.setUTCHours(hour, min, sec, ms) 2641 BUILTIN(DatePrototypeSetUTCHours) { 2642 HandleScope scope(isolate); 2643 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCHours"); 2644 int const argc = args.length() - 1; 2645 Handle<Object> hour = args.atOrUndefined(isolate, 1); 2646 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, hour, Object::ToNumber(hour)); 2647 double h = hour->Number(); 2648 double time_val = date->value()->Number(); 2649 if (!std::isnan(time_val)) { 2650 int64_t const time_ms = static_cast<int64_t>(time_val); 2651 int day = isolate->date_cache()->DaysFromTime(time_ms); 2652 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day); 2653 double m = (time_within_day / (60 * 1000)) % 60; 2654 double s = (time_within_day / 1000) % 60; 2655 double milli = time_within_day % 1000; 2656 if (argc >= 2) { 2657 Handle<Object> min = args.at<Object>(2); 2658 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min)); 2659 m = min->Number(); 2660 if (argc >= 3) { 2661 Handle<Object> sec = args.at<Object>(3); 2662 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec)); 2663 s = sec->Number(); 2664 if (argc >= 4) { 2665 Handle<Object> ms = args.at<Object>(4); 2666 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms)); 2667 milli = ms->Number(); 2668 } 2669 } 2670 } 2671 time_val = MakeDate(day, MakeTime(h, m, s, milli)); 2672 } 2673 return *JSDate::SetValue(date, TimeClip(time_val)); 2674 } 2675 2676 2677 // ES6 section 20.3.4.31 Date.prototype.setUTCMilliseconds(ms) 2678 BUILTIN(DatePrototypeSetUTCMilliseconds) { 2679 HandleScope scope(isolate); 2680 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMilliseconds"); 2681 Handle<Object> ms = args.atOrUndefined(isolate, 1); 2682 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms)); 2683 double time_val = date->value()->Number(); 2684 if (!std::isnan(time_val)) { 2685 int64_t const time_ms = static_cast<int64_t>(time_val); 2686 int day = isolate->date_cache()->DaysFromTime(time_ms); 2687 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day); 2688 int h = time_within_day / (60 * 60 * 1000); 2689 int m = (time_within_day / (60 * 1000)) % 60; 2690 int s = (time_within_day / 1000) % 60; 2691 time_val = MakeDate(day, MakeTime(h, m, s, ms->Number())); 2692 } 2693 return *JSDate::SetValue(date, TimeClip(time_val)); 2694 } 2695 2696 2697 // ES6 section 20.3.4.32 Date.prototype.setUTCMinutes ( min, sec, ms ) 2698 BUILTIN(DatePrototypeSetUTCMinutes) { 2699 HandleScope scope(isolate); 2700 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMinutes"); 2701 int const argc = args.length() - 1; 2702 Handle<Object> min = args.atOrUndefined(isolate, 1); 2703 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min)); 2704 double time_val = date->value()->Number(); 2705 if (!std::isnan(time_val)) { 2706 int64_t const time_ms = static_cast<int64_t>(time_val); 2707 int day = isolate->date_cache()->DaysFromTime(time_ms); 2708 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day); 2709 int h = time_within_day / (60 * 60 * 1000); 2710 double m = min->Number(); 2711 double s = (time_within_day / 1000) % 60; 2712 double milli = time_within_day % 1000; 2713 if (argc >= 2) { 2714 Handle<Object> sec = args.at<Object>(2); 2715 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec)); 2716 s = sec->Number(); 2717 if (argc >= 3) { 2718 Handle<Object> ms = args.at<Object>(3); 2719 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms)); 2720 milli = ms->Number(); 2721 } 2722 } 2723 time_val = MakeDate(day, MakeTime(h, m, s, milli)); 2724 } 2725 return *JSDate::SetValue(date, TimeClip(time_val)); 2726 } 2727 2728 2729 // ES6 section 20.3.4.31 Date.prototype.setUTCMonth ( month, date ) 2730 BUILTIN(DatePrototypeSetUTCMonth) { 2731 HandleScope scope(isolate); 2732 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMonth"); 2733 int const argc = args.length() - 1; 2734 Handle<Object> month = args.atOrUndefined(isolate, 1); 2735 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month)); 2736 double time_val = date->value()->Number(); 2737 if (!std::isnan(time_val)) { 2738 int64_t const time_ms = static_cast<int64_t>(time_val); 2739 int days = isolate->date_cache()->DaysFromTime(time_ms); 2740 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, days); 2741 int year, unused, day; 2742 isolate->date_cache()->YearMonthDayFromDays(days, &year, &unused, &day); 2743 double m = month->Number(); 2744 double dt = day; 2745 if (argc >= 2) { 2746 Handle<Object> date = args.at<Object>(2); 2747 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date)); 2748 dt = date->Number(); 2749 } 2750 time_val = MakeDate(MakeDay(year, m, dt), time_within_day); 2751 } 2752 return *JSDate::SetValue(date, TimeClip(time_val)); 2753 } 2754 2755 2756 // ES6 section 20.3.4.34 Date.prototype.setUTCSeconds ( sec, ms ) 2757 BUILTIN(DatePrototypeSetUTCSeconds) { 2758 HandleScope scope(isolate); 2759 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCSeconds"); 2760 int const argc = args.length() - 1; 2761 Handle<Object> sec = args.atOrUndefined(isolate, 1); 2762 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec)); 2763 double time_val = date->value()->Number(); 2764 if (!std::isnan(time_val)) { 2765 int64_t const time_ms = static_cast<int64_t>(time_val); 2766 int day = isolate->date_cache()->DaysFromTime(time_ms); 2767 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day); 2768 int h = time_within_day / (60 * 60 * 1000); 2769 double m = (time_within_day / (60 * 1000)) % 60; 2770 double s = sec->Number(); 2771 double milli = time_within_day % 1000; 2772 if (argc >= 2) { 2773 Handle<Object> ms = args.at<Object>(2); 2774 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms)); 2775 milli = ms->Number(); 2776 } 2777 time_val = MakeDate(day, MakeTime(h, m, s, milli)); 2778 } 2779 return *JSDate::SetValue(date, TimeClip(time_val)); 2780 } 2781 2782 2783 // ES6 section 20.3.4.35 Date.prototype.toDateString ( ) 2784 BUILTIN(DatePrototypeToDateString) { 2785 HandleScope scope(isolate); 2786 CHECK_RECEIVER(JSDate, date, "Date.prototype.toDateString"); 2787 char buffer[128]; 2788 Vector<char> str(buffer, arraysize(buffer)); 2789 ToDateString(date->value()->Number(), str, isolate->date_cache(), kDateOnly); 2790 return *isolate->factory()->NewStringFromAsciiChecked(str.start()); 2791 } 2792 2793 2794 // ES6 section 20.3.4.36 Date.prototype.toISOString ( ) 2795 BUILTIN(DatePrototypeToISOString) { 2796 HandleScope scope(isolate); 2797 CHECK_RECEIVER(JSDate, date, "Date.prototype.toISOString"); 2798 double const time_val = date->value()->Number(); 2799 if (std::isnan(time_val)) { 2800 THROW_NEW_ERROR_RETURN_FAILURE( 2801 isolate, NewRangeError(MessageTemplate::kInvalidTimeValue)); 2802 } 2803 int64_t const time_ms = static_cast<int64_t>(time_val); 2804 int year, month, day, weekday, hour, min, sec, ms; 2805 isolate->date_cache()->BreakDownTime(time_ms, &year, &month, &day, &weekday, 2806 &hour, &min, &sec, &ms); 2807 char buffer[128]; 2808 Vector<char> str(buffer, arraysize(buffer)); 2809 if (year >= 0 && year <= 9999) { 2810 SNPrintF(str, "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", year, month + 1, day, 2811 hour, min, sec, ms); 2812 } else if (year < 0) { 2813 SNPrintF(str, "-%06d-%02d-%02dT%02d:%02d:%02d.%03dZ", -year, month + 1, day, 2814 hour, min, sec, ms); 2815 } else { 2816 SNPrintF(str, "+%06d-%02d-%02dT%02d:%02d:%02d.%03dZ", year, month + 1, day, 2817 hour, min, sec, ms); 2818 } 2819 return *isolate->factory()->NewStringFromAsciiChecked(str.start()); 2820 } 2821 2822 2823 // ES6 section 20.3.4.41 Date.prototype.toString ( ) 2824 BUILTIN(DatePrototypeToString) { 2825 HandleScope scope(isolate); 2826 CHECK_RECEIVER(JSDate, date, "Date.prototype.toString"); 2827 char buffer[128]; 2828 Vector<char> str(buffer, arraysize(buffer)); 2829 ToDateString(date->value()->Number(), str, isolate->date_cache()); 2830 return *isolate->factory()->NewStringFromAsciiChecked(str.start()); 2831 } 2832 2833 2834 // ES6 section 20.3.4.42 Date.prototype.toTimeString ( ) 2835 BUILTIN(DatePrototypeToTimeString) { 2836 HandleScope scope(isolate); 2837 CHECK_RECEIVER(JSDate, date, "Date.prototype.toTimeString"); 2838 char buffer[128]; 2839 Vector<char> str(buffer, arraysize(buffer)); 2840 ToDateString(date->value()->Number(), str, isolate->date_cache(), kTimeOnly); 2841 return *isolate->factory()->NewStringFromAsciiChecked(str.start()); 2842 } 2843 2844 2845 // ES6 section 20.3.4.43 Date.prototype.toUTCString ( ) 2846 BUILTIN(DatePrototypeToUTCString) { 2847 HandleScope scope(isolate); 2848 CHECK_RECEIVER(JSDate, date, "Date.prototype.toUTCString"); 2849 double const time_val = date->value()->Number(); 2850 if (std::isnan(time_val)) { 2851 return *isolate->factory()->NewStringFromAsciiChecked("Invalid Date"); 2852 } 2853 char buffer[128]; 2854 Vector<char> str(buffer, arraysize(buffer)); 2855 int64_t time_ms = static_cast<int64_t>(time_val); 2856 int year, month, day, weekday, hour, min, sec, ms; 2857 isolate->date_cache()->BreakDownTime(time_ms, &year, &month, &day, &weekday, 2858 &hour, &min, &sec, &ms); 2859 SNPrintF(str, "%s, %02d %s %4d %02d:%02d:%02d GMT", kShortWeekDays[weekday], 2860 day, kShortMonths[month], year, hour, min, sec); 2861 return *isolate->factory()->NewStringFromAsciiChecked(str.start()); 2862 } 2863 2864 2865 // ES6 section 20.3.4.44 Date.prototype.valueOf ( ) 2866 BUILTIN(DatePrototypeValueOf) { 2867 HandleScope scope(isolate); 2868 CHECK_RECEIVER(JSDate, date, "Date.prototype.valueOf"); 2869 return date->value(); 2870 } 2871 2872 2873 // ES6 section 20.3.4.45 Date.prototype [ @@toPrimitive ] ( hint ) 2874 BUILTIN(DatePrototypeToPrimitive) { 2875 HandleScope scope(isolate); 2876 DCHECK_EQ(2, args.length()); 2877 CHECK_RECEIVER(JSReceiver, receiver, "Date.prototype [ @@toPrimitive ]"); 2878 Handle<Object> hint = args.at<Object>(1); 2879 Handle<Object> result; 2880 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, 2881 JSDate::ToPrimitive(receiver, hint)); 2882 return *result; 2883 } 2884 2885 2886 // ES6 section B.2.4.1 Date.prototype.getYear ( ) 2887 BUILTIN(DatePrototypeGetYear) { 2888 HandleScope scope(isolate); 2889 CHECK_RECEIVER(JSDate, date, "Date.prototype.getYear"); 2890 double time_val = date->value()->Number(); 2891 if (std::isnan(time_val)) return date->value(); 2892 int64_t time_ms = static_cast<int64_t>(time_val); 2893 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); 2894 int days = isolate->date_cache()->DaysFromTime(local_time_ms); 2895 int year, month, day; 2896 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day); 2897 return Smi::FromInt(year - 1900); 2898 } 2899 2900 2901 // ES6 section B.2.4.2 Date.prototype.setYear ( year ) 2902 BUILTIN(DatePrototypeSetYear) { 2903 HandleScope scope(isolate); 2904 CHECK_RECEIVER(JSDate, date, "Date.prototype.setYear"); 2905 Handle<Object> year = args.atOrUndefined(isolate, 1); 2906 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, Object::ToNumber(year)); 2907 double m = 0.0, dt = 1.0, y = year->Number(); 2908 if (0.0 <= y && y <= 99.0) { 2909 y = 1900.0 + DoubleToInteger(y); 2910 } 2911 int time_within_day = 0; 2912 if (!std::isnan(date->value()->Number())) { 2913 int64_t const time_ms = static_cast<int64_t>(date->value()->Number()); 2914 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); 2915 int const days = isolate->date_cache()->DaysFromTime(local_time_ms); 2916 time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days); 2917 int year, month, day; 2918 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day); 2919 m = month; 2920 dt = day; 2921 } 2922 double time_val = MakeDate(MakeDay(y, m, dt), time_within_day); 2923 return SetLocalDateValue(date, time_val); 2924 } 2925 2926 2927 // static 2928 void Builtins::Generate_DatePrototypeGetDate(MacroAssembler* masm) { 2929 Generate_DatePrototype_GetField(masm, JSDate::kDay); 2930 } 2931 2932 2933 // static 2934 void Builtins::Generate_DatePrototypeGetDay(MacroAssembler* masm) { 2935 Generate_DatePrototype_GetField(masm, JSDate::kWeekday); 2936 } 2937 2938 2939 // static 2940 void Builtins::Generate_DatePrototypeGetFullYear(MacroAssembler* masm) { 2941 Generate_DatePrototype_GetField(masm, JSDate::kYear); 2942 } 2943 2944 2945 // static 2946 void Builtins::Generate_DatePrototypeGetHours(MacroAssembler* masm) { 2947 Generate_DatePrototype_GetField(masm, JSDate::kHour); 2948 } 2949 2950 2951 // static 2952 void Builtins::Generate_DatePrototypeGetMilliseconds(MacroAssembler* masm) { 2953 Generate_DatePrototype_GetField(masm, JSDate::kMillisecond); 2954 } 2955 2956 2957 // static 2958 void Builtins::Generate_DatePrototypeGetMinutes(MacroAssembler* masm) { 2959 Generate_DatePrototype_GetField(masm, JSDate::kMinute); 2960 } 2961 2962 2963 // static 2964 void Builtins::Generate_DatePrototypeGetMonth(MacroAssembler* masm) { 2965 Generate_DatePrototype_GetField(masm, JSDate::kMonth); 2966 } 2967 2968 2969 // static 2970 void Builtins::Generate_DatePrototypeGetSeconds(MacroAssembler* masm) { 2971 Generate_DatePrototype_GetField(masm, JSDate::kSecond); 2972 } 2973 2974 2975 // static 2976 void Builtins::Generate_DatePrototypeGetTime(MacroAssembler* masm) { 2977 Generate_DatePrototype_GetField(masm, JSDate::kDateValue); 2978 } 2979 2980 2981 // static 2982 void Builtins::Generate_DatePrototypeGetTimezoneOffset(MacroAssembler* masm) { 2983 Generate_DatePrototype_GetField(masm, JSDate::kTimezoneOffset); 2984 } 2985 2986 2987 // static 2988 void Builtins::Generate_DatePrototypeGetUTCDate(MacroAssembler* masm) { 2989 Generate_DatePrototype_GetField(masm, JSDate::kDayUTC); 2990 } 2991 2992 2993 // static 2994 void Builtins::Generate_DatePrototypeGetUTCDay(MacroAssembler* masm) { 2995 Generate_DatePrototype_GetField(masm, JSDate::kWeekdayUTC); 2996 } 2997 2998 2999 // static 3000 void Builtins::Generate_DatePrototypeGetUTCFullYear(MacroAssembler* masm) { 3001 Generate_DatePrototype_GetField(masm, JSDate::kYearUTC); 3002 } 3003 3004 3005 // static 3006 void Builtins::Generate_DatePrototypeGetUTCHours(MacroAssembler* masm) { 3007 Generate_DatePrototype_GetField(masm, JSDate::kHourUTC); 3008 } 3009 3010 3011 // static 3012 void Builtins::Generate_DatePrototypeGetUTCMilliseconds(MacroAssembler* masm) { 3013 Generate_DatePrototype_GetField(masm, JSDate::kMillisecondUTC); 3014 } 3015 3016 3017 // static 3018 void Builtins::Generate_DatePrototypeGetUTCMinutes(MacroAssembler* masm) { 3019 Generate_DatePrototype_GetField(masm, JSDate::kMinuteUTC); 3020 } 3021 3022 3023 // static 3024 void Builtins::Generate_DatePrototypeGetUTCMonth(MacroAssembler* masm) { 3025 Generate_DatePrototype_GetField(masm, JSDate::kMonthUTC); 3026 } 3027 3028 3029 // static 3030 void Builtins::Generate_DatePrototypeGetUTCSeconds(MacroAssembler* masm) { 3031 Generate_DatePrototype_GetField(masm, JSDate::kSecondUTC); 3032 } 3033 3034 3035 namespace { 3036 3037 // ES6 section 19.2.1.1.1 CreateDynamicFunction 3038 MaybeHandle<JSFunction> CreateDynamicFunction( 3039 Isolate* isolate, 3040 BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget> args, 3041 const char* token) { 3042 // Compute number of arguments, ignoring the receiver. 3043 DCHECK_LE(1, args.length()); 3044 int const argc = args.length() - 1; 3045 3046 // Build the source string. 3047 Handle<String> source; 3048 { 3049 IncrementalStringBuilder builder(isolate); 3050 builder.AppendCharacter('('); 3051 builder.AppendCString(token); 3052 builder.AppendCharacter('('); 3053 bool parenthesis_in_arg_string = false; 3054 if (argc > 1) { 3055 for (int i = 1; i < argc; ++i) { 3056 if (i > 1) builder.AppendCharacter(','); 3057 Handle<String> param; 3058 ASSIGN_RETURN_ON_EXCEPTION( 3059 isolate, param, Object::ToString(isolate, args.at<Object>(i)), 3060 JSFunction); 3061 param = String::Flatten(param); 3062 builder.AppendString(param); 3063 // If the formal parameters string include ) - an illegal 3064 // character - it may make the combined function expression 3065 // compile. We avoid this problem by checking for this early on. 3066 DisallowHeapAllocation no_gc; // Ensure vectors stay valid. 3067 String::FlatContent param_content = param->GetFlatContent(); 3068 for (int i = 0, length = param->length(); i < length; ++i) { 3069 if (param_content.Get(i) == ')') { 3070 parenthesis_in_arg_string = true; 3071 break; 3072 } 3073 } 3074 } 3075 // If the formal parameters include an unbalanced block comment, the 3076 // function must be rejected. Since JavaScript does not allow nested 3077 // comments we can include a trailing block comment to catch this. 3078 builder.AppendCString("\n/**/"); 3079 } 3080 builder.AppendCString(") {\n"); 3081 if (argc > 0) { 3082 Handle<String> body; 3083 ASSIGN_RETURN_ON_EXCEPTION( 3084 isolate, body, Object::ToString(isolate, args.at<Object>(argc)), 3085 JSFunction); 3086 builder.AppendString(body); 3087 } 3088 builder.AppendCString("\n})"); 3089 ASSIGN_RETURN_ON_EXCEPTION(isolate, source, builder.Finish(), JSFunction); 3090 3091 // The SyntaxError must be thrown after all the (observable) ToString 3092 // conversions are done. 3093 if (parenthesis_in_arg_string) { 3094 THROW_NEW_ERROR(isolate, 3095 NewSyntaxError(MessageTemplate::kParenthesisInArgString), 3096 JSFunction); 3097 } 3098 } 3099 3100 // Compile the string in the constructor and not a helper so that errors to 3101 // come from here. 3102 Handle<JSFunction> target = args.target(); 3103 Handle<JSObject> target_global_proxy(target->global_proxy(), isolate); 3104 Handle<JSFunction> function; 3105 { 3106 ASSIGN_RETURN_ON_EXCEPTION( 3107 isolate, function, 3108 CompileString(handle(target->native_context(), isolate), source, 3109 ONLY_SINGLE_FUNCTION_LITERAL), 3110 JSFunction); 3111 Handle<Object> result; 3112 ASSIGN_RETURN_ON_EXCEPTION( 3113 isolate, result, 3114 Execution::Call(isolate, function, target_global_proxy, 0, nullptr), 3115 JSFunction); 3116 function = Handle<JSFunction>::cast(result); 3117 function->shared()->set_name_should_print_as_anonymous(true); 3118 } 3119 3120 // If new.target is equal to target then the function created 3121 // is already correctly setup and nothing else should be done 3122 // here. But if new.target is not equal to target then we are 3123 // have a Function builtin subclassing case and therefore the 3124 // function has wrong initial map. To fix that we create a new 3125 // function object with correct initial map. 3126 Handle<Object> unchecked_new_target = args.new_target(); 3127 if (!unchecked_new_target->IsUndefined() && 3128 !unchecked_new_target.is_identical_to(target)) { 3129 Handle<JSReceiver> new_target = 3130 Handle<JSReceiver>::cast(unchecked_new_target); 3131 Handle<Map> initial_map; 3132 ASSIGN_RETURN_ON_EXCEPTION( 3133 isolate, initial_map, 3134 JSFunction::GetDerivedMap(isolate, target, new_target), JSFunction); 3135 3136 Handle<SharedFunctionInfo> shared_info(function->shared(), isolate); 3137 Handle<Map> map = Map::AsLanguageMode( 3138 initial_map, shared_info->language_mode(), shared_info->kind()); 3139 3140 Handle<Context> context(function->context(), isolate); 3141 function = isolate->factory()->NewFunctionFromSharedFunctionInfo( 3142 map, shared_info, context, NOT_TENURED); 3143 } 3144 return function; 3145 } 3146 3147 } // namespace 3148 3149 3150 // ES6 section 19.2.1.1 Function ( p1, p2, ... , pn, body ) 3151 BUILTIN(FunctionConstructor) { 3152 HandleScope scope(isolate); 3153 Handle<JSFunction> result; 3154 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 3155 isolate, result, CreateDynamicFunction(isolate, args, "function")); 3156 return *result; 3157 } 3158 3159 3160 // ES6 section 19.2.3.2 Function.prototype.bind ( thisArg, ...args ) 3161 BUILTIN(FunctionPrototypeBind) { 3162 HandleScope scope(isolate); 3163 DCHECK_LE(1, args.length()); 3164 if (!args.receiver()->IsCallable()) { 3165 THROW_NEW_ERROR_RETURN_FAILURE( 3166 isolate, NewTypeError(MessageTemplate::kFunctionBind)); 3167 } 3168 3169 // Allocate the bound function with the given {this_arg} and {args}. 3170 Handle<JSReceiver> target = args.at<JSReceiver>(0); 3171 Handle<Object> this_arg = isolate->factory()->undefined_value(); 3172 ScopedVector<Handle<Object>> argv(std::max(0, args.length() - 2)); 3173 if (args.length() > 1) { 3174 this_arg = args.at<Object>(1); 3175 for (int i = 2; i < args.length(); ++i) { 3176 argv[i - 2] = args.at<Object>(i); 3177 } 3178 } 3179 Handle<JSBoundFunction> function; 3180 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 3181 isolate, function, 3182 isolate->factory()->NewJSBoundFunction(target, this_arg, argv)); 3183 3184 // TODO(bmeurer): Optimize the rest for the common cases where {target} is 3185 // a function with some initial map or even a bound function. 3186 // Setup the "length" property based on the "length" of the {target}. 3187 Handle<Object> length(Smi::FromInt(0), isolate); 3188 Maybe<bool> target_has_length = 3189 JSReceiver::HasOwnProperty(target, isolate->factory()->length_string()); 3190 if (!target_has_length.IsJust()) { 3191 return isolate->heap()->exception(); 3192 } else if (target_has_length.FromJust()) { 3193 Handle<Object> target_length; 3194 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 3195 isolate, target_length, 3196 JSReceiver::GetProperty(target, isolate->factory()->length_string())); 3197 if (target_length->IsNumber()) { 3198 length = isolate->factory()->NewNumber(std::max( 3199 0.0, DoubleToInteger(target_length->Number()) - argv.length())); 3200 } 3201 } 3202 function->set_length(*length); 3203 3204 // Setup the "name" property based on the "name" of the {target}. 3205 Handle<Object> target_name; 3206 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 3207 isolate, target_name, 3208 JSReceiver::GetProperty(target, isolate->factory()->name_string())); 3209 Handle<String> name; 3210 if (!target_name->IsString()) { 3211 name = isolate->factory()->bound__string(); 3212 } else { 3213 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 3214 isolate, name, Name::ToFunctionName(Handle<String>::cast(target_name))); 3215 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 3216 isolate, name, isolate->factory()->NewConsString( 3217 isolate->factory()->bound__string(), name)); 3218 } 3219 function->set_name(*name); 3220 return *function; 3221 } 3222 3223 3224 // ES6 section 19.2.3.5 Function.prototype.toString ( ) 3225 BUILTIN(FunctionPrototypeToString) { 3226 HandleScope scope(isolate); 3227 Handle<Object> receiver = args.receiver(); 3228 if (receiver->IsJSBoundFunction()) { 3229 return *JSBoundFunction::ToString(Handle<JSBoundFunction>::cast(receiver)); 3230 } else if (receiver->IsJSFunction()) { 3231 return *JSFunction::ToString(Handle<JSFunction>::cast(receiver)); 3232 } 3233 THROW_NEW_ERROR_RETURN_FAILURE( 3234 isolate, NewTypeError(MessageTemplate::kNotGeneric, 3235 isolate->factory()->NewStringFromAsciiChecked( 3236 "Function.prototype.toString"))); 3237 } 3238 3239 3240 // ES6 section 25.2.1.1 GeneratorFunction (p1, p2, ... , pn, body) 3241 BUILTIN(GeneratorFunctionConstructor) { 3242 HandleScope scope(isolate); 3243 Handle<JSFunction> result; 3244 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 3245 isolate, result, CreateDynamicFunction(isolate, args, "function*")); 3246 return *result; 3247 } 3248 3249 3250 // ES6 section 19.4.1.1 Symbol ( [ description ] ) for the [[Call]] case. 3251 BUILTIN(SymbolConstructor) { 3252 HandleScope scope(isolate); 3253 Handle<Symbol> result = isolate->factory()->NewSymbol(); 3254 Handle<Object> description = args.atOrUndefined(isolate, 1); 3255 if (!description->IsUndefined()) { 3256 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, description, 3257 Object::ToString(isolate, description)); 3258 result->set_name(*description); 3259 } 3260 return *result; 3261 } 3262 3263 3264 // ES6 section 19.4.1.1 Symbol ( [ description ] ) for the [[Construct]] case. 3265 BUILTIN(SymbolConstructor_ConstructStub) { 3266 HandleScope scope(isolate); 3267 THROW_NEW_ERROR_RETURN_FAILURE( 3268 isolate, NewTypeError(MessageTemplate::kNotConstructor, 3269 isolate->factory()->Symbol_string())); 3270 } 3271 3272 3273 // ES6 19.1.3.6 Object.prototype.toString 3274 BUILTIN(ObjectProtoToString) { 3275 HandleScope scope(isolate); 3276 Handle<Object> object = args.at<Object>(0); 3277 Handle<String> result; 3278 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 3279 isolate, result, JSObject::ObjectProtoToString(isolate, object)); 3280 return *result; 3281 } 3282 3283 3284 // ES6 section 24.1.2.1 ArrayBuffer ( length ) for the [[Call]] case. 3285 BUILTIN(ArrayBufferConstructor) { 3286 HandleScope scope(isolate); 3287 Handle<JSFunction> target = args.target(); 3288 DCHECK(*target == target->native_context()->array_buffer_fun() || 3289 *target == target->native_context()->shared_array_buffer_fun()); 3290 THROW_NEW_ERROR_RETURN_FAILURE( 3291 isolate, NewTypeError(MessageTemplate::kConstructorNotFunction, 3292 handle(target->shared()->name(), isolate))); 3293 } 3294 3295 3296 // ES6 section 24.1.2.1 ArrayBuffer ( length ) for the [[Construct]] case. 3297 BUILTIN(ArrayBufferConstructor_ConstructStub) { 3298 HandleScope scope(isolate); 3299 Handle<JSFunction> target = args.target(); 3300 Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target()); 3301 Handle<Object> length = args.atOrUndefined(isolate, 1); 3302 DCHECK(*target == target->native_context()->array_buffer_fun() || 3303 *target == target->native_context()->shared_array_buffer_fun()); 3304 Handle<Object> number_length; 3305 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, number_length, 3306 Object::ToInteger(isolate, length)); 3307 if (number_length->Number() < 0.0) { 3308 THROW_NEW_ERROR_RETURN_FAILURE( 3309 isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferLength)); 3310 } 3311 Handle<Map> initial_map; 3312 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 3313 isolate, initial_map, 3314 JSFunction::GetDerivedMap(isolate, target, new_target)); 3315 size_t byte_length; 3316 if (!TryNumberToSize(isolate, *number_length, &byte_length)) { 3317 THROW_NEW_ERROR_RETURN_FAILURE( 3318 isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferLength)); 3319 } 3320 Handle<JSArrayBuffer> result = Handle<JSArrayBuffer>::cast( 3321 isolate->factory()->NewJSObjectFromMap(initial_map)); 3322 SharedFlag shared_flag = 3323 (*target == target->native_context()->array_buffer_fun()) 3324 ? SharedFlag::kNotShared 3325 : SharedFlag::kShared; 3326 if (!JSArrayBuffer::SetupAllocatingData(result, isolate, byte_length, true, 3327 shared_flag)) { 3328 THROW_NEW_ERROR_RETURN_FAILURE( 3329 isolate, NewRangeError(MessageTemplate::kArrayBufferAllocationFailed)); 3330 } 3331 return *result; 3332 } 3333 3334 3335 // ES6 section 24.1.3.1 ArrayBuffer.isView ( arg ) 3336 BUILTIN(ArrayBufferIsView) { 3337 SealHandleScope shs(isolate); 3338 DCHECK_EQ(2, args.length()); 3339 Object* arg = args[1]; 3340 return isolate->heap()->ToBoolean(arg->IsJSArrayBufferView()); 3341 } 3342 3343 3344 // ES6 section 26.2.1.1 Proxy ( target, handler ) for the [[Call]] case. 3345 BUILTIN(ProxyConstructor) { 3346 HandleScope scope(isolate); 3347 THROW_NEW_ERROR_RETURN_FAILURE( 3348 isolate, 3349 NewTypeError(MessageTemplate::kConstructorNotFunction, 3350 isolate->factory()->NewStringFromAsciiChecked("Proxy"))); 3351 } 3352 3353 3354 // ES6 section 26.2.1.1 Proxy ( target, handler ) for the [[Construct]] case. 3355 BUILTIN(ProxyConstructor_ConstructStub) { 3356 HandleScope scope(isolate); 3357 DCHECK(isolate->proxy_function()->IsConstructor()); 3358 Handle<Object> target = args.atOrUndefined(isolate, 1); 3359 Handle<Object> handler = args.atOrUndefined(isolate, 2); 3360 Handle<JSProxy> result; 3361 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, 3362 JSProxy::New(isolate, target, handler)); 3363 return *result; 3364 } 3365 3366 3367 // ----------------------------------------------------------------------------- 3368 // Throwers for restricted function properties and strict arguments object 3369 // properties 3370 3371 3372 BUILTIN(RestrictedFunctionPropertiesThrower) { 3373 HandleScope scope(isolate); 3374 THROW_NEW_ERROR_RETURN_FAILURE( 3375 isolate, NewTypeError(MessageTemplate::kRestrictedFunctionProperties)); 3376 } 3377 3378 3379 BUILTIN(RestrictedStrictArgumentsPropertiesThrower) { 3380 HandleScope scope(isolate); 3381 THROW_NEW_ERROR_RETURN_FAILURE( 3382 isolate, NewTypeError(MessageTemplate::kStrictPoisonPill)); 3383 } 3384 3385 3386 // ----------------------------------------------------------------------------- 3387 // 3388 3389 3390 namespace { 3391 3392 template <bool is_construct> 3393 MUST_USE_RESULT MaybeHandle<Object> HandleApiCallHelper( 3394 Isolate* isolate, BuiltinArguments<BuiltinExtraArguments::kTarget> args) { 3395 HandleScope scope(isolate); 3396 Handle<JSFunction> function = args.target(); 3397 DCHECK(args.receiver()->IsJSReceiver()); 3398 // TODO(ishell): turn this back to a DCHECK. 3399 CHECK(function->shared()->IsApiFunction()); 3400 3401 Handle<FunctionTemplateInfo> fun_data( 3402 function->shared()->get_api_func_data(), isolate); 3403 if (is_construct) { 3404 ASSIGN_RETURN_ON_EXCEPTION( 3405 isolate, fun_data, 3406 ApiNatives::ConfigureInstance(isolate, fun_data, 3407 Handle<JSObject>::cast(args.receiver())), 3408 Object); 3409 } 3410 3411 if (!is_construct && !fun_data->accept_any_receiver()) { 3412 Handle<JSReceiver> receiver = args.at<JSReceiver>(0); 3413 if (receiver->IsJSObject() && receiver->IsAccessCheckNeeded()) { 3414 Handle<JSObject> js_receiver = Handle<JSObject>::cast(receiver); 3415 if (!isolate->MayAccess(handle(isolate->context()), js_receiver)) { 3416 isolate->ReportFailedAccessCheck(js_receiver); 3417 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); 3418 } 3419 } 3420 } 3421 3422 Object* raw_holder = fun_data->GetCompatibleReceiver(isolate, args[0]); 3423 3424 if (raw_holder->IsNull()) { 3425 // This function cannot be called with the given receiver. Abort! 3426 THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kIllegalInvocation), 3427 Object); 3428 } 3429 3430 Object* raw_call_data = fun_data->call_code(); 3431 if (!raw_call_data->IsUndefined()) { 3432 // TODO(ishell): remove this debugging code. 3433 CHECK(raw_call_data->IsCallHandlerInfo()); 3434 CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data); 3435 Object* callback_obj = call_data->callback(); 3436 v8::FunctionCallback callback = 3437 v8::ToCData<v8::FunctionCallback>(callback_obj); 3438 Object* data_obj = call_data->data(); 3439 3440 LOG(isolate, ApiObjectAccess("call", JSObject::cast(*args.receiver()))); 3441 DCHECK(raw_holder->IsJSObject()); 3442 3443 FunctionCallbackArguments custom(isolate, 3444 data_obj, 3445 *function, 3446 raw_holder, 3447 &args[0] - 1, 3448 args.length() - 1, 3449 is_construct); 3450 3451 v8::Local<v8::Value> value = custom.Call(callback); 3452 Handle<Object> result; 3453 if (value.IsEmpty()) { 3454 result = isolate->factory()->undefined_value(); 3455 } else { 3456 result = v8::Utils::OpenHandle(*value); 3457 result->VerifyApiCallResultType(); 3458 } 3459 3460 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); 3461 if (!is_construct || result->IsJSObject()) { 3462 return scope.CloseAndEscape(result); 3463 } 3464 } 3465 3466 return scope.CloseAndEscape(args.receiver()); 3467 } 3468 3469 } // namespace 3470 3471 3472 BUILTIN(HandleApiCall) { 3473 HandleScope scope(isolate); 3474 Handle<Object> result; 3475 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, 3476 HandleApiCallHelper<false>(isolate, args)); 3477 return *result; 3478 } 3479 3480 3481 BUILTIN(HandleApiCallConstruct) { 3482 HandleScope scope(isolate); 3483 Handle<Object> result; 3484 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, 3485 HandleApiCallHelper<true>(isolate, args)); 3486 return *result; 3487 } 3488 3489 3490 Handle<Code> Builtins::CallFunction(ConvertReceiverMode mode) { 3491 switch (mode) { 3492 case ConvertReceiverMode::kNullOrUndefined: 3493 return CallFunction_ReceiverIsNullOrUndefined(); 3494 case ConvertReceiverMode::kNotNullOrUndefined: 3495 return CallFunction_ReceiverIsNotNullOrUndefined(); 3496 case ConvertReceiverMode::kAny: 3497 return CallFunction_ReceiverIsAny(); 3498 } 3499 UNREACHABLE(); 3500 return Handle<Code>::null(); 3501 } 3502 3503 3504 Handle<Code> Builtins::Call(ConvertReceiverMode mode) { 3505 switch (mode) { 3506 case ConvertReceiverMode::kNullOrUndefined: 3507 return Call_ReceiverIsNullOrUndefined(); 3508 case ConvertReceiverMode::kNotNullOrUndefined: 3509 return Call_ReceiverIsNotNullOrUndefined(); 3510 case ConvertReceiverMode::kAny: 3511 return Call_ReceiverIsAny(); 3512 } 3513 UNREACHABLE(); 3514 return Handle<Code>::null(); 3515 } 3516 3517 3518 namespace { 3519 3520 class RelocatableArguments 3521 : public BuiltinArguments<BuiltinExtraArguments::kTarget>, 3522 public Relocatable { 3523 public: 3524 RelocatableArguments(Isolate* isolate, int length, Object** arguments) 3525 : BuiltinArguments<BuiltinExtraArguments::kTarget>(length, arguments), 3526 Relocatable(isolate) {} 3527 3528 virtual inline void IterateInstance(ObjectVisitor* v) { 3529 if (length() == 0) return; 3530 v->VisitPointers(lowest_address(), highest_address() + 1); 3531 } 3532 3533 private: 3534 DISALLOW_COPY_AND_ASSIGN(RelocatableArguments); 3535 }; 3536 3537 } // namespace 3538 3539 3540 MaybeHandle<Object> Builtins::InvokeApiFunction(Handle<JSFunction> function, 3541 Handle<Object> receiver, 3542 int argc, 3543 Handle<Object> args[]) { 3544 // Construct BuiltinArguments object: function, arguments reversed, receiver. 3545 const int kBufferSize = 32; 3546 Object* small_argv[kBufferSize]; 3547 Object** argv; 3548 if (argc + 2 <= kBufferSize) { 3549 argv = small_argv; 3550 } else { 3551 argv = new Object* [argc + 2]; 3552 } 3553 argv[argc + 1] = *receiver; 3554 for (int i = 0; i < argc; ++i) { 3555 argv[argc - i] = *args[i]; 3556 } 3557 argv[0] = *function; 3558 MaybeHandle<Object> result; 3559 { 3560 auto isolate = function->GetIsolate(); 3561 RelocatableArguments arguments(isolate, argc + 2, &argv[argc + 1]); 3562 result = HandleApiCallHelper<false>(isolate, arguments); 3563 } 3564 if (argv != small_argv) { 3565 delete[] argv; 3566 } 3567 return result; 3568 } 3569 3570 3571 // Helper function to handle calls to non-function objects created through the 3572 // API. The object can be called as either a constructor (using new) or just as 3573 // a function (without new). 3574 MUST_USE_RESULT static Object* HandleApiCallAsFunctionOrConstructor( 3575 Isolate* isolate, bool is_construct_call, 3576 BuiltinArguments<BuiltinExtraArguments::kNone> args) { 3577 Heap* heap = isolate->heap(); 3578 3579 Handle<Object> receiver = args.receiver(); 3580 3581 // Get the object called. 3582 JSObject* obj = JSObject::cast(*receiver); 3583 3584 // Get the invocation callback from the function descriptor that was 3585 // used to create the called object. 3586 DCHECK(obj->map()->is_callable()); 3587 JSFunction* constructor = JSFunction::cast(obj->map()->GetConstructor()); 3588 // TODO(ishell): turn this back to a DCHECK. 3589 CHECK(constructor->shared()->IsApiFunction()); 3590 Object* handler = 3591 constructor->shared()->get_api_func_data()->instance_call_handler(); 3592 DCHECK(!handler->IsUndefined()); 3593 // TODO(ishell): remove this debugging code. 3594 CHECK(handler->IsCallHandlerInfo()); 3595 CallHandlerInfo* call_data = CallHandlerInfo::cast(handler); 3596 Object* callback_obj = call_data->callback(); 3597 v8::FunctionCallback callback = 3598 v8::ToCData<v8::FunctionCallback>(callback_obj); 3599 3600 // Get the data for the call and perform the callback. 3601 Object* result; 3602 { 3603 HandleScope scope(isolate); 3604 LOG(isolate, ApiObjectAccess("call non-function", obj)); 3605 3606 FunctionCallbackArguments custom(isolate, 3607 call_data->data(), 3608 constructor, 3609 obj, 3610 &args[0] - 1, 3611 args.length() - 1, 3612 is_construct_call); 3613 v8::Local<v8::Value> value = custom.Call(callback); 3614 if (value.IsEmpty()) { 3615 result = heap->undefined_value(); 3616 } else { 3617 result = *reinterpret_cast<Object**>(*value); 3618 result->VerifyApiCallResultType(); 3619 } 3620 } 3621 // Check for exceptions and return result. 3622 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); 3623 return result; 3624 } 3625 3626 3627 // Handle calls to non-function objects created through the API. This delegate 3628 // function is used when the call is a normal function call. 3629 BUILTIN(HandleApiCallAsFunction) { 3630 return HandleApiCallAsFunctionOrConstructor(isolate, false, args); 3631 } 3632 3633 3634 // Handle calls to non-function objects created through the API. This delegate 3635 // function is used when the call is a construct call. 3636 BUILTIN(HandleApiCallAsConstructor) { 3637 return HandleApiCallAsFunctionOrConstructor(isolate, true, args); 3638 } 3639 3640 3641 static void Generate_LoadIC_Miss(MacroAssembler* masm) { 3642 LoadIC::GenerateMiss(masm); 3643 } 3644 3645 3646 static void Generate_LoadIC_Normal(MacroAssembler* masm) { 3647 LoadIC::GenerateNormal(masm, SLOPPY); 3648 } 3649 3650 3651 static void Generate_LoadIC_Normal_Strong(MacroAssembler* masm) { 3652 LoadIC::GenerateNormal(masm, STRONG); 3653 } 3654 3655 3656 static void Generate_LoadIC_Getter_ForDeopt(MacroAssembler* masm) { 3657 NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(masm); 3658 } 3659 3660 3661 static void Generate_LoadIC_Slow(MacroAssembler* masm) { 3662 LoadIC::GenerateRuntimeGetProperty(masm, SLOPPY); 3663 } 3664 3665 3666 static void Generate_LoadIC_Slow_Strong(MacroAssembler* masm) { 3667 LoadIC::GenerateRuntimeGetProperty(masm, STRONG); 3668 } 3669 3670 3671 static void Generate_KeyedLoadIC_Slow(MacroAssembler* masm) { 3672 KeyedLoadIC::GenerateRuntimeGetProperty(masm, SLOPPY); 3673 } 3674 3675 3676 static void Generate_KeyedLoadIC_Slow_Strong(MacroAssembler* masm) { 3677 KeyedLoadIC::GenerateRuntimeGetProperty(masm, STRONG); 3678 } 3679 3680 3681 static void Generate_KeyedLoadIC_Miss(MacroAssembler* masm) { 3682 KeyedLoadIC::GenerateMiss(masm); 3683 } 3684 3685 3686 static void Generate_KeyedLoadIC_Megamorphic(MacroAssembler* masm) { 3687 KeyedLoadIC::GenerateMegamorphic(masm, SLOPPY); 3688 } 3689 3690 3691 static void Generate_KeyedLoadIC_Megamorphic_Strong(MacroAssembler* masm) { 3692 KeyedLoadIC::GenerateMegamorphic(masm, STRONG); 3693 } 3694 3695 3696 static void Generate_StoreIC_Miss(MacroAssembler* masm) { 3697 StoreIC::GenerateMiss(masm); 3698 } 3699 3700 3701 static void Generate_StoreIC_Normal(MacroAssembler* masm) { 3702 StoreIC::GenerateNormal(masm); 3703 } 3704 3705 3706 static void Generate_StoreIC_Slow(MacroAssembler* masm) { 3707 NamedStoreHandlerCompiler::GenerateSlow(masm); 3708 } 3709 3710 3711 static void Generate_KeyedStoreIC_Slow(MacroAssembler* masm) { 3712 ElementHandlerCompiler::GenerateStoreSlow(masm); 3713 } 3714 3715 3716 static void Generate_StoreIC_Setter_ForDeopt(MacroAssembler* masm) { 3717 NamedStoreHandlerCompiler::GenerateStoreViaSetterForDeopt(masm); 3718 } 3719 3720 3721 static void Generate_KeyedStoreIC_Megamorphic(MacroAssembler* masm) { 3722 KeyedStoreIC::GenerateMegamorphic(masm, SLOPPY); 3723 } 3724 3725 3726 static void Generate_KeyedStoreIC_Megamorphic_Strict(MacroAssembler* masm) { 3727 KeyedStoreIC::GenerateMegamorphic(masm, STRICT); 3728 } 3729 3730 3731 static void Generate_KeyedStoreIC_Miss(MacroAssembler* masm) { 3732 KeyedStoreIC::GenerateMiss(masm); 3733 } 3734 3735 3736 static void Generate_KeyedStoreIC_Initialize(MacroAssembler* masm) { 3737 KeyedStoreIC::GenerateInitialize(masm); 3738 } 3739 3740 3741 static void Generate_KeyedStoreIC_Initialize_Strict(MacroAssembler* masm) { 3742 KeyedStoreIC::GenerateInitialize(masm); 3743 } 3744 3745 3746 static void Generate_KeyedStoreIC_PreMonomorphic(MacroAssembler* masm) { 3747 KeyedStoreIC::GeneratePreMonomorphic(masm); 3748 } 3749 3750 3751 static void Generate_KeyedStoreIC_PreMonomorphic_Strict(MacroAssembler* masm) { 3752 KeyedStoreIC::GeneratePreMonomorphic(masm); 3753 } 3754 3755 3756 static void Generate_Return_DebugBreak(MacroAssembler* masm) { 3757 DebugCodegen::GenerateDebugBreakStub(masm, 3758 DebugCodegen::SAVE_RESULT_REGISTER); 3759 } 3760 3761 3762 static void Generate_Slot_DebugBreak(MacroAssembler* masm) { 3763 DebugCodegen::GenerateDebugBreakStub(masm, 3764 DebugCodegen::IGNORE_RESULT_REGISTER); 3765 } 3766 3767 3768 static void Generate_FrameDropper_LiveEdit(MacroAssembler* masm) { 3769 DebugCodegen::GenerateFrameDropperLiveEdit(masm); 3770 } 3771 3772 3773 Builtins::Builtins() : initialized_(false) { 3774 memset(builtins_, 0, sizeof(builtins_[0]) * builtin_count); 3775 memset(names_, 0, sizeof(names_[0]) * builtin_count); 3776 } 3777 3778 3779 Builtins::~Builtins() { 3780 } 3781 3782 3783 #define DEF_ENUM_C(name, ignore) FUNCTION_ADDR(Builtin_##name), 3784 Address const Builtins::c_functions_[cfunction_count] = { 3785 BUILTIN_LIST_C(DEF_ENUM_C) 3786 }; 3787 #undef DEF_ENUM_C 3788 3789 3790 struct BuiltinDesc { 3791 byte* generator; 3792 byte* c_code; 3793 const char* s_name; // name is only used for generating log information. 3794 int name; 3795 Code::Flags flags; 3796 BuiltinExtraArguments extra_args; 3797 }; 3798 3799 #define BUILTIN_FUNCTION_TABLE_INIT { V8_ONCE_INIT, {} } 3800 3801 class BuiltinFunctionTable { 3802 public: 3803 BuiltinDesc* functions() { 3804 base::CallOnce(&once_, &Builtins::InitBuiltinFunctionTable); 3805 return functions_; 3806 } 3807 3808 base::OnceType once_; 3809 BuiltinDesc functions_[Builtins::builtin_count + 1]; 3810 3811 friend class Builtins; 3812 }; 3813 3814 static BuiltinFunctionTable builtin_function_table = 3815 BUILTIN_FUNCTION_TABLE_INIT; 3816 3817 // Define array of pointers to generators and C builtin functions. 3818 // We do this in a sort of roundabout way so that we can do the initialization 3819 // within the lexical scope of Builtins:: and within a context where 3820 // Code::Flags names a non-abstract type. 3821 void Builtins::InitBuiltinFunctionTable() { 3822 BuiltinDesc* functions = builtin_function_table.functions_; 3823 functions[builtin_count].generator = NULL; 3824 functions[builtin_count].c_code = NULL; 3825 functions[builtin_count].s_name = NULL; 3826 functions[builtin_count].name = builtin_count; 3827 functions[builtin_count].flags = static_cast<Code::Flags>(0); 3828 functions[builtin_count].extra_args = BuiltinExtraArguments::kNone; 3829 3830 #define DEF_FUNCTION_PTR_C(aname, aextra_args) \ 3831 functions->generator = FUNCTION_ADDR(Generate_Adaptor); \ 3832 functions->c_code = FUNCTION_ADDR(Builtin_##aname); \ 3833 functions->s_name = #aname; \ 3834 functions->name = c_##aname; \ 3835 functions->flags = Code::ComputeFlags(Code::BUILTIN); \ 3836 functions->extra_args = BuiltinExtraArguments::aextra_args; \ 3837 ++functions; 3838 3839 #define DEF_FUNCTION_PTR_A(aname, kind, state, extra) \ 3840 functions->generator = FUNCTION_ADDR(Generate_##aname); \ 3841 functions->c_code = NULL; \ 3842 functions->s_name = #aname; \ 3843 functions->name = k##aname; \ 3844 functions->flags = Code::ComputeFlags(Code::kind, state, extra); \ 3845 functions->extra_args = BuiltinExtraArguments::kNone; \ 3846 ++functions; 3847 3848 #define DEF_FUNCTION_PTR_H(aname, kind) \ 3849 functions->generator = FUNCTION_ADDR(Generate_##aname); \ 3850 functions->c_code = NULL; \ 3851 functions->s_name = #aname; \ 3852 functions->name = k##aname; \ 3853 functions->flags = Code::ComputeHandlerFlags(Code::kind); \ 3854 functions->extra_args = BuiltinExtraArguments::kNone; \ 3855 ++functions; 3856 3857 BUILTIN_LIST_C(DEF_FUNCTION_PTR_C) 3858 BUILTIN_LIST_A(DEF_FUNCTION_PTR_A) 3859 BUILTIN_LIST_H(DEF_FUNCTION_PTR_H) 3860 BUILTIN_LIST_DEBUG_A(DEF_FUNCTION_PTR_A) 3861 3862 #undef DEF_FUNCTION_PTR_C 3863 #undef DEF_FUNCTION_PTR_A 3864 } 3865 3866 3867 void Builtins::SetUp(Isolate* isolate, bool create_heap_objects) { 3868 DCHECK(!initialized_); 3869 3870 // Create a scope for the handles in the builtins. 3871 HandleScope scope(isolate); 3872 3873 const BuiltinDesc* functions = builtin_function_table.functions(); 3874 3875 // For now we generate builtin adaptor code into a stack-allocated 3876 // buffer, before copying it into individual code objects. Be careful 3877 // with alignment, some platforms don't like unaligned code. 3878 #ifdef DEBUG 3879 // We can generate a lot of debug code on Arm64. 3880 const size_t buffer_size = 32*KB; 3881 #elif V8_TARGET_ARCH_PPC64 3882 // 8 KB is insufficient on PPC64 when FLAG_debug_code is on. 3883 const size_t buffer_size = 10 * KB; 3884 #else 3885 const size_t buffer_size = 8*KB; 3886 #endif 3887 union { int force_alignment; byte buffer[buffer_size]; } u; 3888 3889 // Traverse the list of builtins and generate an adaptor in a 3890 // separate code object for each one. 3891 for (int i = 0; i < builtin_count; i++) { 3892 if (create_heap_objects) { 3893 MacroAssembler masm(isolate, u.buffer, sizeof u.buffer, 3894 CodeObjectRequired::kYes); 3895 // Generate the code/adaptor. 3896 typedef void (*Generator)(MacroAssembler*, int, BuiltinExtraArguments); 3897 Generator g = FUNCTION_CAST<Generator>(functions[i].generator); 3898 // We pass all arguments to the generator, but it may not use all of 3899 // them. This works because the first arguments are on top of the 3900 // stack. 3901 DCHECK(!masm.has_frame()); 3902 g(&masm, functions[i].name, functions[i].extra_args); 3903 // Move the code into the object heap. 3904 CodeDesc desc; 3905 masm.GetCode(&desc); 3906 Code::Flags flags = functions[i].flags; 3907 Handle<Code> code = 3908 isolate->factory()->NewCode(desc, flags, masm.CodeObject()); 3909 // Log the event and add the code to the builtins array. 3910 PROFILE(isolate, 3911 CodeCreateEvent(Logger::BUILTIN_TAG, *code, functions[i].s_name)); 3912 builtins_[i] = *code; 3913 code->set_builtin_index(i); 3914 #ifdef ENABLE_DISASSEMBLER 3915 if (FLAG_print_builtin_code) { 3916 CodeTracer::Scope trace_scope(isolate->GetCodeTracer()); 3917 OFStream os(trace_scope.file()); 3918 os << "Builtin: " << functions[i].s_name << "\n"; 3919 code->Disassemble(functions[i].s_name, os); 3920 os << "\n"; 3921 } 3922 #endif 3923 } else { 3924 // Deserializing. The values will be filled in during IterateBuiltins. 3925 builtins_[i] = NULL; 3926 } 3927 names_[i] = functions[i].s_name; 3928 } 3929 3930 // Mark as initialized. 3931 initialized_ = true; 3932 } 3933 3934 3935 void Builtins::TearDown() { 3936 initialized_ = false; 3937 } 3938 3939 3940 void Builtins::IterateBuiltins(ObjectVisitor* v) { 3941 v->VisitPointers(&builtins_[0], &builtins_[0] + builtin_count); 3942 } 3943 3944 3945 const char* Builtins::Lookup(byte* pc) { 3946 // may be called during initialization (disassembler!) 3947 if (initialized_) { 3948 for (int i = 0; i < builtin_count; i++) { 3949 Code* entry = Code::cast(builtins_[i]); 3950 if (entry->contains(pc)) { 3951 return names_[i]; 3952 } 3953 } 3954 } 3955 return NULL; 3956 } 3957 3958 3959 void Builtins::Generate_InterruptCheck(MacroAssembler* masm) { 3960 masm->TailCallRuntime(Runtime::kInterrupt); 3961 } 3962 3963 3964 void Builtins::Generate_StackCheck(MacroAssembler* masm) { 3965 masm->TailCallRuntime(Runtime::kStackGuard); 3966 } 3967 3968 3969 #define DEFINE_BUILTIN_ACCESSOR_C(name, ignore) \ 3970 Handle<Code> Builtins::name() { \ 3971 Code** code_address = \ 3972 reinterpret_cast<Code**>(builtin_address(k##name)); \ 3973 return Handle<Code>(code_address); \ 3974 } 3975 #define DEFINE_BUILTIN_ACCESSOR_A(name, kind, state, extra) \ 3976 Handle<Code> Builtins::name() { \ 3977 Code** code_address = \ 3978 reinterpret_cast<Code**>(builtin_address(k##name)); \ 3979 return Handle<Code>(code_address); \ 3980 } 3981 #define DEFINE_BUILTIN_ACCESSOR_H(name, kind) \ 3982 Handle<Code> Builtins::name() { \ 3983 Code** code_address = \ 3984 reinterpret_cast<Code**>(builtin_address(k##name)); \ 3985 return Handle<Code>(code_address); \ 3986 } 3987 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) 3988 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) 3989 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) 3990 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) 3991 #undef DEFINE_BUILTIN_ACCESSOR_C 3992 #undef DEFINE_BUILTIN_ACCESSOR_A 3993 3994 3995 } // namespace internal 3996 } // namespace v8 3997