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:
BuiltinArguments(int length,Object ** arguments)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
operator [](int index)41 Object*& operator[] (int index) {
42 DCHECK(index < length());
43 return Arguments::operator[](index);
44 }
45
at(int index)46 template <class S> Handle<S> at(int index) {
47 DCHECK(index < length());
48 return Arguments::at<S>(index);
49 }
50
atOrUndefined(Isolate * isolate,int index)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
receiver()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 <>
length() const74 int BuiltinArguments<BuiltinExtraArguments::kNone>::length() const {
75 return Arguments::length();
76 }
77
78 template <>
length() const79 int BuiltinArguments<BuiltinExtraArguments::kTarget>::length() const {
80 return Arguments::length() - 1;
81 }
82
83 template <>
target()84 Handle<JSFunction> BuiltinArguments<BuiltinExtraArguments::kTarget>::target() {
85 return Arguments::at<JSFunction>(Arguments::length() - 1);
86 }
87
88 template <>
length() const89 int BuiltinArguments<BuiltinExtraArguments::kNewTarget>::length() const {
90 return Arguments::length() - 1;
91 }
92
93 template <>
94 Handle<HeapObject>
new_target()95 BuiltinArguments<BuiltinExtraArguments::kNewTarget>::new_target() {
96 return Arguments::at<HeapObject>(Arguments::length() - 1);
97 }
98
99 template <>
length() const100 int BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>::length()
101 const {
102 return Arguments::length() - 2;
103 }
104
105 template <>
106 Handle<JSFunction>
target()107 BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>::target() {
108 return Arguments::at<JSFunction>(Arguments::length() - 2);
109 }
110
111 template <>
112 Handle<HeapObject>
new_target()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;
BUILTIN_LIST_C(DEF_ARG_TYPE)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
GetSloppyArgumentsLength(Isolate * isolate,Handle<JSObject> object,int * out)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
PrototypeHasNoElements(PrototypeIterator * iter)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
IsJSArrayFastElementMovingAllowed(Isolate * isolate,JSArray * receiver)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
EnsureJSArrayWithWritableFastElements(Isolate * isolate,Handle<Object> receiver,Arguments * args,int first_added_arg)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
CallJsIntrinsic(Isolate * isolate,Handle<JSFunction> function,BuiltinArguments<BuiltinExtraArguments::kNone> args)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
BUILTIN(Illegal)325 BUILTIN(Illegal) {
326 UNREACHABLE();
327 return isolate->heap()->undefined_value(); // Make compiler happy.
328 }
329
330
BUILTIN(EmptyFunction)331 BUILTIN(EmptyFunction) { return isolate->heap()->undefined_value(); }
332
333
BUILTIN(ArrayPush)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
BUILTIN(ArrayPop)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
BUILTIN(ArrayShift)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
BUILTIN(ArrayUnshift)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
BUILTIN(ArraySlice)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
BUILTIN(ArraySplice)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:
ArrayConcatVisitor(Isolate * isolate,Handle<FixedArray> storage,bool fast_elements)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
~ArrayConcatVisitor()639 ~ArrayConcatVisitor() { clear_storage(); }
640
visit(uint32_t i,Handle<Object> elm)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
increase_index_offset(uint32_t delta)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
exceeds_array_limit() const690 bool exceeds_array_limit() const {
691 return ExceedsLimitField::decode(bit_field_);
692 }
693
ToArray()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.
SetDictionaryMode()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
clear_storage()733 inline void clear_storage() {
734 GlobalHandles::Destroy(Handle<Object>::cast(storage_).location());
735 }
736
set_storage(FixedArray * storage)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
fast_elements() const745 bool fast_elements() const { return FastElementsField::decode(bit_field_); }
set_fast_elements(bool fast)746 void set_fast_elements(bool fast) {
747 bit_field_ = FastElementsField::update(bit_field_, fast);
748 }
set_exceeds_array_limit(bool exceeds)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
EstimateElementCount(Handle<JSArray> array)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>
IterateTypedArrayElements(Isolate * isolate,Handle<JSObject> receiver,bool elements_are_ints,bool elements_are_guaranteed_smis,ArrayConcatVisitor * visitor)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>.
compareUInt32(const uint32_t * ap,const uint32_t * bp)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
CollectElementIndices(Handle<JSObject> object,uint32_t range,List<uint32_t> * indices)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
IterateElementsSlow(Isolate * isolate,Handle<JSReceiver> receiver,uint32_t length,ArrayConcatVisitor * visitor)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 */
IterateElements(Isolate * isolate,Handle<JSReceiver> receiver,ArrayConcatVisitor * visitor)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
HasConcatSpreadableModifier(Isolate * isolate,Handle<JSArray> obj)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
IsConcatSpreadable(Isolate * isolate,Handle<Object> obj)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
Slow_ArrayConcat(Arguments * args,Isolate * isolate)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
Fast_ArrayConcat(Isolate * isolate,Arguments * args)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
BUILTIN(ArrayConcat)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
BUILTIN(ArrayIsArray)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
BUILTIN(ObjectAssign)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 ] )
BUILTIN(ObjectCreate)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 )
BUILTIN(ObjectFreeze)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 )
BUILTIN(ObjectIsExtensible)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 )
BUILTIN(ObjectIsFrozen)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 )
BUILTIN(ObjectIsSealed)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 )
BUILTIN(ObjectKeys)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 )
BUILTIN(ObjectPreventExtensions)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 )
BUILTIN(ObjectSeal)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
CodeGenerationFromStringsAllowed(Isolate * isolate,Handle<Context> context)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
CompileString(Handle<Context> context,Handle<String> source,ParseRestriction restriction)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)
BUILTIN(GlobalEval)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
BUILTIN(ReflectDefineProperty)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
BUILTIN(ReflectDeleteProperty)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
BUILTIN(ReflectGet)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
BUILTIN(ReflectGetOwnPropertyDescriptor)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
BUILTIN(ReflectGetPrototypeOf)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
BUILTIN(ReflectHas)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
BUILTIN(ReflectIsExtensible)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
BUILTIN(ReflectOwnKeys)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
BUILTIN(ReflectPreventExtensions)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
BUILTIN(ReflectSet)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
BUILTIN(ReflectSetPrototypeOf)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)
MakeDate(double day,double 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)
MakeDay(double year,double month,double 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)
MakeTime(double hour,double min,double sec,double 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)
TimeClip(double 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
ParseDateTimeString(Handle<String> str)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)
ToDateString(double time_val,Vector<char> str,DateCache * date_cache,ToDateStringMode mode=kDateAndTime)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
SetLocalDateValue(Handle<JSDate> date,double time_val)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.
BUILTIN(DateConstructor)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.
BUILTIN(DateConstructor_ConstructStub)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 ( )
BUILTIN(DateNow)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 )
BUILTIN(DateParse)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)
BUILTIN(DateUTC)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 )
BUILTIN(DatePrototypeSetDate)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)
BUILTIN(DatePrototypeSetFullYear)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)
BUILTIN(DatePrototypeSetHours)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)
BUILTIN(DatePrototypeSetMilliseconds)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 )
BUILTIN(DatePrototypeSetMinutes)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 )
BUILTIN(DatePrototypeSetMonth)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 )
BUILTIN(DatePrototypeSetSeconds)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 )
BUILTIN(DatePrototypeSetTime)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 )
BUILTIN(DatePrototypeSetUTCDate)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)
BUILTIN(DatePrototypeSetUTCFullYear)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)
BUILTIN(DatePrototypeSetUTCHours)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)
BUILTIN(DatePrototypeSetUTCMilliseconds)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 )
BUILTIN(DatePrototypeSetUTCMinutes)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 )
BUILTIN(DatePrototypeSetUTCMonth)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 )
BUILTIN(DatePrototypeSetUTCSeconds)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 ( )
BUILTIN(DatePrototypeToDateString)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 ( )
BUILTIN(DatePrototypeToISOString)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 ( )
BUILTIN(DatePrototypeToString)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 ( )
BUILTIN(DatePrototypeToTimeString)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 ( )
BUILTIN(DatePrototypeToUTCString)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 ( )
BUILTIN(DatePrototypeValueOf)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 )
BUILTIN(DatePrototypeToPrimitive)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 ( )
BUILTIN(DatePrototypeGetYear)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 )
BUILTIN(DatePrototypeSetYear)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
Generate_DatePrototypeGetDate(MacroAssembler * masm)2928 void Builtins::Generate_DatePrototypeGetDate(MacroAssembler* masm) {
2929 Generate_DatePrototype_GetField(masm, JSDate::kDay);
2930 }
2931
2932
2933 // static
Generate_DatePrototypeGetDay(MacroAssembler * masm)2934 void Builtins::Generate_DatePrototypeGetDay(MacroAssembler* masm) {
2935 Generate_DatePrototype_GetField(masm, JSDate::kWeekday);
2936 }
2937
2938
2939 // static
Generate_DatePrototypeGetFullYear(MacroAssembler * masm)2940 void Builtins::Generate_DatePrototypeGetFullYear(MacroAssembler* masm) {
2941 Generate_DatePrototype_GetField(masm, JSDate::kYear);
2942 }
2943
2944
2945 // static
Generate_DatePrototypeGetHours(MacroAssembler * masm)2946 void Builtins::Generate_DatePrototypeGetHours(MacroAssembler* masm) {
2947 Generate_DatePrototype_GetField(masm, JSDate::kHour);
2948 }
2949
2950
2951 // static
Generate_DatePrototypeGetMilliseconds(MacroAssembler * masm)2952 void Builtins::Generate_DatePrototypeGetMilliseconds(MacroAssembler* masm) {
2953 Generate_DatePrototype_GetField(masm, JSDate::kMillisecond);
2954 }
2955
2956
2957 // static
Generate_DatePrototypeGetMinutes(MacroAssembler * masm)2958 void Builtins::Generate_DatePrototypeGetMinutes(MacroAssembler* masm) {
2959 Generate_DatePrototype_GetField(masm, JSDate::kMinute);
2960 }
2961
2962
2963 // static
Generate_DatePrototypeGetMonth(MacroAssembler * masm)2964 void Builtins::Generate_DatePrototypeGetMonth(MacroAssembler* masm) {
2965 Generate_DatePrototype_GetField(masm, JSDate::kMonth);
2966 }
2967
2968
2969 // static
Generate_DatePrototypeGetSeconds(MacroAssembler * masm)2970 void Builtins::Generate_DatePrototypeGetSeconds(MacroAssembler* masm) {
2971 Generate_DatePrototype_GetField(masm, JSDate::kSecond);
2972 }
2973
2974
2975 // static
Generate_DatePrototypeGetTime(MacroAssembler * masm)2976 void Builtins::Generate_DatePrototypeGetTime(MacroAssembler* masm) {
2977 Generate_DatePrototype_GetField(masm, JSDate::kDateValue);
2978 }
2979
2980
2981 // static
Generate_DatePrototypeGetTimezoneOffset(MacroAssembler * masm)2982 void Builtins::Generate_DatePrototypeGetTimezoneOffset(MacroAssembler* masm) {
2983 Generate_DatePrototype_GetField(masm, JSDate::kTimezoneOffset);
2984 }
2985
2986
2987 // static
Generate_DatePrototypeGetUTCDate(MacroAssembler * masm)2988 void Builtins::Generate_DatePrototypeGetUTCDate(MacroAssembler* masm) {
2989 Generate_DatePrototype_GetField(masm, JSDate::kDayUTC);
2990 }
2991
2992
2993 // static
Generate_DatePrototypeGetUTCDay(MacroAssembler * masm)2994 void Builtins::Generate_DatePrototypeGetUTCDay(MacroAssembler* masm) {
2995 Generate_DatePrototype_GetField(masm, JSDate::kWeekdayUTC);
2996 }
2997
2998
2999 // static
Generate_DatePrototypeGetUTCFullYear(MacroAssembler * masm)3000 void Builtins::Generate_DatePrototypeGetUTCFullYear(MacroAssembler* masm) {
3001 Generate_DatePrototype_GetField(masm, JSDate::kYearUTC);
3002 }
3003
3004
3005 // static
Generate_DatePrototypeGetUTCHours(MacroAssembler * masm)3006 void Builtins::Generate_DatePrototypeGetUTCHours(MacroAssembler* masm) {
3007 Generate_DatePrototype_GetField(masm, JSDate::kHourUTC);
3008 }
3009
3010
3011 // static
Generate_DatePrototypeGetUTCMilliseconds(MacroAssembler * masm)3012 void Builtins::Generate_DatePrototypeGetUTCMilliseconds(MacroAssembler* masm) {
3013 Generate_DatePrototype_GetField(masm, JSDate::kMillisecondUTC);
3014 }
3015
3016
3017 // static
Generate_DatePrototypeGetUTCMinutes(MacroAssembler * masm)3018 void Builtins::Generate_DatePrototypeGetUTCMinutes(MacroAssembler* masm) {
3019 Generate_DatePrototype_GetField(masm, JSDate::kMinuteUTC);
3020 }
3021
3022
3023 // static
Generate_DatePrototypeGetUTCMonth(MacroAssembler * masm)3024 void Builtins::Generate_DatePrototypeGetUTCMonth(MacroAssembler* masm) {
3025 Generate_DatePrototype_GetField(masm, JSDate::kMonthUTC);
3026 }
3027
3028
3029 // static
Generate_DatePrototypeGetUTCSeconds(MacroAssembler * masm)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
CreateDynamicFunction(Isolate * isolate,BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget> args,const char * token)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 )
BUILTIN(FunctionConstructor)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 )
BUILTIN(FunctionPrototypeBind)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 ( )
BUILTIN(FunctionPrototypeToString)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)
BUILTIN(GeneratorFunctionConstructor)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.
BUILTIN(SymbolConstructor)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.
BUILTIN(SymbolConstructor_ConstructStub)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
BUILTIN(ObjectProtoToString)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.
BUILTIN(ArrayBufferConstructor)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.
BUILTIN(ArrayBufferConstructor_ConstructStub)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 )
BUILTIN(ArrayBufferIsView)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.
BUILTIN(ProxyConstructor)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.
BUILTIN(ProxyConstructor_ConstructStub)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
BUILTIN(RestrictedFunctionPropertiesThrower)3372 BUILTIN(RestrictedFunctionPropertiesThrower) {
3373 HandleScope scope(isolate);
3374 THROW_NEW_ERROR_RETURN_FAILURE(
3375 isolate, NewTypeError(MessageTemplate::kRestrictedFunctionProperties));
3376 }
3377
3378
BUILTIN(RestrictedStrictArgumentsPropertiesThrower)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>
HandleApiCallHelper(Isolate * isolate,BuiltinArguments<BuiltinExtraArguments::kTarget> args)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
BUILTIN(HandleApiCall)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
BUILTIN(HandleApiCallConstruct)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
CallFunction(ConvertReceiverMode mode)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
Call(ConvertReceiverMode mode)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:
RelocatableArguments(Isolate * isolate,int length,Object ** arguments)3524 RelocatableArguments(Isolate* isolate, int length, Object** arguments)
3525 : BuiltinArguments<BuiltinExtraArguments::kTarget>(length, arguments),
3526 Relocatable(isolate) {}
3527
IterateInstance(ObjectVisitor * v)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
InvokeApiFunction(Handle<JSFunction> function,Handle<Object> receiver,int argc,Handle<Object> args[])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).
HandleApiCallAsFunctionOrConstructor(Isolate * isolate,bool is_construct_call,BuiltinArguments<BuiltinExtraArguments::kNone> args)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.
BUILTIN(HandleApiCallAsFunction)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.
BUILTIN(HandleApiCallAsConstructor)3636 BUILTIN(HandleApiCallAsConstructor) {
3637 return HandleApiCallAsFunctionOrConstructor(isolate, true, args);
3638 }
3639
3640
Generate_LoadIC_Miss(MacroAssembler * masm)3641 static void Generate_LoadIC_Miss(MacroAssembler* masm) {
3642 LoadIC::GenerateMiss(masm);
3643 }
3644
3645
Generate_LoadIC_Normal(MacroAssembler * masm)3646 static void Generate_LoadIC_Normal(MacroAssembler* masm) {
3647 LoadIC::GenerateNormal(masm, SLOPPY);
3648 }
3649
3650
Generate_LoadIC_Normal_Strong(MacroAssembler * masm)3651 static void Generate_LoadIC_Normal_Strong(MacroAssembler* masm) {
3652 LoadIC::GenerateNormal(masm, STRONG);
3653 }
3654
3655
Generate_LoadIC_Getter_ForDeopt(MacroAssembler * masm)3656 static void Generate_LoadIC_Getter_ForDeopt(MacroAssembler* masm) {
3657 NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(masm);
3658 }
3659
3660
Generate_LoadIC_Slow(MacroAssembler * masm)3661 static void Generate_LoadIC_Slow(MacroAssembler* masm) {
3662 LoadIC::GenerateRuntimeGetProperty(masm, SLOPPY);
3663 }
3664
3665
Generate_LoadIC_Slow_Strong(MacroAssembler * masm)3666 static void Generate_LoadIC_Slow_Strong(MacroAssembler* masm) {
3667 LoadIC::GenerateRuntimeGetProperty(masm, STRONG);
3668 }
3669
3670
Generate_KeyedLoadIC_Slow(MacroAssembler * masm)3671 static void Generate_KeyedLoadIC_Slow(MacroAssembler* masm) {
3672 KeyedLoadIC::GenerateRuntimeGetProperty(masm, SLOPPY);
3673 }
3674
3675
Generate_KeyedLoadIC_Slow_Strong(MacroAssembler * masm)3676 static void Generate_KeyedLoadIC_Slow_Strong(MacroAssembler* masm) {
3677 KeyedLoadIC::GenerateRuntimeGetProperty(masm, STRONG);
3678 }
3679
3680
Generate_KeyedLoadIC_Miss(MacroAssembler * masm)3681 static void Generate_KeyedLoadIC_Miss(MacroAssembler* masm) {
3682 KeyedLoadIC::GenerateMiss(masm);
3683 }
3684
3685
Generate_KeyedLoadIC_Megamorphic(MacroAssembler * masm)3686 static void Generate_KeyedLoadIC_Megamorphic(MacroAssembler* masm) {
3687 KeyedLoadIC::GenerateMegamorphic(masm, SLOPPY);
3688 }
3689
3690
Generate_KeyedLoadIC_Megamorphic_Strong(MacroAssembler * masm)3691 static void Generate_KeyedLoadIC_Megamorphic_Strong(MacroAssembler* masm) {
3692 KeyedLoadIC::GenerateMegamorphic(masm, STRONG);
3693 }
3694
3695
Generate_StoreIC_Miss(MacroAssembler * masm)3696 static void Generate_StoreIC_Miss(MacroAssembler* masm) {
3697 StoreIC::GenerateMiss(masm);
3698 }
3699
3700
Generate_StoreIC_Normal(MacroAssembler * masm)3701 static void Generate_StoreIC_Normal(MacroAssembler* masm) {
3702 StoreIC::GenerateNormal(masm);
3703 }
3704
3705
Generate_StoreIC_Slow(MacroAssembler * masm)3706 static void Generate_StoreIC_Slow(MacroAssembler* masm) {
3707 NamedStoreHandlerCompiler::GenerateSlow(masm);
3708 }
3709
3710
Generate_KeyedStoreIC_Slow(MacroAssembler * masm)3711 static void Generate_KeyedStoreIC_Slow(MacroAssembler* masm) {
3712 ElementHandlerCompiler::GenerateStoreSlow(masm);
3713 }
3714
3715
Generate_StoreIC_Setter_ForDeopt(MacroAssembler * masm)3716 static void Generate_StoreIC_Setter_ForDeopt(MacroAssembler* masm) {
3717 NamedStoreHandlerCompiler::GenerateStoreViaSetterForDeopt(masm);
3718 }
3719
3720
Generate_KeyedStoreIC_Megamorphic(MacroAssembler * masm)3721 static void Generate_KeyedStoreIC_Megamorphic(MacroAssembler* masm) {
3722 KeyedStoreIC::GenerateMegamorphic(masm, SLOPPY);
3723 }
3724
3725
Generate_KeyedStoreIC_Megamorphic_Strict(MacroAssembler * masm)3726 static void Generate_KeyedStoreIC_Megamorphic_Strict(MacroAssembler* masm) {
3727 KeyedStoreIC::GenerateMegamorphic(masm, STRICT);
3728 }
3729
3730
Generate_KeyedStoreIC_Miss(MacroAssembler * masm)3731 static void Generate_KeyedStoreIC_Miss(MacroAssembler* masm) {
3732 KeyedStoreIC::GenerateMiss(masm);
3733 }
3734
3735
Generate_KeyedStoreIC_Initialize(MacroAssembler * masm)3736 static void Generate_KeyedStoreIC_Initialize(MacroAssembler* masm) {
3737 KeyedStoreIC::GenerateInitialize(masm);
3738 }
3739
3740
Generate_KeyedStoreIC_Initialize_Strict(MacroAssembler * masm)3741 static void Generate_KeyedStoreIC_Initialize_Strict(MacroAssembler* masm) {
3742 KeyedStoreIC::GenerateInitialize(masm);
3743 }
3744
3745
Generate_KeyedStoreIC_PreMonomorphic(MacroAssembler * masm)3746 static void Generate_KeyedStoreIC_PreMonomorphic(MacroAssembler* masm) {
3747 KeyedStoreIC::GeneratePreMonomorphic(masm);
3748 }
3749
3750
Generate_KeyedStoreIC_PreMonomorphic_Strict(MacroAssembler * masm)3751 static void Generate_KeyedStoreIC_PreMonomorphic_Strict(MacroAssembler* masm) {
3752 KeyedStoreIC::GeneratePreMonomorphic(masm);
3753 }
3754
3755
Generate_Return_DebugBreak(MacroAssembler * masm)3756 static void Generate_Return_DebugBreak(MacroAssembler* masm) {
3757 DebugCodegen::GenerateDebugBreakStub(masm,
3758 DebugCodegen::SAVE_RESULT_REGISTER);
3759 }
3760
3761
Generate_Slot_DebugBreak(MacroAssembler * masm)3762 static void Generate_Slot_DebugBreak(MacroAssembler* masm) {
3763 DebugCodegen::GenerateDebugBreakStub(masm,
3764 DebugCodegen::IGNORE_RESULT_REGISTER);
3765 }
3766
3767
Generate_FrameDropper_LiveEdit(MacroAssembler * masm)3768 static void Generate_FrameDropper_LiveEdit(MacroAssembler* masm) {
3769 DebugCodegen::GenerateFrameDropperLiveEdit(masm);
3770 }
3771
3772
Builtins()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
~Builtins()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:
functions()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.
InitBuiltinFunctionTable()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
SetUp(Isolate * isolate,bool create_heap_objects)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
TearDown()3935 void Builtins::TearDown() {
3936 initialized_ = false;
3937 }
3938
3939
IterateBuiltins(ObjectVisitor * v)3940 void Builtins::IterateBuiltins(ObjectVisitor* v) {
3941 v->VisitPointers(&builtins_[0], &builtins_[0] + builtin_count);
3942 }
3943
3944
Lookup(byte * pc)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
Generate_InterruptCheck(MacroAssembler * masm)3959 void Builtins::Generate_InterruptCheck(MacroAssembler* masm) {
3960 masm->TailCallRuntime(Runtime::kInterrupt);
3961 }
3962
3963
Generate_StackCheck(MacroAssembler * masm)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