• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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-arguments.h"
8 #include "src/api-natives.h"
9 #include "src/api.h"
10 #include "src/base/ieee754.h"
11 #include "src/base/once.h"
12 #include "src/bootstrapper.h"
13 #include "src/code-factory.h"
14 #include "src/code-stub-assembler.h"
15 #include "src/dateparser-inl.h"
16 #include "src/elements.h"
17 #include "src/frames-inl.h"
18 #include "src/gdb-jit.h"
19 #include "src/ic/handler-compiler.h"
20 #include "src/ic/ic.h"
21 #include "src/isolate-inl.h"
22 #include "src/json-parser.h"
23 #include "src/json-stringifier.h"
24 #include "src/messages.h"
25 #include "src/property-descriptor.h"
26 #include "src/prototype.h"
27 #include "src/string-builder.h"
28 #include "src/uri.h"
29 #include "src/vm-state-inl.h"
30 
31 namespace v8 {
32 namespace internal {
33 
34 namespace {
35 
36 // Arguments object passed to C++ builtins.
37 class BuiltinArguments : public Arguments {
38  public:
BuiltinArguments(int length,Object ** arguments)39   BuiltinArguments(int length, Object** arguments)
40       : Arguments(length, arguments) {
41     // Check we have at least the receiver.
42     DCHECK_LE(1, this->length());
43   }
44 
operator [](int index)45   Object*& operator[] (int index) {
46     DCHECK_LT(index, length());
47     return Arguments::operator[](index);
48   }
49 
at(int index)50   template <class S> Handle<S> at(int index) {
51     DCHECK_LT(index, length());
52     return Arguments::at<S>(index);
53   }
54 
atOrUndefined(Isolate * isolate,int index)55   Handle<Object> atOrUndefined(Isolate* isolate, int index) {
56     if (index >= length()) {
57       return isolate->factory()->undefined_value();
58     }
59     return at<Object>(index);
60   }
61 
receiver()62   Handle<Object> receiver() {
63     return Arguments::at<Object>(0);
64   }
65 
66   template <class S>
target()67   Handle<S> target() {
68     return Arguments::at<S>(Arguments::length() - 2);
69   }
new_target()70   Handle<HeapObject> new_target() {
71     return Arguments::at<HeapObject>(Arguments::length() - 1);
72   }
73 
74   // Gets the total number of arguments including the receiver (but
75   // excluding extra arguments).
length() const76   int length() const { return Arguments::length() - 2; }
77 };
78 
79 
80 // ----------------------------------------------------------------------------
81 // Support macro for defining builtins in C++.
82 // ----------------------------------------------------------------------------
83 //
84 // A builtin function is defined by writing:
85 //
86 //   BUILTIN(name) {
87 //     ...
88 //   }
89 //
90 // In the body of the builtin function the arguments can be accessed
91 // through the BuiltinArguments object args.
92 // TODO(cbruni): add global flag to check whether any tracing events have been
93 // enabled.
94 #define BUILTIN(name)                                                        \
95   MUST_USE_RESULT static Object* Builtin_Impl_##name(BuiltinArguments args,  \
96                                                      Isolate* isolate);      \
97                                                                              \
98   V8_NOINLINE static Object* Builtin_Impl_Stats_##name(                      \
99       int args_length, Object** args_object, Isolate* isolate) {             \
100     BuiltinArguments args(args_length, args_object);                         \
101     RuntimeCallTimerScope timer(isolate, &RuntimeCallStats::Builtin_##name); \
102     TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.runtime"),                    \
103                  "V8.Builtin_" #name);                                       \
104     return Builtin_Impl_##name(args, isolate);                               \
105   }                                                                          \
106                                                                              \
107   MUST_USE_RESULT static Object* Builtin_##name(                             \
108       int args_length, Object** args_object, Isolate* isolate) {             \
109     if (FLAG_runtime_call_stats) {                                           \
110       return Builtin_Impl_Stats_##name(args_length, args_object, isolate);   \
111     }                                                                        \
112     BuiltinArguments args(args_length, args_object);                         \
113     return Builtin_Impl_##name(args, isolate);                               \
114   }                                                                          \
115                                                                              \
116   MUST_USE_RESULT static Object* Builtin_Impl_##name(BuiltinArguments args,  \
117                                                      Isolate* isolate)
118 
119 // ----------------------------------------------------------------------------
120 
121 #define CHECK_RECEIVER(Type, name, method)                                  \
122   if (!args.receiver()->Is##Type()) {                                       \
123     THROW_NEW_ERROR_RETURN_FAILURE(                                         \
124         isolate,                                                            \
125         NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,          \
126                      isolate->factory()->NewStringFromAsciiChecked(method), \
127                      args.receiver()));                                     \
128   }                                                                         \
129   Handle<Type> name = Handle<Type>::cast(args.receiver())
130 
131 // Throws a TypeError for {method} if the receiver is not coercible to Object,
132 // or converts the receiver to a String otherwise and assigns it to a new var
133 // with the given {name}.
134 #define TO_THIS_STRING(name, method)                                          \
135   if (args.receiver()->IsNull(isolate) ||                                     \
136       args.receiver()->IsUndefined(isolate)) {                                \
137     THROW_NEW_ERROR_RETURN_FAILURE(                                           \
138         isolate,                                                              \
139         NewTypeError(MessageTemplate::kCalledOnNullOrUndefined,               \
140                      isolate->factory()->NewStringFromAsciiChecked(method))); \
141   }                                                                           \
142   Handle<String> name;                                                        \
143   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(                                         \
144       isolate, name, Object::ToString(isolate, args.receiver()))
145 
ClampedToInteger(Isolate * isolate,Object * object,int * out)146 inline bool ClampedToInteger(Isolate* isolate, Object* object, int* out) {
147   // This is an extended version of ECMA-262 7.1.11 handling signed values
148   // Try to convert object to a number and clamp values to [kMinInt, kMaxInt]
149   if (object->IsSmi()) {
150     *out = Smi::cast(object)->value();
151     return true;
152   } else if (object->IsHeapNumber()) {
153     double value = HeapNumber::cast(object)->value();
154     if (std::isnan(value)) {
155       *out = 0;
156     } else if (value > kMaxInt) {
157       *out = kMaxInt;
158     } else if (value < kMinInt) {
159       *out = kMinInt;
160     } else {
161       *out = static_cast<int>(value);
162     }
163     return true;
164   } else if (object->IsUndefined(isolate) || object->IsNull(isolate)) {
165     *out = 0;
166     return true;
167   } else if (object->IsBoolean()) {
168     *out = object->IsTrue(isolate);
169     return true;
170   }
171   return false;
172 }
173 
174 
GetSloppyArgumentsLength(Isolate * isolate,Handle<JSObject> object,int * out)175 inline bool GetSloppyArgumentsLength(Isolate* isolate, Handle<JSObject> object,
176                                      int* out) {
177   Context* context = *isolate->native_context();
178   Map* map = object->map();
179   if (map != context->sloppy_arguments_map() &&
180       map != context->strict_arguments_map() &&
181       map != context->fast_aliased_arguments_map()) {
182     return false;
183   }
184   DCHECK(object->HasFastElements() || object->HasFastArgumentsElements());
185   Object* len_obj = object->InObjectPropertyAt(JSArgumentsObject::kLengthIndex);
186   if (!len_obj->IsSmi()) return false;
187   *out = Max(0, Smi::cast(len_obj)->value());
188   return *out <= object->elements()->length();
189 }
190 
PrototypeHasNoElements(Isolate * isolate,JSObject * object)191 inline bool PrototypeHasNoElements(Isolate* isolate, JSObject* object) {
192   DisallowHeapAllocation no_gc;
193   HeapObject* prototype = HeapObject::cast(object->map()->prototype());
194   HeapObject* null = isolate->heap()->null_value();
195   HeapObject* empty = isolate->heap()->empty_fixed_array();
196   while (prototype != null) {
197     Map* map = prototype->map();
198     if (map->instance_type() <= LAST_CUSTOM_ELEMENTS_RECEIVER) return false;
199     if (JSObject::cast(prototype)->elements() != empty) return false;
200     prototype = HeapObject::cast(map->prototype());
201   }
202   return true;
203 }
204 
IsJSArrayFastElementMovingAllowed(Isolate * isolate,JSArray * receiver)205 inline bool IsJSArrayFastElementMovingAllowed(Isolate* isolate,
206                                               JSArray* receiver) {
207   return PrototypeHasNoElements(isolate, receiver);
208 }
209 
HasSimpleElements(JSObject * current)210 inline bool HasSimpleElements(JSObject* current) {
211   return current->map()->instance_type() > LAST_CUSTOM_ELEMENTS_RECEIVER &&
212          !current->GetElementsAccessor()->HasAccessors(current);
213 }
214 
HasOnlySimpleReceiverElements(Isolate * isolate,JSObject * receiver)215 inline bool HasOnlySimpleReceiverElements(Isolate* isolate,
216                                           JSObject* receiver) {
217   // Check that we have no accessors on the receiver's elements.
218   if (!HasSimpleElements(receiver)) return false;
219   return PrototypeHasNoElements(isolate, receiver);
220 }
221 
HasOnlySimpleElements(Isolate * isolate,JSReceiver * receiver)222 inline bool HasOnlySimpleElements(Isolate* isolate, JSReceiver* receiver) {
223   DisallowHeapAllocation no_gc;
224   PrototypeIterator iter(isolate, receiver, kStartAtReceiver);
225   for (; !iter.IsAtEnd(); iter.Advance()) {
226     if (iter.GetCurrent()->IsJSProxy()) return false;
227     JSObject* current = iter.GetCurrent<JSObject>();
228     if (!HasSimpleElements(current)) return false;
229   }
230   return true;
231 }
232 
233 // Returns |false| if not applicable.
234 MUST_USE_RESULT
EnsureJSArrayWithWritableFastElements(Isolate * isolate,Handle<Object> receiver,BuiltinArguments * args,int first_added_arg)235 inline bool EnsureJSArrayWithWritableFastElements(Isolate* isolate,
236                                                   Handle<Object> receiver,
237                                                   BuiltinArguments* args,
238                                                   int first_added_arg) {
239   if (!receiver->IsJSArray()) return false;
240   Handle<JSArray> array = Handle<JSArray>::cast(receiver);
241   ElementsKind origin_kind = array->GetElementsKind();
242   if (IsDictionaryElementsKind(origin_kind)) return false;
243   if (!array->map()->is_extensible()) return false;
244   if (args == nullptr) return true;
245 
246   // If there may be elements accessors in the prototype chain, the fast path
247   // cannot be used if there arguments to add to the array.
248   if (!IsJSArrayFastElementMovingAllowed(isolate, *array)) return false;
249 
250   // Adding elements to the array prototype would break code that makes sure
251   // it has no elements. Handle that elsewhere.
252   if (isolate->IsAnyInitialArrayPrototype(array)) return false;
253 
254   // Need to ensure that the arguments passed in args can be contained in
255   // the array.
256   int args_length = args->length();
257   if (first_added_arg >= args_length) return true;
258 
259   if (IsFastObjectElementsKind(origin_kind)) return true;
260   ElementsKind target_kind = origin_kind;
261   {
262     DisallowHeapAllocation no_gc;
263     for (int i = first_added_arg; i < args_length; i++) {
264       Object* arg = (*args)[i];
265       if (arg->IsHeapObject()) {
266         if (arg->IsHeapNumber()) {
267           target_kind = FAST_DOUBLE_ELEMENTS;
268         } else {
269           target_kind = FAST_ELEMENTS;
270           break;
271         }
272       }
273     }
274   }
275   if (target_kind != origin_kind) {
276     // Use a short-lived HandleScope to avoid creating several copies of the
277     // elements handle which would cause issues when left-trimming later-on.
278     HandleScope scope(isolate);
279     JSObject::TransitionElementsKind(array, target_kind);
280   }
281   return true;
282 }
283 
CallJsIntrinsic(Isolate * isolate,Handle<JSFunction> function,BuiltinArguments args)284 MUST_USE_RESULT static Object* CallJsIntrinsic(Isolate* isolate,
285                                                Handle<JSFunction> function,
286                                                BuiltinArguments args) {
287   HandleScope handleScope(isolate);
288   int argc = args.length() - 1;
289   ScopedVector<Handle<Object> > argv(argc);
290   for (int i = 0; i < argc; ++i) {
291     argv[i] = args.at<Object>(i + 1);
292   }
293   RETURN_RESULT_OR_FAILURE(
294       isolate,
295       Execution::Call(isolate, function, args.receiver(), argc, argv.start()));
296 }
297 
298 
299 }  // namespace
300 
301 
BUILTIN(Illegal)302 BUILTIN(Illegal) {
303   UNREACHABLE();
304   return isolate->heap()->undefined_value();  // Make compiler happy.
305 }
306 
307 
BUILTIN(EmptyFunction)308 BUILTIN(EmptyFunction) { return isolate->heap()->undefined_value(); }
309 
Generate_ArrayIsArray(CodeStubAssembler * assembler)310 void Builtins::Generate_ArrayIsArray(CodeStubAssembler* assembler) {
311   typedef compiler::Node Node;
312   typedef CodeStubAssembler::Label Label;
313 
314   Node* object = assembler->Parameter(1);
315   Node* context = assembler->Parameter(4);
316 
317   Label call_runtime(assembler), return_true(assembler),
318       return_false(assembler);
319 
320   assembler->GotoIf(assembler->WordIsSmi(object), &return_false);
321   Node* instance_type = assembler->LoadInstanceType(object);
322 
323   assembler->GotoIf(assembler->Word32Equal(
324                         instance_type, assembler->Int32Constant(JS_ARRAY_TYPE)),
325                     &return_true);
326 
327   // TODO(verwaest): Handle proxies in-place.
328   assembler->Branch(assembler->Word32Equal(
329                         instance_type, assembler->Int32Constant(JS_PROXY_TYPE)),
330                     &call_runtime, &return_false);
331 
332   assembler->Bind(&return_true);
333   assembler->Return(assembler->BooleanConstant(true));
334 
335   assembler->Bind(&return_false);
336   assembler->Return(assembler->BooleanConstant(false));
337 
338   assembler->Bind(&call_runtime);
339   assembler->Return(
340       assembler->CallRuntime(Runtime::kArrayIsArray, context, object));
341 }
342 
Generate_ObjectHasOwnProperty(CodeStubAssembler * assembler)343 void Builtins::Generate_ObjectHasOwnProperty(CodeStubAssembler* assembler) {
344   typedef compiler::Node Node;
345   typedef CodeStubAssembler::Label Label;
346   typedef CodeStubAssembler::Variable Variable;
347 
348   Node* object = assembler->Parameter(0);
349   Node* key = assembler->Parameter(1);
350   Node* context = assembler->Parameter(4);
351 
352   Label call_runtime(assembler), return_true(assembler),
353       return_false(assembler);
354 
355   // Smi receivers do not have own properties.
356   Label if_objectisnotsmi(assembler);
357   assembler->Branch(assembler->WordIsSmi(object), &return_false,
358                     &if_objectisnotsmi);
359   assembler->Bind(&if_objectisnotsmi);
360 
361   Node* map = assembler->LoadMap(object);
362   Node* instance_type = assembler->LoadMapInstanceType(map);
363 
364   Variable var_index(assembler, MachineRepresentation::kWord32);
365 
366   Label keyisindex(assembler), if_iskeyunique(assembler);
367   assembler->TryToName(key, &keyisindex, &var_index, &if_iskeyunique,
368                        &call_runtime);
369 
370   assembler->Bind(&if_iskeyunique);
371   assembler->TryHasOwnProperty(object, map, instance_type, key, &return_true,
372                                &return_false, &call_runtime);
373 
374   assembler->Bind(&keyisindex);
375   assembler->TryLookupElement(object, map, instance_type, var_index.value(),
376                               &return_true, &return_false, &call_runtime);
377 
378   assembler->Bind(&return_true);
379   assembler->Return(assembler->BooleanConstant(true));
380 
381   assembler->Bind(&return_false);
382   assembler->Return(assembler->BooleanConstant(false));
383 
384   assembler->Bind(&call_runtime);
385   assembler->Return(assembler->CallRuntime(Runtime::kObjectHasOwnProperty,
386                                            context, object, key));
387 }
388 
389 namespace {
390 
DoArrayPush(Isolate * isolate,BuiltinArguments args)391 Object* DoArrayPush(Isolate* isolate, BuiltinArguments args) {
392   HandleScope scope(isolate);
393   Handle<Object> receiver = args.receiver();
394   if (!EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1)) {
395     return CallJsIntrinsic(isolate, isolate->array_push(), args);
396   }
397   // Fast Elements Path
398   int to_add = args.length() - 1;
399   Handle<JSArray> array = Handle<JSArray>::cast(receiver);
400   int len = Smi::cast(array->length())->value();
401   if (to_add == 0) return Smi::FromInt(len);
402 
403   // Currently fixed arrays cannot grow too big, so we should never hit this.
404   DCHECK_LE(to_add, Smi::kMaxValue - Smi::cast(array->length())->value());
405 
406   if (JSArray::HasReadOnlyLength(array)) {
407     return CallJsIntrinsic(isolate, isolate->array_push(), args);
408   }
409 
410   ElementsAccessor* accessor = array->GetElementsAccessor();
411   int new_length = accessor->Push(array, &args, to_add);
412   return Smi::FromInt(new_length);
413 }
414 
415 }  // namespace
416 
BUILTIN(ArrayPush)417 BUILTIN(ArrayPush) { return DoArrayPush(isolate, args); }
418 
419 // TODO(verwaest): This is a temporary helper until the FastArrayPush stub can
420 // tailcall to the builtin directly.
RUNTIME_FUNCTION(Runtime_ArrayPush)421 RUNTIME_FUNCTION(Runtime_ArrayPush) {
422   DCHECK_EQ(2, args.length());
423   Arguments* incoming = reinterpret_cast<Arguments*>(args[0]);
424   // Rewrap the arguments as builtins arguments.
425   BuiltinArguments caller_args(incoming->length() + 3,
426                                incoming->arguments() + 1);
427   return DoArrayPush(isolate, caller_args);
428 }
429 
BUILTIN(ArrayPop)430 BUILTIN(ArrayPop) {
431   HandleScope scope(isolate);
432   Handle<Object> receiver = args.receiver();
433   if (!EnsureJSArrayWithWritableFastElements(isolate, receiver, nullptr, 0)) {
434     return CallJsIntrinsic(isolate, isolate->array_pop(), args);
435   }
436 
437   Handle<JSArray> array = Handle<JSArray>::cast(receiver);
438 
439   uint32_t len = static_cast<uint32_t>(Smi::cast(array->length())->value());
440   if (len == 0) return isolate->heap()->undefined_value();
441 
442   if (JSArray::HasReadOnlyLength(array)) {
443     return CallJsIntrinsic(isolate, isolate->array_pop(), args);
444   }
445 
446   Handle<Object> result;
447   if (IsJSArrayFastElementMovingAllowed(isolate, JSArray::cast(*receiver))) {
448     // Fast Elements Path
449     result = array->GetElementsAccessor()->Pop(array);
450   } else {
451     // Use Slow Lookup otherwise
452     uint32_t new_length = len - 1;
453     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
454         isolate, result, JSReceiver::GetElement(isolate, array, new_length));
455     JSArray::SetLength(array, new_length);
456   }
457   return *result;
458 }
459 
460 
BUILTIN(ArrayShift)461 BUILTIN(ArrayShift) {
462   HandleScope scope(isolate);
463   Heap* heap = isolate->heap();
464   Handle<Object> receiver = args.receiver();
465   if (!EnsureJSArrayWithWritableFastElements(isolate, receiver, nullptr, 0) ||
466       !IsJSArrayFastElementMovingAllowed(isolate, JSArray::cast(*receiver))) {
467     return CallJsIntrinsic(isolate, isolate->array_shift(), args);
468   }
469   Handle<JSArray> array = Handle<JSArray>::cast(receiver);
470 
471   int len = Smi::cast(array->length())->value();
472   if (len == 0) return heap->undefined_value();
473 
474   if (JSArray::HasReadOnlyLength(array)) {
475     return CallJsIntrinsic(isolate, isolate->array_shift(), args);
476   }
477 
478   Handle<Object> first = array->GetElementsAccessor()->Shift(array);
479   return *first;
480 }
481 
482 
BUILTIN(ArrayUnshift)483 BUILTIN(ArrayUnshift) {
484   HandleScope scope(isolate);
485   Handle<Object> receiver = args.receiver();
486   if (!EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1)) {
487     return CallJsIntrinsic(isolate, isolate->array_unshift(), args);
488   }
489   Handle<JSArray> array = Handle<JSArray>::cast(receiver);
490   int to_add = args.length() - 1;
491   if (to_add == 0) return array->length();
492 
493   // Currently fixed arrays cannot grow too big, so we should never hit this.
494   DCHECK_LE(to_add, Smi::kMaxValue - Smi::cast(array->length())->value());
495 
496   if (JSArray::HasReadOnlyLength(array)) {
497     return CallJsIntrinsic(isolate, isolate->array_unshift(), args);
498   }
499 
500   ElementsAccessor* accessor = array->GetElementsAccessor();
501   int new_length = accessor->Unshift(array, &args, to_add);
502   return Smi::FromInt(new_length);
503 }
504 
505 
BUILTIN(ArraySlice)506 BUILTIN(ArraySlice) {
507   HandleScope scope(isolate);
508   Handle<Object> receiver = args.receiver();
509   int len = -1;
510   int relative_start = 0;
511   int relative_end = 0;
512 
513   if (receiver->IsJSArray()) {
514     DisallowHeapAllocation no_gc;
515     JSArray* array = JSArray::cast(*receiver);
516     if (V8_UNLIKELY(!array->HasFastElements() ||
517                     !IsJSArrayFastElementMovingAllowed(isolate, array) ||
518                     !isolate->IsArraySpeciesLookupChainIntact() ||
519                     // If this is a subclass of Array, then call out to JS
520                     !array->HasArrayPrototype(isolate))) {
521       AllowHeapAllocation allow_allocation;
522       return CallJsIntrinsic(isolate, isolate->array_slice(), args);
523     }
524     len = Smi::cast(array->length())->value();
525   } else if (receiver->IsJSObject() &&
526              GetSloppyArgumentsLength(isolate, Handle<JSObject>::cast(receiver),
527                                       &len)) {
528     // Array.prototype.slice.call(arguments, ...) is quite a common idiom
529     // (notably more than 50% of invocations in Web apps).
530     // Treat it in C++ as well.
531     DCHECK(JSObject::cast(*receiver)->HasFastElements() ||
532            JSObject::cast(*receiver)->HasFastArgumentsElements());
533   } else {
534     AllowHeapAllocation allow_allocation;
535     return CallJsIntrinsic(isolate, isolate->array_slice(), args);
536   }
537   DCHECK_LE(0, len);
538   int argument_count = args.length() - 1;
539   // Note carefully chosen defaults---if argument is missing,
540   // it's undefined which gets converted to 0 for relative_start
541   // and to len for relative_end.
542   relative_start = 0;
543   relative_end = len;
544   if (argument_count > 0) {
545     DisallowHeapAllocation no_gc;
546     if (!ClampedToInteger(isolate, args[1], &relative_start)) {
547       AllowHeapAllocation allow_allocation;
548       return CallJsIntrinsic(isolate, isolate->array_slice(), args);
549     }
550     if (argument_count > 1) {
551       Object* end_arg = args[2];
552       // slice handles the end_arg specially
553       if (end_arg->IsUndefined(isolate)) {
554         relative_end = len;
555       } else if (!ClampedToInteger(isolate, end_arg, &relative_end)) {
556         AllowHeapAllocation allow_allocation;
557         return CallJsIntrinsic(isolate, isolate->array_slice(), args);
558       }
559     }
560   }
561 
562   // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 6.
563   uint32_t actual_start = (relative_start < 0) ? Max(len + relative_start, 0)
564                                                : Min(relative_start, len);
565 
566   // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 8.
567   uint32_t actual_end =
568       (relative_end < 0) ? Max(len + relative_end, 0) : Min(relative_end, len);
569 
570   Handle<JSObject> object = Handle<JSObject>::cast(receiver);
571   ElementsAccessor* accessor = object->GetElementsAccessor();
572   return *accessor->Slice(object, actual_start, actual_end);
573 }
574 
575 
BUILTIN(ArraySplice)576 BUILTIN(ArraySplice) {
577   HandleScope scope(isolate);
578   Handle<Object> receiver = args.receiver();
579   if (V8_UNLIKELY(
580           !EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 3) ||
581           // If this is a subclass of Array, then call out to JS.
582           !Handle<JSArray>::cast(receiver)->HasArrayPrototype(isolate) ||
583           // If anything with @@species has been messed with, call out to JS.
584           !isolate->IsArraySpeciesLookupChainIntact())) {
585     return CallJsIntrinsic(isolate, isolate->array_splice(), args);
586   }
587   Handle<JSArray> array = Handle<JSArray>::cast(receiver);
588 
589   int argument_count = args.length() - 1;
590   int relative_start = 0;
591   if (argument_count > 0) {
592     DisallowHeapAllocation no_gc;
593     if (!ClampedToInteger(isolate, args[1], &relative_start)) {
594       AllowHeapAllocation allow_allocation;
595       return CallJsIntrinsic(isolate, isolate->array_splice(), args);
596     }
597   }
598   int len = Smi::cast(array->length())->value();
599   // clip relative start to [0, len]
600   int actual_start = (relative_start < 0) ? Max(len + relative_start, 0)
601                                           : Min(relative_start, len);
602 
603   int actual_delete_count;
604   if (argument_count == 1) {
605     // SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is
606     // given as a request to delete all the elements from the start.
607     // And it differs from the case of undefined delete count.
608     // This does not follow ECMA-262, but we do the same for compatibility.
609     DCHECK(len - actual_start >= 0);
610     actual_delete_count = len - actual_start;
611   } else {
612     int delete_count = 0;
613     DisallowHeapAllocation no_gc;
614     if (argument_count > 1) {
615       if (!ClampedToInteger(isolate, args[2], &delete_count)) {
616         AllowHeapAllocation allow_allocation;
617         return CallJsIntrinsic(isolate, isolate->array_splice(), args);
618       }
619     }
620     actual_delete_count = Min(Max(delete_count, 0), len - actual_start);
621   }
622 
623   int add_count = (argument_count > 1) ? (argument_count - 2) : 0;
624   int new_length = len - actual_delete_count + add_count;
625 
626   if (new_length != len && JSArray::HasReadOnlyLength(array)) {
627     AllowHeapAllocation allow_allocation;
628     return CallJsIntrinsic(isolate, isolate->array_splice(), args);
629   }
630   ElementsAccessor* accessor = array->GetElementsAccessor();
631   Handle<JSArray> result_array = accessor->Splice(
632       array, actual_start, actual_delete_count, &args, add_count);
633   return *result_array;
634 }
635 
636 
637 // Array Concat -------------------------------------------------------------
638 
639 namespace {
640 
641 /**
642  * A simple visitor visits every element of Array's.
643  * The backend storage can be a fixed array for fast elements case,
644  * or a dictionary for sparse array. Since Dictionary is a subtype
645  * of FixedArray, the class can be used by both fast and slow cases.
646  * The second parameter of the constructor, fast_elements, specifies
647  * whether the storage is a FixedArray or Dictionary.
648  *
649  * An index limit is used to deal with the situation that a result array
650  * length overflows 32-bit non-negative integer.
651  */
652 class ArrayConcatVisitor {
653  public:
ArrayConcatVisitor(Isolate * isolate,Handle<Object> storage,bool fast_elements)654   ArrayConcatVisitor(Isolate* isolate, Handle<Object> storage,
655                      bool fast_elements)
656       : isolate_(isolate),
657         storage_(isolate->global_handles()->Create(*storage)),
658         index_offset_(0u),
659         bit_field_(FastElementsField::encode(fast_elements) |
660                    ExceedsLimitField::encode(false) |
661                    IsFixedArrayField::encode(storage->IsFixedArray())) {
662     DCHECK(!(this->fast_elements() && !is_fixed_array()));
663   }
664 
~ArrayConcatVisitor()665   ~ArrayConcatVisitor() { clear_storage(); }
666 
visit(uint32_t i,Handle<Object> elm)667   MUST_USE_RESULT bool visit(uint32_t i, Handle<Object> elm) {
668     uint32_t index = index_offset_ + i;
669 
670     if (i >= JSObject::kMaxElementCount - index_offset_) {
671       set_exceeds_array_limit(true);
672       // Exception hasn't been thrown at this point. Return true to
673       // break out, and caller will throw. !visit would imply that
674       // there is already a pending exception.
675       return true;
676     }
677 
678     if (!is_fixed_array()) {
679       LookupIterator it(isolate_, storage_, index, LookupIterator::OWN);
680       MAYBE_RETURN(
681           JSReceiver::CreateDataProperty(&it, elm, Object::THROW_ON_ERROR),
682           false);
683       return true;
684     }
685 
686     if (fast_elements()) {
687       if (index < static_cast<uint32_t>(storage_fixed_array()->length())) {
688         storage_fixed_array()->set(index, *elm);
689         return true;
690       }
691       // Our initial estimate of length was foiled, possibly by
692       // getters on the arrays increasing the length of later arrays
693       // during iteration.
694       // This shouldn't happen in anything but pathological cases.
695       SetDictionaryMode();
696       // Fall-through to dictionary mode.
697     }
698     DCHECK(!fast_elements());
699     Handle<SeededNumberDictionary> dict(
700         SeededNumberDictionary::cast(*storage_));
701     // The object holding this backing store has just been allocated, so
702     // it cannot yet be used as a prototype.
703     Handle<SeededNumberDictionary> result =
704         SeededNumberDictionary::AtNumberPut(dict, index, elm, false);
705     if (!result.is_identical_to(dict)) {
706       // Dictionary needed to grow.
707       clear_storage();
708       set_storage(*result);
709     }
710     return true;
711   }
712 
increase_index_offset(uint32_t delta)713   void increase_index_offset(uint32_t delta) {
714     if (JSObject::kMaxElementCount - index_offset_ < delta) {
715       index_offset_ = JSObject::kMaxElementCount;
716     } else {
717       index_offset_ += delta;
718     }
719     // If the initial length estimate was off (see special case in visit()),
720     // but the array blowing the limit didn't contain elements beyond the
721     // provided-for index range, go to dictionary mode now.
722     if (fast_elements() &&
723         index_offset_ >
724             static_cast<uint32_t>(FixedArrayBase::cast(*storage_)->length())) {
725       SetDictionaryMode();
726     }
727   }
728 
exceeds_array_limit() const729   bool exceeds_array_limit() const {
730     return ExceedsLimitField::decode(bit_field_);
731   }
732 
ToArray()733   Handle<JSArray> ToArray() {
734     DCHECK(is_fixed_array());
735     Handle<JSArray> array = isolate_->factory()->NewJSArray(0);
736     Handle<Object> length =
737         isolate_->factory()->NewNumber(static_cast<double>(index_offset_));
738     Handle<Map> map = JSObject::GetElementsTransitionMap(
739         array, fast_elements() ? FAST_HOLEY_ELEMENTS : DICTIONARY_ELEMENTS);
740     array->set_map(*map);
741     array->set_length(*length);
742     array->set_elements(*storage_fixed_array());
743     return array;
744   }
745 
746   // Storage is either a FixedArray (if is_fixed_array()) or a JSReciever
747   // (otherwise)
storage_fixed_array()748   Handle<FixedArray> storage_fixed_array() {
749     DCHECK(is_fixed_array());
750     return Handle<FixedArray>::cast(storage_);
751   }
storage_jsreceiver()752   Handle<JSReceiver> storage_jsreceiver() {
753     DCHECK(!is_fixed_array());
754     return Handle<JSReceiver>::cast(storage_);
755   }
756 
757  private:
758   // Convert storage to dictionary mode.
SetDictionaryMode()759   void SetDictionaryMode() {
760     DCHECK(fast_elements() && is_fixed_array());
761     Handle<FixedArray> current_storage = storage_fixed_array();
762     Handle<SeededNumberDictionary> slow_storage(
763         SeededNumberDictionary::New(isolate_, current_storage->length()));
764     uint32_t current_length = static_cast<uint32_t>(current_storage->length());
765     FOR_WITH_HANDLE_SCOPE(
766         isolate_, uint32_t, i = 0, i, i < current_length, i++, {
767           Handle<Object> element(current_storage->get(i), isolate_);
768           if (!element->IsTheHole(isolate_)) {
769             // The object holding this backing store has just been allocated, so
770             // it cannot yet be used as a prototype.
771             Handle<SeededNumberDictionary> new_storage =
772                 SeededNumberDictionary::AtNumberPut(slow_storage, i, element,
773                                                     false);
774             if (!new_storage.is_identical_to(slow_storage)) {
775               slow_storage = loop_scope.CloseAndEscape(new_storage);
776             }
777           }
778         });
779     clear_storage();
780     set_storage(*slow_storage);
781     set_fast_elements(false);
782   }
783 
clear_storage()784   inline void clear_storage() { GlobalHandles::Destroy(storage_.location()); }
785 
set_storage(FixedArray * storage)786   inline void set_storage(FixedArray* storage) {
787     DCHECK(is_fixed_array());
788     storage_ = isolate_->global_handles()->Create(storage);
789   }
790 
791   class FastElementsField : public BitField<bool, 0, 1> {};
792   class ExceedsLimitField : public BitField<bool, 1, 1> {};
793   class IsFixedArrayField : public BitField<bool, 2, 1> {};
794 
fast_elements() const795   bool fast_elements() const { return FastElementsField::decode(bit_field_); }
set_fast_elements(bool fast)796   void set_fast_elements(bool fast) {
797     bit_field_ = FastElementsField::update(bit_field_, fast);
798   }
set_exceeds_array_limit(bool exceeds)799   void set_exceeds_array_limit(bool exceeds) {
800     bit_field_ = ExceedsLimitField::update(bit_field_, exceeds);
801   }
is_fixed_array() const802   bool is_fixed_array() const { return IsFixedArrayField::decode(bit_field_); }
803 
804   Isolate* isolate_;
805   Handle<Object> storage_;  // Always a global handle.
806   // Index after last seen index. Always less than or equal to
807   // JSObject::kMaxElementCount.
808   uint32_t index_offset_;
809   uint32_t bit_field_;
810 };
811 
812 
EstimateElementCount(Handle<JSArray> array)813 uint32_t EstimateElementCount(Handle<JSArray> array) {
814   DisallowHeapAllocation no_gc;
815   uint32_t length = static_cast<uint32_t>(array->length()->Number());
816   int element_count = 0;
817   switch (array->GetElementsKind()) {
818     case FAST_SMI_ELEMENTS:
819     case FAST_HOLEY_SMI_ELEMENTS:
820     case FAST_ELEMENTS:
821     case FAST_HOLEY_ELEMENTS: {
822       // Fast elements can't have lengths that are not representable by
823       // a 32-bit signed integer.
824       DCHECK(static_cast<int32_t>(FixedArray::kMaxLength) >= 0);
825       int fast_length = static_cast<int>(length);
826       Isolate* isolate = array->GetIsolate();
827       FixedArray* elements = FixedArray::cast(array->elements());
828       for (int i = 0; i < fast_length; i++) {
829         if (!elements->get(i)->IsTheHole(isolate)) element_count++;
830       }
831       break;
832     }
833     case FAST_DOUBLE_ELEMENTS:
834     case FAST_HOLEY_DOUBLE_ELEMENTS: {
835       // Fast elements can't have lengths that are not representable by
836       // a 32-bit signed integer.
837       DCHECK(static_cast<int32_t>(FixedDoubleArray::kMaxLength) >= 0);
838       int fast_length = static_cast<int>(length);
839       if (array->elements()->IsFixedArray()) {
840         DCHECK(FixedArray::cast(array->elements())->length() == 0);
841         break;
842       }
843       FixedDoubleArray* elements = FixedDoubleArray::cast(array->elements());
844       for (int i = 0; i < fast_length; i++) {
845         if (!elements->is_the_hole(i)) element_count++;
846       }
847       break;
848     }
849     case DICTIONARY_ELEMENTS: {
850       SeededNumberDictionary* dictionary =
851           SeededNumberDictionary::cast(array->elements());
852       Isolate* isolate = dictionary->GetIsolate();
853       int capacity = dictionary->Capacity();
854       for (int i = 0; i < capacity; i++) {
855         Object* key = dictionary->KeyAt(i);
856         if (dictionary->IsKey(isolate, key)) {
857           element_count++;
858         }
859       }
860       break;
861     }
862 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) case TYPE##_ELEMENTS:
863 
864       TYPED_ARRAYS(TYPED_ARRAY_CASE)
865 #undef TYPED_ARRAY_CASE
866       // External arrays are always dense.
867       return length;
868     case NO_ELEMENTS:
869       return 0;
870     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
871     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
872     case FAST_STRING_WRAPPER_ELEMENTS:
873     case SLOW_STRING_WRAPPER_ELEMENTS:
874       UNREACHABLE();
875       return 0;
876   }
877   // As an estimate, we assume that the prototype doesn't contain any
878   // inherited elements.
879   return element_count;
880 }
881 
882 
883 // Used for sorting indices in a List<uint32_t>.
compareUInt32(const uint32_t * ap,const uint32_t * bp)884 int compareUInt32(const uint32_t* ap, const uint32_t* bp) {
885   uint32_t a = *ap;
886   uint32_t b = *bp;
887   return (a == b) ? 0 : (a < b) ? -1 : 1;
888 }
889 
890 
CollectElementIndices(Handle<JSObject> object,uint32_t range,List<uint32_t> * indices)891 void CollectElementIndices(Handle<JSObject> object, uint32_t range,
892                            List<uint32_t>* indices) {
893   Isolate* isolate = object->GetIsolate();
894   ElementsKind kind = object->GetElementsKind();
895   switch (kind) {
896     case FAST_SMI_ELEMENTS:
897     case FAST_ELEMENTS:
898     case FAST_HOLEY_SMI_ELEMENTS:
899     case FAST_HOLEY_ELEMENTS: {
900       DisallowHeapAllocation no_gc;
901       FixedArray* elements = FixedArray::cast(object->elements());
902       uint32_t length = static_cast<uint32_t>(elements->length());
903       if (range < length) length = range;
904       for (uint32_t i = 0; i < length; i++) {
905         if (!elements->get(i)->IsTheHole(isolate)) {
906           indices->Add(i);
907         }
908       }
909       break;
910     }
911     case FAST_HOLEY_DOUBLE_ELEMENTS:
912     case FAST_DOUBLE_ELEMENTS: {
913       if (object->elements()->IsFixedArray()) {
914         DCHECK(object->elements()->length() == 0);
915         break;
916       }
917       Handle<FixedDoubleArray> elements(
918           FixedDoubleArray::cast(object->elements()));
919       uint32_t length = static_cast<uint32_t>(elements->length());
920       if (range < length) length = range;
921       for (uint32_t i = 0; i < length; i++) {
922         if (!elements->is_the_hole(i)) {
923           indices->Add(i);
924         }
925       }
926       break;
927     }
928     case DICTIONARY_ELEMENTS: {
929       DisallowHeapAllocation no_gc;
930       SeededNumberDictionary* dict =
931           SeededNumberDictionary::cast(object->elements());
932       uint32_t capacity = dict->Capacity();
933       FOR_WITH_HANDLE_SCOPE(isolate, uint32_t, j = 0, j, j < capacity, j++, {
934         Object* k = dict->KeyAt(j);
935         if (!dict->IsKey(isolate, k)) continue;
936         DCHECK(k->IsNumber());
937         uint32_t index = static_cast<uint32_t>(k->Number());
938         if (index < range) {
939           indices->Add(index);
940         }
941       });
942       break;
943     }
944 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) case TYPE##_ELEMENTS:
945 
946       TYPED_ARRAYS(TYPED_ARRAY_CASE)
947 #undef TYPED_ARRAY_CASE
948       {
949         uint32_t length = static_cast<uint32_t>(
950             FixedArrayBase::cast(object->elements())->length());
951         if (range <= length) {
952           length = range;
953           // We will add all indices, so we might as well clear it first
954           // and avoid duplicates.
955           indices->Clear();
956         }
957         for (uint32_t i = 0; i < length; i++) {
958           indices->Add(i);
959         }
960         if (length == range) return;  // All indices accounted for already.
961         break;
962       }
963     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
964     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
965       ElementsAccessor* accessor = object->GetElementsAccessor();
966       for (uint32_t i = 0; i < range; i++) {
967         if (accessor->HasElement(object, i)) {
968           indices->Add(i);
969         }
970       }
971       break;
972     }
973     case FAST_STRING_WRAPPER_ELEMENTS:
974     case SLOW_STRING_WRAPPER_ELEMENTS: {
975       DCHECK(object->IsJSValue());
976       Handle<JSValue> js_value = Handle<JSValue>::cast(object);
977       DCHECK(js_value->value()->IsString());
978       Handle<String> string(String::cast(js_value->value()), isolate);
979       uint32_t length = static_cast<uint32_t>(string->length());
980       uint32_t i = 0;
981       uint32_t limit = Min(length, range);
982       for (; i < limit; i++) {
983         indices->Add(i);
984       }
985       ElementsAccessor* accessor = object->GetElementsAccessor();
986       for (; i < range; i++) {
987         if (accessor->HasElement(object, i)) {
988           indices->Add(i);
989         }
990       }
991       break;
992     }
993     case NO_ELEMENTS:
994       break;
995   }
996 
997   PrototypeIterator iter(isolate, object);
998   if (!iter.IsAtEnd()) {
999     // The prototype will usually have no inherited element indices,
1000     // but we have to check.
1001     CollectElementIndices(PrototypeIterator::GetCurrent<JSObject>(iter), range,
1002                           indices);
1003   }
1004 }
1005 
1006 
IterateElementsSlow(Isolate * isolate,Handle<JSReceiver> receiver,uint32_t length,ArrayConcatVisitor * visitor)1007 bool IterateElementsSlow(Isolate* isolate, Handle<JSReceiver> receiver,
1008                          uint32_t length, ArrayConcatVisitor* visitor) {
1009   FOR_WITH_HANDLE_SCOPE(isolate, uint32_t, i = 0, i, i < length, ++i, {
1010     Maybe<bool> maybe = JSReceiver::HasElement(receiver, i);
1011     if (!maybe.IsJust()) return false;
1012     if (maybe.FromJust()) {
1013       Handle<Object> element_value;
1014       ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1015           isolate, element_value, JSReceiver::GetElement(isolate, receiver, i),
1016           false);
1017       if (!visitor->visit(i, element_value)) return false;
1018     }
1019   });
1020   visitor->increase_index_offset(length);
1021   return true;
1022 }
1023 
1024 
1025 /**
1026  * A helper function that visits "array" elements of a JSReceiver in numerical
1027  * order.
1028  *
1029  * The visitor argument called for each existing element in the array
1030  * with the element index and the element's value.
1031  * Afterwards it increments the base-index of the visitor by the array
1032  * length.
1033  * Returns false if any access threw an exception, otherwise true.
1034  */
IterateElements(Isolate * isolate,Handle<JSReceiver> receiver,ArrayConcatVisitor * visitor)1035 bool IterateElements(Isolate* isolate, Handle<JSReceiver> receiver,
1036                      ArrayConcatVisitor* visitor) {
1037   uint32_t length = 0;
1038 
1039   if (receiver->IsJSArray()) {
1040     Handle<JSArray> array = Handle<JSArray>::cast(receiver);
1041     length = static_cast<uint32_t>(array->length()->Number());
1042   } else {
1043     Handle<Object> val;
1044     ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1045         isolate, val, Object::GetLengthFromArrayLike(isolate, receiver), false);
1046     // TODO(caitp): Support larger element indexes (up to 2^53-1).
1047     if (!val->ToUint32(&length)) {
1048       length = 0;
1049     }
1050     // TODO(cbruni): handle other element kind as well
1051     return IterateElementsSlow(isolate, receiver, length, visitor);
1052   }
1053 
1054   if (!HasOnlySimpleElements(isolate, *receiver)) {
1055     return IterateElementsSlow(isolate, receiver, length, visitor);
1056   }
1057   Handle<JSObject> array = Handle<JSObject>::cast(receiver);
1058 
1059   switch (array->GetElementsKind()) {
1060     case FAST_SMI_ELEMENTS:
1061     case FAST_ELEMENTS:
1062     case FAST_HOLEY_SMI_ELEMENTS:
1063     case FAST_HOLEY_ELEMENTS: {
1064       // Run through the elements FixedArray and use HasElement and GetElement
1065       // to check the prototype for missing elements.
1066       Handle<FixedArray> elements(FixedArray::cast(array->elements()));
1067       int fast_length = static_cast<int>(length);
1068       DCHECK(fast_length <= elements->length());
1069       FOR_WITH_HANDLE_SCOPE(isolate, int, j = 0, j, j < fast_length, j++, {
1070         Handle<Object> element_value(elements->get(j), isolate);
1071         if (!element_value->IsTheHole(isolate)) {
1072           if (!visitor->visit(j, element_value)) return false;
1073         } else {
1074           Maybe<bool> maybe = JSReceiver::HasElement(array, j);
1075           if (!maybe.IsJust()) return false;
1076           if (maybe.FromJust()) {
1077             // Call GetElement on array, not its prototype, or getters won't
1078             // have the correct receiver.
1079             ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1080                 isolate, element_value,
1081                 JSReceiver::GetElement(isolate, array, j), false);
1082             if (!visitor->visit(j, element_value)) return false;
1083           }
1084         }
1085       });
1086       break;
1087     }
1088     case FAST_HOLEY_DOUBLE_ELEMENTS:
1089     case FAST_DOUBLE_ELEMENTS: {
1090       // Empty array is FixedArray but not FixedDoubleArray.
1091       if (length == 0) break;
1092       // Run through the elements FixedArray and use HasElement and GetElement
1093       // to check the prototype for missing elements.
1094       if (array->elements()->IsFixedArray()) {
1095         DCHECK(array->elements()->length() == 0);
1096         break;
1097       }
1098       Handle<FixedDoubleArray> elements(
1099           FixedDoubleArray::cast(array->elements()));
1100       int fast_length = static_cast<int>(length);
1101       DCHECK(fast_length <= elements->length());
1102       FOR_WITH_HANDLE_SCOPE(isolate, int, j = 0, j, j < fast_length, j++, {
1103         if (!elements->is_the_hole(j)) {
1104           double double_value = elements->get_scalar(j);
1105           Handle<Object> element_value =
1106               isolate->factory()->NewNumber(double_value);
1107           if (!visitor->visit(j, element_value)) return false;
1108         } else {
1109           Maybe<bool> maybe = JSReceiver::HasElement(array, j);
1110           if (!maybe.IsJust()) return false;
1111           if (maybe.FromJust()) {
1112             // Call GetElement on array, not its prototype, or getters won't
1113             // have the correct receiver.
1114             Handle<Object> element_value;
1115             ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1116                 isolate, element_value,
1117                 JSReceiver::GetElement(isolate, array, j), false);
1118             if (!visitor->visit(j, element_value)) return false;
1119           }
1120         }
1121       });
1122       break;
1123     }
1124 
1125     case DICTIONARY_ELEMENTS: {
1126       Handle<SeededNumberDictionary> dict(array->element_dictionary());
1127       List<uint32_t> indices(dict->Capacity() / 2);
1128       // Collect all indices in the object and the prototypes less
1129       // than length. This might introduce duplicates in the indices list.
1130       CollectElementIndices(array, length, &indices);
1131       indices.Sort(&compareUInt32);
1132       int n = indices.length();
1133       FOR_WITH_HANDLE_SCOPE(isolate, int, j = 0, j, j < n, (void)0, {
1134         uint32_t index = indices[j];
1135         Handle<Object> element;
1136         ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1137             isolate, element, JSReceiver::GetElement(isolate, array, index),
1138             false);
1139         if (!visitor->visit(index, element)) return false;
1140         // Skip to next different index (i.e., omit duplicates).
1141         do {
1142           j++;
1143         } while (j < n && indices[j] == index);
1144       });
1145       break;
1146     }
1147     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
1148     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
1149       FOR_WITH_HANDLE_SCOPE(
1150           isolate, uint32_t, index = 0, index, index < length, index++, {
1151             Handle<Object> element;
1152             ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1153                 isolate, element, JSReceiver::GetElement(isolate, array, index),
1154                 false);
1155             if (!visitor->visit(index, element)) return false;
1156           });
1157       break;
1158     }
1159     case NO_ELEMENTS:
1160       break;
1161 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) case TYPE##_ELEMENTS:
1162       TYPED_ARRAYS(TYPED_ARRAY_CASE)
1163 #undef TYPED_ARRAY_CASE
1164       return IterateElementsSlow(isolate, receiver, length, visitor);
1165     case FAST_STRING_WRAPPER_ELEMENTS:
1166     case SLOW_STRING_WRAPPER_ELEMENTS:
1167       // |array| is guaranteed to be an array or typed array.
1168       UNREACHABLE();
1169       break;
1170   }
1171   visitor->increase_index_offset(length);
1172   return true;
1173 }
1174 
IsConcatSpreadable(Isolate * isolate,Handle<Object> obj)1175 static Maybe<bool> IsConcatSpreadable(Isolate* isolate, Handle<Object> obj) {
1176   HandleScope handle_scope(isolate);
1177   if (!obj->IsJSReceiver()) return Just(false);
1178   if (!isolate->IsIsConcatSpreadableLookupChainIntact()) {
1179     // Slow path if @@isConcatSpreadable has been used.
1180     Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol());
1181     Handle<Object> value;
1182     MaybeHandle<Object> maybeValue =
1183         i::Runtime::GetObjectProperty(isolate, obj, key);
1184     if (!maybeValue.ToHandle(&value)) return Nothing<bool>();
1185     if (!value->IsUndefined(isolate)) return Just(value->BooleanValue());
1186   }
1187   return Object::IsArray(obj);
1188 }
1189 
Slow_ArrayConcat(BuiltinArguments * args,Handle<Object> species,Isolate * isolate)1190 Object* Slow_ArrayConcat(BuiltinArguments* args, Handle<Object> species,
1191                          Isolate* isolate) {
1192   int argument_count = args->length();
1193 
1194   bool is_array_species = *species == isolate->context()->array_function();
1195 
1196   // Pass 1: estimate the length and number of elements of the result.
1197   // The actual length can be larger if any of the arguments have getters
1198   // that mutate other arguments (but will otherwise be precise).
1199   // The number of elements is precise if there are no inherited elements.
1200 
1201   ElementsKind kind = FAST_SMI_ELEMENTS;
1202 
1203   uint32_t estimate_result_length = 0;
1204   uint32_t estimate_nof_elements = 0;
1205   FOR_WITH_HANDLE_SCOPE(isolate, int, i = 0, i, i < argument_count, i++, {
1206     Handle<Object> obj((*args)[i], isolate);
1207     uint32_t length_estimate;
1208     uint32_t element_estimate;
1209     if (obj->IsJSArray()) {
1210       Handle<JSArray> array(Handle<JSArray>::cast(obj));
1211       length_estimate = static_cast<uint32_t>(array->length()->Number());
1212       if (length_estimate != 0) {
1213         ElementsKind array_kind =
1214             GetPackedElementsKind(array->GetElementsKind());
1215         kind = GetMoreGeneralElementsKind(kind, array_kind);
1216       }
1217       element_estimate = EstimateElementCount(array);
1218     } else {
1219       if (obj->IsHeapObject()) {
1220         kind = GetMoreGeneralElementsKind(
1221             kind, obj->IsNumber() ? FAST_DOUBLE_ELEMENTS : FAST_ELEMENTS);
1222       }
1223       length_estimate = 1;
1224       element_estimate = 1;
1225     }
1226     // Avoid overflows by capping at kMaxElementCount.
1227     if (JSObject::kMaxElementCount - estimate_result_length < length_estimate) {
1228       estimate_result_length = JSObject::kMaxElementCount;
1229     } else {
1230       estimate_result_length += length_estimate;
1231     }
1232     if (JSObject::kMaxElementCount - estimate_nof_elements < element_estimate) {
1233       estimate_nof_elements = JSObject::kMaxElementCount;
1234     } else {
1235       estimate_nof_elements += element_estimate;
1236     }
1237   });
1238 
1239   // If estimated number of elements is more than half of length, a
1240   // fixed array (fast case) is more time and space-efficient than a
1241   // dictionary.
1242   bool fast_case =
1243       is_array_species && (estimate_nof_elements * 2) >= estimate_result_length;
1244 
1245   if (fast_case && kind == FAST_DOUBLE_ELEMENTS) {
1246     Handle<FixedArrayBase> storage =
1247         isolate->factory()->NewFixedDoubleArray(estimate_result_length);
1248     int j = 0;
1249     bool failure = false;
1250     if (estimate_result_length > 0) {
1251       Handle<FixedDoubleArray> double_storage =
1252           Handle<FixedDoubleArray>::cast(storage);
1253       for (int i = 0; i < argument_count; i++) {
1254         Handle<Object> obj((*args)[i], isolate);
1255         if (obj->IsSmi()) {
1256           double_storage->set(j, Smi::cast(*obj)->value());
1257           j++;
1258         } else if (obj->IsNumber()) {
1259           double_storage->set(j, obj->Number());
1260           j++;
1261         } else {
1262           DisallowHeapAllocation no_gc;
1263           JSArray* array = JSArray::cast(*obj);
1264           uint32_t length = static_cast<uint32_t>(array->length()->Number());
1265           switch (array->GetElementsKind()) {
1266             case FAST_HOLEY_DOUBLE_ELEMENTS:
1267             case FAST_DOUBLE_ELEMENTS: {
1268               // Empty array is FixedArray but not FixedDoubleArray.
1269               if (length == 0) break;
1270               FixedDoubleArray* elements =
1271                   FixedDoubleArray::cast(array->elements());
1272               for (uint32_t i = 0; i < length; i++) {
1273                 if (elements->is_the_hole(i)) {
1274                   // TODO(jkummerow/verwaest): We could be a bit more clever
1275                   // here: Check if there are no elements/getters on the
1276                   // prototype chain, and if so, allow creation of a holey
1277                   // result array.
1278                   // Same thing below (holey smi case).
1279                   failure = true;
1280                   break;
1281                 }
1282                 double double_value = elements->get_scalar(i);
1283                 double_storage->set(j, double_value);
1284                 j++;
1285               }
1286               break;
1287             }
1288             case FAST_HOLEY_SMI_ELEMENTS:
1289             case FAST_SMI_ELEMENTS: {
1290               Object* the_hole = isolate->heap()->the_hole_value();
1291               FixedArray* elements(FixedArray::cast(array->elements()));
1292               for (uint32_t i = 0; i < length; i++) {
1293                 Object* element = elements->get(i);
1294                 if (element == the_hole) {
1295                   failure = true;
1296                   break;
1297                 }
1298                 int32_t int_value = Smi::cast(element)->value();
1299                 double_storage->set(j, int_value);
1300                 j++;
1301               }
1302               break;
1303             }
1304             case FAST_HOLEY_ELEMENTS:
1305             case FAST_ELEMENTS:
1306             case DICTIONARY_ELEMENTS:
1307             case NO_ELEMENTS:
1308               DCHECK_EQ(0u, length);
1309               break;
1310             default:
1311               UNREACHABLE();
1312           }
1313         }
1314         if (failure) break;
1315       }
1316     }
1317     if (!failure) {
1318       return *isolate->factory()->NewJSArrayWithElements(storage, kind, j);
1319     }
1320     // In case of failure, fall through.
1321   }
1322 
1323   Handle<Object> storage;
1324   if (fast_case) {
1325     // The backing storage array must have non-existing elements to preserve
1326     // holes across concat operations.
1327     storage =
1328         isolate->factory()->NewFixedArrayWithHoles(estimate_result_length);
1329   } else if (is_array_species) {
1330     // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate
1331     uint32_t at_least_space_for =
1332         estimate_nof_elements + (estimate_nof_elements >> 2);
1333     storage = SeededNumberDictionary::New(isolate, at_least_space_for);
1334   } else {
1335     DCHECK(species->IsConstructor());
1336     Handle<Object> length(Smi::FromInt(0), isolate);
1337     Handle<Object> storage_object;
1338     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1339         isolate, storage_object,
1340         Execution::New(isolate, species, species, 1, &length));
1341     storage = storage_object;
1342   }
1343 
1344   ArrayConcatVisitor visitor(isolate, storage, fast_case);
1345 
1346   for (int i = 0; i < argument_count; i++) {
1347     Handle<Object> obj((*args)[i], isolate);
1348     Maybe<bool> spreadable = IsConcatSpreadable(isolate, obj);
1349     MAYBE_RETURN(spreadable, isolate->heap()->exception());
1350     if (spreadable.FromJust()) {
1351       Handle<JSReceiver> object = Handle<JSReceiver>::cast(obj);
1352       if (!IterateElements(isolate, object, &visitor)) {
1353         return isolate->heap()->exception();
1354       }
1355     } else {
1356       if (!visitor.visit(0, obj)) return isolate->heap()->exception();
1357       visitor.increase_index_offset(1);
1358     }
1359   }
1360 
1361   if (visitor.exceeds_array_limit()) {
1362     THROW_NEW_ERROR_RETURN_FAILURE(
1363         isolate, NewRangeError(MessageTemplate::kInvalidArrayLength));
1364   }
1365 
1366   if (is_array_species) {
1367     return *visitor.ToArray();
1368   } else {
1369     return *visitor.storage_jsreceiver();
1370   }
1371 }
1372 
IsSimpleArray(Isolate * isolate,Handle<JSArray> obj)1373 bool IsSimpleArray(Isolate* isolate, Handle<JSArray> obj) {
1374   DisallowHeapAllocation no_gc;
1375   Map* map = obj->map();
1376   // If there is only the 'length' property we are fine.
1377   if (map->prototype() ==
1378           isolate->native_context()->initial_array_prototype() &&
1379       map->NumberOfOwnDescriptors() == 1) {
1380     return true;
1381   }
1382   // TODO(cbruni): slower lookup for array subclasses and support slow
1383   // @@IsConcatSpreadable lookup.
1384   return false;
1385 }
1386 
Fast_ArrayConcat(Isolate * isolate,BuiltinArguments * args)1387 MaybeHandle<JSArray> Fast_ArrayConcat(Isolate* isolate,
1388                                       BuiltinArguments* args) {
1389   if (!isolate->IsIsConcatSpreadableLookupChainIntact()) {
1390     return MaybeHandle<JSArray>();
1391   }
1392   // We shouldn't overflow when adding another len.
1393   const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2);
1394   STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt);
1395   STATIC_ASSERT(FixedDoubleArray::kMaxLength < kHalfOfMaxInt);
1396   USE(kHalfOfMaxInt);
1397 
1398   int n_arguments = args->length();
1399   int result_len = 0;
1400   {
1401     DisallowHeapAllocation no_gc;
1402     // Iterate through all the arguments performing checks
1403     // and calculating total length.
1404     for (int i = 0; i < n_arguments; i++) {
1405       Object* arg = (*args)[i];
1406       if (!arg->IsJSArray()) return MaybeHandle<JSArray>();
1407       if (!HasOnlySimpleReceiverElements(isolate, JSObject::cast(arg))) {
1408         return MaybeHandle<JSArray>();
1409       }
1410       // TODO(cbruni): support fast concatenation of DICTIONARY_ELEMENTS.
1411       if (!JSObject::cast(arg)->HasFastElements()) {
1412         return MaybeHandle<JSArray>();
1413       }
1414       Handle<JSArray> array(JSArray::cast(arg), isolate);
1415       if (!IsSimpleArray(isolate, array)) {
1416         return MaybeHandle<JSArray>();
1417       }
1418       // The Array length is guaranted to be <= kHalfOfMaxInt thus we won't
1419       // overflow.
1420       result_len += Smi::cast(array->length())->value();
1421       DCHECK(result_len >= 0);
1422       // Throw an Error if we overflow the FixedArray limits
1423       if (FixedDoubleArray::kMaxLength < result_len ||
1424           FixedArray::kMaxLength < result_len) {
1425         AllowHeapAllocation gc;
1426         THROW_NEW_ERROR(isolate,
1427                         NewRangeError(MessageTemplate::kInvalidArrayLength),
1428                         JSArray);
1429       }
1430     }
1431   }
1432   return ElementsAccessor::Concat(isolate, args, n_arguments, result_len);
1433 }
1434 
1435 }  // namespace
1436 
1437 
1438 // ES6 22.1.3.1 Array.prototype.concat
BUILTIN(ArrayConcat)1439 BUILTIN(ArrayConcat) {
1440   HandleScope scope(isolate);
1441 
1442   Handle<Object> receiver = args.receiver();
1443   // TODO(bmeurer): Do we really care about the exact exception message here?
1444   if (receiver->IsNull(isolate) || receiver->IsUndefined(isolate)) {
1445     THROW_NEW_ERROR_RETURN_FAILURE(
1446         isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined,
1447                               isolate->factory()->NewStringFromAsciiChecked(
1448                                   "Array.prototype.concat")));
1449   }
1450   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1451       isolate, receiver, Object::ToObject(isolate, args.receiver()));
1452   args[0] = *receiver;
1453 
1454   Handle<JSArray> result_array;
1455 
1456   // Avoid a real species read to avoid extra lookups to the array constructor
1457   if (V8_LIKELY(receiver->IsJSArray() &&
1458                 Handle<JSArray>::cast(receiver)->HasArrayPrototype(isolate) &&
1459                 isolate->IsArraySpeciesLookupChainIntact())) {
1460     if (Fast_ArrayConcat(isolate, &args).ToHandle(&result_array)) {
1461       return *result_array;
1462     }
1463     if (isolate->has_pending_exception()) return isolate->heap()->exception();
1464   }
1465   // Reading @@species happens before anything else with a side effect, so
1466   // we can do it here to determine whether to take the fast path.
1467   Handle<Object> species;
1468   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1469       isolate, species, Object::ArraySpeciesConstructor(isolate, receiver));
1470   if (*species == *isolate->array_function()) {
1471     if (Fast_ArrayConcat(isolate, &args).ToHandle(&result_array)) {
1472       return *result_array;
1473     }
1474     if (isolate->has_pending_exception()) return isolate->heap()->exception();
1475   }
1476   return Slow_ArrayConcat(&args, species, isolate);
1477 }
1478 
1479 
1480 namespace {
1481 
FastAssign(Handle<JSReceiver> to,Handle<Object> next_source)1482 MUST_USE_RESULT Maybe<bool> FastAssign(Handle<JSReceiver> to,
1483                                        Handle<Object> next_source) {
1484   // Non-empty strings are the only non-JSReceivers that need to be handled
1485   // explicitly by Object.assign.
1486   if (!next_source->IsJSReceiver()) {
1487     return Just(!next_source->IsString() ||
1488                 String::cast(*next_source)->length() == 0);
1489   }
1490 
1491   // If the target is deprecated, the object will be updated on first store. If
1492   // the source for that store equals the target, this will invalidate the
1493   // cached representation of the source. Preventively upgrade the target.
1494   // Do this on each iteration since any property load could cause deprecation.
1495   if (to->map()->is_deprecated()) {
1496     JSObject::MigrateInstance(Handle<JSObject>::cast(to));
1497   }
1498 
1499   Isolate* isolate = to->GetIsolate();
1500   Handle<Map> map(JSReceiver::cast(*next_source)->map(), isolate);
1501 
1502   if (!map->IsJSObjectMap()) return Just(false);
1503   if (!map->OnlyHasSimpleProperties()) return Just(false);
1504 
1505   Handle<JSObject> from = Handle<JSObject>::cast(next_source);
1506   if (from->elements() != isolate->heap()->empty_fixed_array()) {
1507     return Just(false);
1508   }
1509 
1510   Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
1511   int length = map->NumberOfOwnDescriptors();
1512 
1513   bool stable = true;
1514 
1515   for (int i = 0; i < length; i++) {
1516     Handle<Name> next_key(descriptors->GetKey(i), isolate);
1517     Handle<Object> prop_value;
1518     // Directly decode from the descriptor array if |from| did not change shape.
1519     if (stable) {
1520       PropertyDetails details = descriptors->GetDetails(i);
1521       if (!details.IsEnumerable()) continue;
1522       if (details.kind() == kData) {
1523         if (details.location() == kDescriptor) {
1524           prop_value = handle(descriptors->GetValue(i), isolate);
1525         } else {
1526           Representation representation = details.representation();
1527           FieldIndex index = FieldIndex::ForDescriptor(*map, i);
1528           prop_value = JSObject::FastPropertyAt(from, representation, index);
1529         }
1530       } else {
1531         ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1532             isolate, prop_value, JSReceiver::GetProperty(from, next_key),
1533             Nothing<bool>());
1534         stable = from->map() == *map;
1535       }
1536     } else {
1537       // If the map did change, do a slower lookup. We are still guaranteed that
1538       // the object has a simple shape, and that the key is a name.
1539       LookupIterator it(from, next_key, from,
1540                         LookupIterator::OWN_SKIP_INTERCEPTOR);
1541       if (!it.IsFound()) continue;
1542       DCHECK(it.state() == LookupIterator::DATA ||
1543              it.state() == LookupIterator::ACCESSOR);
1544       if (!it.IsEnumerable()) continue;
1545       ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1546           isolate, prop_value, Object::GetProperty(&it), Nothing<bool>());
1547     }
1548     LookupIterator it(to, next_key, to);
1549     bool call_to_js = it.IsFound() && it.state() != LookupIterator::DATA;
1550     Maybe<bool> result = Object::SetProperty(
1551         &it, prop_value, STRICT, Object::CERTAINLY_NOT_STORE_FROM_KEYED);
1552     if (result.IsNothing()) return result;
1553     if (stable && call_to_js) stable = from->map() == *map;
1554   }
1555 
1556   return Just(true);
1557 }
1558 
1559 }  // namespace
1560 
1561 // ES6 19.1.2.1 Object.assign
BUILTIN(ObjectAssign)1562 BUILTIN(ObjectAssign) {
1563   HandleScope scope(isolate);
1564   Handle<Object> target = args.atOrUndefined(isolate, 1);
1565 
1566   // 1. Let to be ? ToObject(target).
1567   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, target,
1568                                      Object::ToObject(isolate, target));
1569   Handle<JSReceiver> to = Handle<JSReceiver>::cast(target);
1570   // 2. If only one argument was passed, return to.
1571   if (args.length() == 2) return *to;
1572   // 3. Let sources be the List of argument values starting with the
1573   //    second argument.
1574   // 4. For each element nextSource of sources, in ascending index order,
1575   for (int i = 2; i < args.length(); ++i) {
1576     Handle<Object> next_source = args.at<Object>(i);
1577     Maybe<bool> fast_assign = FastAssign(to, next_source);
1578     if (fast_assign.IsNothing()) return isolate->heap()->exception();
1579     if (fast_assign.FromJust()) continue;
1580     // 4a. If nextSource is undefined or null, let keys be an empty List.
1581     // 4b. Else,
1582     // 4b i. Let from be ToObject(nextSource).
1583     // Only non-empty strings and JSReceivers have enumerable properties.
1584     Handle<JSReceiver> from =
1585         Object::ToObject(isolate, next_source).ToHandleChecked();
1586     // 4b ii. Let keys be ? from.[[OwnPropertyKeys]]().
1587     Handle<FixedArray> keys;
1588     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1589         isolate, keys, KeyAccumulator::GetKeys(
1590                            from, KeyCollectionMode::kOwnOnly, ALL_PROPERTIES,
1591                            GetKeysConversion::kKeepNumbers));
1592     // 4c. Repeat for each element nextKey of keys in List order,
1593     for (int j = 0; j < keys->length(); ++j) {
1594       Handle<Object> next_key(keys->get(j), isolate);
1595       // 4c i. Let desc be ? from.[[GetOwnProperty]](nextKey).
1596       PropertyDescriptor desc;
1597       Maybe<bool> found =
1598           JSReceiver::GetOwnPropertyDescriptor(isolate, from, next_key, &desc);
1599       if (found.IsNothing()) return isolate->heap()->exception();
1600       // 4c ii. If desc is not undefined and desc.[[Enumerable]] is true, then
1601       if (found.FromJust() && desc.enumerable()) {
1602         // 4c ii 1. Let propValue be ? Get(from, nextKey).
1603         Handle<Object> prop_value;
1604         ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1605             isolate, prop_value,
1606             Runtime::GetObjectProperty(isolate, from, next_key));
1607         // 4c ii 2. Let status be ? Set(to, nextKey, propValue, true).
1608         Handle<Object> status;
1609         ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1610             isolate, status, Runtime::SetObjectProperty(isolate, to, next_key,
1611                                                         prop_value, STRICT));
1612       }
1613     }
1614   }
1615   // 5. Return to.
1616   return *to;
1617 }
1618 
1619 
1620 // ES6 section 19.1.2.2 Object.create ( O [ , Properties ] )
1621 // TODO(verwaest): Support the common cases with precached map directly in
1622 // an Object.create stub.
BUILTIN(ObjectCreate)1623 BUILTIN(ObjectCreate) {
1624   HandleScope scope(isolate);
1625   Handle<Object> prototype = args.atOrUndefined(isolate, 1);
1626   if (!prototype->IsNull(isolate) && !prototype->IsJSReceiver()) {
1627     THROW_NEW_ERROR_RETURN_FAILURE(
1628         isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, prototype));
1629   }
1630 
1631   // Generate the map with the specified {prototype} based on the Object
1632   // function's initial map from the current native context.
1633   // TODO(bmeurer): Use a dedicated cache for Object.create; think about
1634   // slack tracking for Object.create.
1635   Handle<Map> map(isolate->native_context()->object_function()->initial_map(),
1636                   isolate);
1637   if (map->prototype() != *prototype) {
1638     if (prototype->IsNull(isolate)) {
1639       map = isolate->object_with_null_prototype_map();
1640     } else if (prototype->IsJSObject()) {
1641       Handle<JSObject> js_prototype = Handle<JSObject>::cast(prototype);
1642       if (!js_prototype->map()->is_prototype_map()) {
1643         JSObject::OptimizeAsPrototype(js_prototype, FAST_PROTOTYPE);
1644       }
1645       Handle<PrototypeInfo> info =
1646           Map::GetOrCreatePrototypeInfo(js_prototype, isolate);
1647       // TODO(verwaest): Use inobject slack tracking for this map.
1648       if (info->HasObjectCreateMap()) {
1649         map = handle(info->ObjectCreateMap(), isolate);
1650       } else {
1651         map = Map::CopyInitialMap(map);
1652         Map::SetPrototype(map, prototype, FAST_PROTOTYPE);
1653         PrototypeInfo::SetObjectCreateMap(info, map);
1654       }
1655     } else {
1656       map = Map::TransitionToPrototype(map, prototype, REGULAR_PROTOTYPE);
1657     }
1658   }
1659 
1660   // Actually allocate the object.
1661   Handle<JSObject> object = isolate->factory()->NewJSObjectFromMap(map);
1662 
1663   // Define the properties if properties was specified and is not undefined.
1664   Handle<Object> properties = args.atOrUndefined(isolate, 2);
1665   if (!properties->IsUndefined(isolate)) {
1666     RETURN_FAILURE_ON_EXCEPTION(
1667         isolate, JSReceiver::DefineProperties(isolate, object, properties));
1668   }
1669 
1670   return *object;
1671 }
1672 
1673 // ES6 section 19.1.2.3 Object.defineProperties
BUILTIN(ObjectDefineProperties)1674 BUILTIN(ObjectDefineProperties) {
1675   HandleScope scope(isolate);
1676   DCHECK_EQ(3, args.length());
1677   Handle<Object> target = args.at<Object>(1);
1678   Handle<Object> properties = args.at<Object>(2);
1679 
1680   RETURN_RESULT_OR_FAILURE(
1681       isolate, JSReceiver::DefineProperties(isolate, target, properties));
1682 }
1683 
1684 // ES6 section 19.1.2.4 Object.defineProperty
BUILTIN(ObjectDefineProperty)1685 BUILTIN(ObjectDefineProperty) {
1686   HandleScope scope(isolate);
1687   DCHECK_EQ(4, args.length());
1688   Handle<Object> target = args.at<Object>(1);
1689   Handle<Object> key = args.at<Object>(2);
1690   Handle<Object> attributes = args.at<Object>(3);
1691 
1692   return JSReceiver::DefineProperty(isolate, target, key, attributes);
1693 }
1694 
1695 namespace {
1696 
1697 template <AccessorComponent which_accessor>
ObjectDefineAccessor(Isolate * isolate,Handle<Object> object,Handle<Object> name,Handle<Object> accessor)1698 Object* ObjectDefineAccessor(Isolate* isolate, Handle<Object> object,
1699                              Handle<Object> name, Handle<Object> accessor) {
1700   // 1. Let O be ? ToObject(this value).
1701   Handle<JSReceiver> receiver;
1702   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
1703                                      Object::ConvertReceiver(isolate, object));
1704   // 2. If IsCallable(getter) is false, throw a TypeError exception.
1705   if (!accessor->IsCallable()) {
1706     MessageTemplate::Template message =
1707         which_accessor == ACCESSOR_GETTER
1708             ? MessageTemplate::kObjectGetterExpectingFunction
1709             : MessageTemplate::kObjectSetterExpectingFunction;
1710     THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(message));
1711   }
1712   // 3. Let desc be PropertyDescriptor{[[Get]]: getter, [[Enumerable]]: true,
1713   //                                   [[Configurable]]: true}.
1714   PropertyDescriptor desc;
1715   if (which_accessor == ACCESSOR_GETTER) {
1716     desc.set_get(accessor);
1717   } else {
1718     DCHECK(which_accessor == ACCESSOR_SETTER);
1719     desc.set_set(accessor);
1720   }
1721   desc.set_enumerable(true);
1722   desc.set_configurable(true);
1723   // 4. Let key be ? ToPropertyKey(P).
1724   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
1725                                      Object::ToPropertyKey(isolate, name));
1726   // 5. Perform ? DefinePropertyOrThrow(O, key, desc).
1727   // To preserve legacy behavior, we ignore errors silently rather than
1728   // throwing an exception.
1729   Maybe<bool> success = JSReceiver::DefineOwnProperty(
1730       isolate, receiver, name, &desc, Object::DONT_THROW);
1731   MAYBE_RETURN(success, isolate->heap()->exception());
1732   if (!success.FromJust()) {
1733     isolate->CountUsage(v8::Isolate::kDefineGetterOrSetterWouldThrow);
1734   }
1735   // 6. Return undefined.
1736   return isolate->heap()->undefined_value();
1737 }
1738 
ObjectLookupAccessor(Isolate * isolate,Handle<Object> object,Handle<Object> key,AccessorComponent component)1739 Object* ObjectLookupAccessor(Isolate* isolate, Handle<Object> object,
1740                              Handle<Object> key, AccessorComponent component) {
1741   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, object,
1742                                      Object::ConvertReceiver(isolate, object));
1743   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key,
1744                                      Object::ToPropertyKey(isolate, key));
1745   bool success = false;
1746   LookupIterator it = LookupIterator::PropertyOrElement(
1747       isolate, object, key, &success,
1748       LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
1749   DCHECK(success);
1750 
1751   for (; it.IsFound(); it.Next()) {
1752     switch (it.state()) {
1753       case LookupIterator::INTERCEPTOR:
1754       case LookupIterator::NOT_FOUND:
1755       case LookupIterator::TRANSITION:
1756         UNREACHABLE();
1757 
1758       case LookupIterator::ACCESS_CHECK:
1759         if (it.HasAccess()) continue;
1760         isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>());
1761         RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
1762         return isolate->heap()->undefined_value();
1763 
1764       case LookupIterator::JSPROXY:
1765         return isolate->heap()->undefined_value();
1766 
1767       case LookupIterator::INTEGER_INDEXED_EXOTIC:
1768         return isolate->heap()->undefined_value();
1769       case LookupIterator::DATA:
1770         continue;
1771       case LookupIterator::ACCESSOR: {
1772         Handle<Object> maybe_pair = it.GetAccessors();
1773         if (maybe_pair->IsAccessorPair()) {
1774           return *AccessorPair::GetComponent(
1775               Handle<AccessorPair>::cast(maybe_pair), component);
1776         }
1777       }
1778     }
1779   }
1780 
1781   return isolate->heap()->undefined_value();
1782 }
1783 
1784 }  // namespace
1785 
1786 // ES6 B.2.2.2 a.k.a.
1787 // https://tc39.github.io/ecma262/#sec-object.prototype.__defineGetter__
BUILTIN(ObjectDefineGetter)1788 BUILTIN(ObjectDefineGetter) {
1789   HandleScope scope(isolate);
1790   Handle<Object> object = args.at<Object>(0);  // Receiver.
1791   Handle<Object> name = args.at<Object>(1);
1792   Handle<Object> getter = args.at<Object>(2);
1793   return ObjectDefineAccessor<ACCESSOR_GETTER>(isolate, object, name, getter);
1794 }
1795 
1796 // ES6 B.2.2.3 a.k.a.
1797 // https://tc39.github.io/ecma262/#sec-object.prototype.__defineSetter__
BUILTIN(ObjectDefineSetter)1798 BUILTIN(ObjectDefineSetter) {
1799   HandleScope scope(isolate);
1800   Handle<Object> object = args.at<Object>(0);  // Receiver.
1801   Handle<Object> name = args.at<Object>(1);
1802   Handle<Object> setter = args.at<Object>(2);
1803   return ObjectDefineAccessor<ACCESSOR_SETTER>(isolate, object, name, setter);
1804 }
1805 
1806 // ES6 B.2.2.4 a.k.a.
1807 // https://tc39.github.io/ecma262/#sec-object.prototype.__lookupGetter__
BUILTIN(ObjectLookupGetter)1808 BUILTIN(ObjectLookupGetter) {
1809   HandleScope scope(isolate);
1810   Handle<Object> object = args.at<Object>(0);
1811   Handle<Object> name = args.at<Object>(1);
1812   return ObjectLookupAccessor(isolate, object, name, ACCESSOR_GETTER);
1813 }
1814 
1815 // ES6 B.2.2.5 a.k.a.
1816 // https://tc39.github.io/ecma262/#sec-object.prototype.__lookupSetter__
BUILTIN(ObjectLookupSetter)1817 BUILTIN(ObjectLookupSetter) {
1818   HandleScope scope(isolate);
1819   Handle<Object> object = args.at<Object>(0);
1820   Handle<Object> name = args.at<Object>(1);
1821   return ObjectLookupAccessor(isolate, object, name, ACCESSOR_SETTER);
1822 }
1823 
1824 // ES6 section 19.1.2.5 Object.freeze ( O )
BUILTIN(ObjectFreeze)1825 BUILTIN(ObjectFreeze) {
1826   HandleScope scope(isolate);
1827   Handle<Object> object = args.atOrUndefined(isolate, 1);
1828   if (object->IsJSReceiver()) {
1829     MAYBE_RETURN(JSReceiver::SetIntegrityLevel(Handle<JSReceiver>::cast(object),
1830                                                FROZEN, Object::THROW_ON_ERROR),
1831                  isolate->heap()->exception());
1832   }
1833   return *object;
1834 }
1835 
1836 
1837 // ES section 19.1.2.9 Object.getPrototypeOf ( O )
BUILTIN(ObjectGetPrototypeOf)1838 BUILTIN(ObjectGetPrototypeOf) {
1839   HandleScope scope(isolate);
1840   Handle<Object> object = args.atOrUndefined(isolate, 1);
1841 
1842   Handle<JSReceiver> receiver;
1843   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1844       isolate, receiver, Object::ToObject(isolate, object));
1845 
1846   RETURN_RESULT_OR_FAILURE(isolate,
1847                            JSReceiver::GetPrototype(isolate, receiver));
1848 }
1849 
1850 
1851 // ES6 section 19.1.2.6 Object.getOwnPropertyDescriptor ( O, P )
BUILTIN(ObjectGetOwnPropertyDescriptor)1852 BUILTIN(ObjectGetOwnPropertyDescriptor) {
1853   HandleScope scope(isolate);
1854   // 1. Let obj be ? ToObject(O).
1855   Handle<Object> object = args.atOrUndefined(isolate, 1);
1856   Handle<JSReceiver> receiver;
1857   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
1858                                      Object::ToObject(isolate, object));
1859   // 2. Let key be ? ToPropertyKey(P).
1860   Handle<Object> property = args.atOrUndefined(isolate, 2);
1861   Handle<Name> key;
1862   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key,
1863                                      Object::ToName(isolate, property));
1864   // 3. Let desc be ? obj.[[GetOwnProperty]](key).
1865   PropertyDescriptor desc;
1866   Maybe<bool> found =
1867       JSReceiver::GetOwnPropertyDescriptor(isolate, receiver, key, &desc);
1868   MAYBE_RETURN(found, isolate->heap()->exception());
1869   // 4. Return FromPropertyDescriptor(desc).
1870   if (!found.FromJust()) return isolate->heap()->undefined_value();
1871   return *desc.ToObject(isolate);
1872 }
1873 
1874 
1875 namespace {
1876 
GetOwnPropertyKeys(Isolate * isolate,BuiltinArguments args,PropertyFilter filter)1877 Object* GetOwnPropertyKeys(Isolate* isolate, BuiltinArguments args,
1878                            PropertyFilter filter) {
1879   HandleScope scope(isolate);
1880   Handle<Object> object = args.atOrUndefined(isolate, 1);
1881   Handle<JSReceiver> receiver;
1882   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
1883                                      Object::ToObject(isolate, object));
1884   Handle<FixedArray> keys;
1885   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1886       isolate, keys,
1887       KeyAccumulator::GetKeys(receiver, KeyCollectionMode::kOwnOnly, filter,
1888                               GetKeysConversion::kConvertToString));
1889   return *isolate->factory()->NewJSArrayWithElements(keys);
1890 }
1891 
1892 }  // namespace
1893 
1894 
1895 // ES6 section 19.1.2.7 Object.getOwnPropertyNames ( O )
BUILTIN(ObjectGetOwnPropertyNames)1896 BUILTIN(ObjectGetOwnPropertyNames) {
1897   return GetOwnPropertyKeys(isolate, args, SKIP_SYMBOLS);
1898 }
1899 
1900 
1901 // ES6 section 19.1.2.8 Object.getOwnPropertySymbols ( O )
BUILTIN(ObjectGetOwnPropertySymbols)1902 BUILTIN(ObjectGetOwnPropertySymbols) {
1903   return GetOwnPropertyKeys(isolate, args, SKIP_STRINGS);
1904 }
1905 
1906 
1907 // ES#sec-object.is Object.is ( value1, value2 )
BUILTIN(ObjectIs)1908 BUILTIN(ObjectIs) {
1909   SealHandleScope shs(isolate);
1910   DCHECK_EQ(3, args.length());
1911   Handle<Object> value1 = args.at<Object>(1);
1912   Handle<Object> value2 = args.at<Object>(2);
1913   return isolate->heap()->ToBoolean(value1->SameValue(*value2));
1914 }
1915 
1916 
1917 // ES6 section 19.1.2.11 Object.isExtensible ( O )
BUILTIN(ObjectIsExtensible)1918 BUILTIN(ObjectIsExtensible) {
1919   HandleScope scope(isolate);
1920   Handle<Object> object = args.atOrUndefined(isolate, 1);
1921   Maybe<bool> result =
1922       object->IsJSReceiver()
1923           ? JSReceiver::IsExtensible(Handle<JSReceiver>::cast(object))
1924           : Just(false);
1925   MAYBE_RETURN(result, isolate->heap()->exception());
1926   return isolate->heap()->ToBoolean(result.FromJust());
1927 }
1928 
1929 
1930 // ES6 section 19.1.2.12 Object.isFrozen ( O )
BUILTIN(ObjectIsFrozen)1931 BUILTIN(ObjectIsFrozen) {
1932   HandleScope scope(isolate);
1933   Handle<Object> object = args.atOrUndefined(isolate, 1);
1934   Maybe<bool> result = object->IsJSReceiver()
1935                            ? JSReceiver::TestIntegrityLevel(
1936                                  Handle<JSReceiver>::cast(object), FROZEN)
1937                            : Just(true);
1938   MAYBE_RETURN(result, isolate->heap()->exception());
1939   return isolate->heap()->ToBoolean(result.FromJust());
1940 }
1941 
1942 
1943 // ES6 section 19.1.2.13 Object.isSealed ( O )
BUILTIN(ObjectIsSealed)1944 BUILTIN(ObjectIsSealed) {
1945   HandleScope scope(isolate);
1946   Handle<Object> object = args.atOrUndefined(isolate, 1);
1947   Maybe<bool> result = object->IsJSReceiver()
1948                            ? JSReceiver::TestIntegrityLevel(
1949                                  Handle<JSReceiver>::cast(object), SEALED)
1950                            : Just(true);
1951   MAYBE_RETURN(result, isolate->heap()->exception());
1952   return isolate->heap()->ToBoolean(result.FromJust());
1953 }
1954 
1955 
1956 // ES6 section 19.1.2.14 Object.keys ( O )
BUILTIN(ObjectKeys)1957 BUILTIN(ObjectKeys) {
1958   HandleScope scope(isolate);
1959   Handle<Object> object = args.atOrUndefined(isolate, 1);
1960   Handle<JSReceiver> receiver;
1961   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
1962                                      Object::ToObject(isolate, object));
1963 
1964   Handle<FixedArray> keys;
1965   int enum_length = receiver->map()->EnumLength();
1966   if (enum_length != kInvalidEnumCacheSentinel &&
1967       JSObject::cast(*receiver)->elements() ==
1968           isolate->heap()->empty_fixed_array()) {
1969     DCHECK(receiver->IsJSObject());
1970     DCHECK(!JSObject::cast(*receiver)->HasNamedInterceptor());
1971     DCHECK(!JSObject::cast(*receiver)->IsAccessCheckNeeded());
1972     DCHECK(!receiver->map()->has_hidden_prototype());
1973     DCHECK(JSObject::cast(*receiver)->HasFastProperties());
1974     if (enum_length == 0) {
1975       keys = isolate->factory()->empty_fixed_array();
1976     } else {
1977       Handle<FixedArray> cache(
1978           receiver->map()->instance_descriptors()->GetEnumCache());
1979       keys = isolate->factory()->CopyFixedArrayUpTo(cache, enum_length);
1980     }
1981   } else {
1982     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1983         isolate, keys,
1984         KeyAccumulator::GetKeys(receiver, KeyCollectionMode::kOwnOnly,
1985                                 ENUMERABLE_STRINGS,
1986                                 GetKeysConversion::kConvertToString));
1987   }
1988   return *isolate->factory()->NewJSArrayWithElements(keys, FAST_ELEMENTS);
1989 }
1990 
BUILTIN(ObjectValues)1991 BUILTIN(ObjectValues) {
1992   HandleScope scope(isolate);
1993   Handle<Object> object = args.atOrUndefined(isolate, 1);
1994   Handle<JSReceiver> receiver;
1995   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
1996                                      Object::ToObject(isolate, object));
1997   Handle<FixedArray> values;
1998   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1999       isolate, values, JSReceiver::GetOwnValues(receiver, ENUMERABLE_STRINGS));
2000   return *isolate->factory()->NewJSArrayWithElements(values);
2001 }
2002 
2003 
BUILTIN(ObjectEntries)2004 BUILTIN(ObjectEntries) {
2005   HandleScope scope(isolate);
2006   Handle<Object> object = args.atOrUndefined(isolate, 1);
2007   Handle<JSReceiver> receiver;
2008   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
2009                                      Object::ToObject(isolate, object));
2010   Handle<FixedArray> entries;
2011   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2012       isolate, entries,
2013       JSReceiver::GetOwnEntries(receiver, ENUMERABLE_STRINGS));
2014   return *isolate->factory()->NewJSArrayWithElements(entries);
2015 }
2016 
BUILTIN(ObjectGetOwnPropertyDescriptors)2017 BUILTIN(ObjectGetOwnPropertyDescriptors) {
2018   HandleScope scope(isolate);
2019   Handle<Object> object = args.atOrUndefined(isolate, 1);
2020   Handle<Object> undefined = isolate->factory()->undefined_value();
2021 
2022   Handle<JSReceiver> receiver;
2023   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
2024                                      Object::ToObject(isolate, object));
2025 
2026   Handle<FixedArray> keys;
2027   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2028       isolate, keys, KeyAccumulator::GetKeys(
2029                          receiver, KeyCollectionMode::kOwnOnly, ALL_PROPERTIES,
2030                          GetKeysConversion::kConvertToString));
2031 
2032   Handle<JSObject> descriptors =
2033       isolate->factory()->NewJSObject(isolate->object_function());
2034 
2035   for (int i = 0; i < keys->length(); ++i) {
2036     Handle<Name> key = Handle<Name>::cast(FixedArray::get(*keys, i, isolate));
2037     PropertyDescriptor descriptor;
2038     Maybe<bool> did_get_descriptor = JSReceiver::GetOwnPropertyDescriptor(
2039         isolate, receiver, key, &descriptor);
2040     MAYBE_RETURN(did_get_descriptor, isolate->heap()->exception());
2041 
2042     Handle<Object> from_descriptor = did_get_descriptor.FromJust()
2043                                          ? descriptor.ToObject(isolate)
2044                                          : undefined;
2045 
2046     LookupIterator it = LookupIterator::PropertyOrElement(
2047         isolate, descriptors, key, descriptors, LookupIterator::OWN);
2048     Maybe<bool> success = JSReceiver::CreateDataProperty(&it, from_descriptor,
2049                                                          Object::DONT_THROW);
2050     CHECK(success.FromJust());
2051   }
2052 
2053   return *descriptors;
2054 }
2055 
2056 // ES6 section 19.1.2.15 Object.preventExtensions ( O )
BUILTIN(ObjectPreventExtensions)2057 BUILTIN(ObjectPreventExtensions) {
2058   HandleScope scope(isolate);
2059   Handle<Object> object = args.atOrUndefined(isolate, 1);
2060   if (object->IsJSReceiver()) {
2061     MAYBE_RETURN(JSReceiver::PreventExtensions(Handle<JSReceiver>::cast(object),
2062                                                Object::THROW_ON_ERROR),
2063                  isolate->heap()->exception());
2064   }
2065   return *object;
2066 }
2067 
2068 
2069 // ES6 section 19.1.2.17 Object.seal ( O )
BUILTIN(ObjectSeal)2070 BUILTIN(ObjectSeal) {
2071   HandleScope scope(isolate);
2072   Handle<Object> object = args.atOrUndefined(isolate, 1);
2073   if (object->IsJSReceiver()) {
2074     MAYBE_RETURN(JSReceiver::SetIntegrityLevel(Handle<JSReceiver>::cast(object),
2075                                                SEALED, Object::THROW_ON_ERROR),
2076                  isolate->heap()->exception());
2077   }
2078   return *object;
2079 }
2080 
2081 // ES6 section 18.2.6.2 decodeURI (encodedURI)
BUILTIN(GlobalDecodeURI)2082 BUILTIN(GlobalDecodeURI) {
2083   HandleScope scope(isolate);
2084   Handle<String> encoded_uri;
2085   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2086       isolate, encoded_uri,
2087       Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
2088 
2089   RETURN_RESULT_OR_FAILURE(isolate, Uri::DecodeUri(isolate, encoded_uri));
2090 }
2091 
2092 // ES6 section 18.2.6.3 decodeURIComponent (encodedURIComponent)
BUILTIN(GlobalDecodeURIComponent)2093 BUILTIN(GlobalDecodeURIComponent) {
2094   HandleScope scope(isolate);
2095   Handle<String> encoded_uri_component;
2096   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2097       isolate, encoded_uri_component,
2098       Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
2099 
2100   RETURN_RESULT_OR_FAILURE(
2101       isolate, Uri::DecodeUriComponent(isolate, encoded_uri_component));
2102 }
2103 
2104 // ES6 section 18.2.6.4 encodeURI (uri)
BUILTIN(GlobalEncodeURI)2105 BUILTIN(GlobalEncodeURI) {
2106   HandleScope scope(isolate);
2107   Handle<String> uri;
2108   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2109       isolate, uri, Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
2110 
2111   RETURN_RESULT_OR_FAILURE(isolate, Uri::EncodeUri(isolate, uri));
2112 }
2113 
2114 // ES6 section 18.2.6.5 encodeURIComponenet (uriComponent)
BUILTIN(GlobalEncodeURIComponent)2115 BUILTIN(GlobalEncodeURIComponent) {
2116   HandleScope scope(isolate);
2117   Handle<String> uri_component;
2118   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2119       isolate, uri_component,
2120       Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
2121 
2122   RETURN_RESULT_OR_FAILURE(isolate,
2123                            Uri::EncodeUriComponent(isolate, uri_component));
2124 }
2125 
2126 // ES6 section B.2.1.1 escape (string)
BUILTIN(GlobalEscape)2127 BUILTIN(GlobalEscape) {
2128   HandleScope scope(isolate);
2129   Handle<String> string;
2130   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2131       isolate, string,
2132       Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
2133 
2134   RETURN_RESULT_OR_FAILURE(isolate, Uri::Escape(isolate, string));
2135 }
2136 
2137 // ES6 section B.2.1.2 unescape (string)
BUILTIN(GlobalUnescape)2138 BUILTIN(GlobalUnescape) {
2139   HandleScope scope(isolate);
2140   Handle<String> string;
2141   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2142       isolate, string,
2143       Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
2144 
2145   RETURN_RESULT_OR_FAILURE(isolate, Uri::Unescape(isolate, string));
2146 }
2147 
2148 namespace {
2149 
CodeGenerationFromStringsAllowed(Isolate * isolate,Handle<Context> context)2150 bool CodeGenerationFromStringsAllowed(Isolate* isolate,
2151                                       Handle<Context> context) {
2152   DCHECK(context->allow_code_gen_from_strings()->IsFalse(isolate));
2153   // Check with callback if set.
2154   AllowCodeGenerationFromStringsCallback callback =
2155       isolate->allow_code_gen_callback();
2156   if (callback == NULL) {
2157     // No callback set and code generation disallowed.
2158     return false;
2159   } else {
2160     // Callback set. Let it decide if code generation is allowed.
2161     VMState<EXTERNAL> state(isolate);
2162     return callback(v8::Utils::ToLocal(context));
2163   }
2164 }
2165 
2166 
CompileString(Handle<Context> context,Handle<String> source,ParseRestriction restriction)2167 MaybeHandle<JSFunction> CompileString(Handle<Context> context,
2168                                       Handle<String> source,
2169                                       ParseRestriction restriction) {
2170   Isolate* const isolate = context->GetIsolate();
2171   Handle<Context> native_context(context->native_context(), isolate);
2172 
2173   // Check if native context allows code generation from
2174   // strings. Throw an exception if it doesn't.
2175   if (native_context->allow_code_gen_from_strings()->IsFalse(isolate) &&
2176       !CodeGenerationFromStringsAllowed(isolate, native_context)) {
2177     Handle<Object> error_message =
2178         native_context->ErrorMessageForCodeGenerationFromStrings();
2179     THROW_NEW_ERROR(isolate, NewEvalError(MessageTemplate::kCodeGenFromStrings,
2180                                           error_message),
2181                     JSFunction);
2182   }
2183 
2184   // Compile source string in the native context.
2185   int eval_scope_position = 0;
2186   int eval_position = RelocInfo::kNoPosition;
2187   Handle<SharedFunctionInfo> outer_info(native_context->closure()->shared());
2188   return Compiler::GetFunctionFromEval(source, outer_info, native_context,
2189                                        SLOPPY, restriction, eval_scope_position,
2190                                        eval_position);
2191 }
2192 
2193 }  // namespace
2194 
2195 
2196 // ES6 section 18.2.1 eval (x)
BUILTIN(GlobalEval)2197 BUILTIN(GlobalEval) {
2198   HandleScope scope(isolate);
2199   Handle<Object> x = args.atOrUndefined(isolate, 1);
2200   Handle<JSFunction> target = args.target<JSFunction>();
2201   Handle<JSObject> target_global_proxy(target->global_proxy(), isolate);
2202   if (!x->IsString()) return *x;
2203   Handle<JSFunction> function;
2204   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2205       isolate, function,
2206       CompileString(handle(target->native_context(), isolate),
2207                     Handle<String>::cast(x), NO_PARSE_RESTRICTION));
2208   RETURN_RESULT_OR_FAILURE(
2209       isolate,
2210       Execution::Call(isolate, function, target_global_proxy, 0, nullptr));
2211 }
2212 
2213 // ES6 section 24.3.1 JSON.parse.
BUILTIN(JsonParse)2214 BUILTIN(JsonParse) {
2215   HandleScope scope(isolate);
2216   Handle<Object> source = args.atOrUndefined(isolate, 1);
2217   Handle<Object> reviver = args.atOrUndefined(isolate, 2);
2218   Handle<String> string;
2219   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, string,
2220                                      Object::ToString(isolate, source));
2221   string = String::Flatten(string);
2222   RETURN_RESULT_OR_FAILURE(
2223       isolate, string->IsSeqOneByteString()
2224                    ? JsonParser<true>::Parse(isolate, string, reviver)
2225                    : JsonParser<false>::Parse(isolate, string, reviver));
2226 }
2227 
2228 // ES6 section 24.3.2 JSON.stringify.
BUILTIN(JsonStringify)2229 BUILTIN(JsonStringify) {
2230   HandleScope scope(isolate);
2231   JsonStringifier stringifier(isolate);
2232   Handle<Object> object = args.atOrUndefined(isolate, 1);
2233   Handle<Object> replacer = args.atOrUndefined(isolate, 2);
2234   Handle<Object> indent = args.atOrUndefined(isolate, 3);
2235   RETURN_RESULT_OR_FAILURE(isolate,
2236                            stringifier.Stringify(object, replacer, indent));
2237 }
2238 
2239 // -----------------------------------------------------------------------------
2240 // ES6 section 20.2.2 Function Properties of the Math Object
2241 
2242 
2243 // ES6 section 20.2.2.2 Math.acos ( x )
BUILTIN(MathAcos)2244 BUILTIN(MathAcos) {
2245   HandleScope scope(isolate);
2246   DCHECK_EQ(2, args.length());
2247   Handle<Object> x = args.at<Object>(1);
2248   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x, Object::ToNumber(x));
2249   return *isolate->factory()->NewHeapNumber(std::acos(x->Number()));
2250 }
2251 
2252 
2253 // ES6 section 20.2.2.4 Math.asin ( x )
BUILTIN(MathAsin)2254 BUILTIN(MathAsin) {
2255   HandleScope scope(isolate);
2256   DCHECK_EQ(2, args.length());
2257   Handle<Object> x = args.at<Object>(1);
2258   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x, Object::ToNumber(x));
2259   return *isolate->factory()->NewHeapNumber(std::asin(x->Number()));
2260 }
2261 
2262 // ES6 section 20.2.2.6 Math.atan ( x )
Generate_MathAtan(CodeStubAssembler * assembler)2263 void Builtins::Generate_MathAtan(CodeStubAssembler* assembler) {
2264   using compiler::Node;
2265 
2266   Node* x = assembler->Parameter(1);
2267   Node* context = assembler->Parameter(4);
2268   Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
2269   Node* value = assembler->Float64Atan(x_value);
2270   Node* result = assembler->ChangeFloat64ToTagged(value);
2271   assembler->Return(result);
2272 }
2273 
2274 // ES6 section 20.2.2.8 Math.atan2 ( y, x )
Generate_MathAtan2(CodeStubAssembler * assembler)2275 void Builtins::Generate_MathAtan2(CodeStubAssembler* assembler) {
2276   using compiler::Node;
2277 
2278   Node* y = assembler->Parameter(1);
2279   Node* x = assembler->Parameter(2);
2280   Node* context = assembler->Parameter(5);
2281   Node* y_value = assembler->TruncateTaggedToFloat64(context, y);
2282   Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
2283   Node* value = assembler->Float64Atan2(y_value, x_value);
2284   Node* result = assembler->ChangeFloat64ToTagged(value);
2285   assembler->Return(result);
2286 }
2287 
2288 // ES6 section 20.2.2.7 Math.atanh ( x )
Generate_MathAtanh(CodeStubAssembler * assembler)2289 void Builtins::Generate_MathAtanh(CodeStubAssembler* assembler) {
2290   using compiler::Node;
2291 
2292   Node* x = assembler->Parameter(1);
2293   Node* context = assembler->Parameter(4);
2294   Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
2295   Node* value = assembler->Float64Atanh(x_value);
2296   Node* result = assembler->ChangeFloat64ToTagged(value);
2297   assembler->Return(result);
2298 }
2299 
2300 namespace {
2301 
Generate_MathRoundingOperation(CodeStubAssembler * assembler,compiler::Node * (CodeStubAssembler::* float64op)(compiler::Node *))2302 void Generate_MathRoundingOperation(
2303     CodeStubAssembler* assembler,
2304     compiler::Node* (CodeStubAssembler::*float64op)(compiler::Node*)) {
2305   typedef CodeStubAssembler::Label Label;
2306   typedef compiler::Node Node;
2307   typedef CodeStubAssembler::Variable Variable;
2308 
2309   Node* context = assembler->Parameter(4);
2310 
2311   // We might need to loop once for ToNumber conversion.
2312   Variable var_x(assembler, MachineRepresentation::kTagged);
2313   Label loop(assembler, &var_x);
2314   var_x.Bind(assembler->Parameter(1));
2315   assembler->Goto(&loop);
2316   assembler->Bind(&loop);
2317   {
2318     // Load the current {x} value.
2319     Node* x = var_x.value();
2320 
2321     // Check if {x} is a Smi or a HeapObject.
2322     Label if_xissmi(assembler), if_xisnotsmi(assembler);
2323     assembler->Branch(assembler->WordIsSmi(x), &if_xissmi, &if_xisnotsmi);
2324 
2325     assembler->Bind(&if_xissmi);
2326     {
2327       // Nothing to do when {x} is a Smi.
2328       assembler->Return(x);
2329     }
2330 
2331     assembler->Bind(&if_xisnotsmi);
2332     {
2333       // Check if {x} is a HeapNumber.
2334       Label if_xisheapnumber(assembler),
2335           if_xisnotheapnumber(assembler, Label::kDeferred);
2336       assembler->Branch(
2337           assembler->WordEqual(assembler->LoadMap(x),
2338                                assembler->HeapNumberMapConstant()),
2339           &if_xisheapnumber, &if_xisnotheapnumber);
2340 
2341       assembler->Bind(&if_xisheapnumber);
2342       {
2343         Node* x_value = assembler->LoadHeapNumberValue(x);
2344         Node* value = (assembler->*float64op)(x_value);
2345         Node* result = assembler->ChangeFloat64ToTagged(value);
2346         assembler->Return(result);
2347       }
2348 
2349       assembler->Bind(&if_xisnotheapnumber);
2350       {
2351         // Need to convert {x} to a Number first.
2352         Callable callable =
2353             CodeFactory::NonNumberToNumber(assembler->isolate());
2354         var_x.Bind(assembler->CallStub(callable, context, x));
2355         assembler->Goto(&loop);
2356       }
2357     }
2358   }
2359 }
2360 
2361 }  // namespace
2362 
2363 // ES6 section 20.2.2.10 Math.ceil ( x )
Generate_MathCeil(CodeStubAssembler * assembler)2364 void Builtins::Generate_MathCeil(CodeStubAssembler* assembler) {
2365   Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Ceil);
2366 }
2367 
2368 // ES6 section 20.2.2.9 Math.cbrt ( x )
Generate_MathCbrt(CodeStubAssembler * assembler)2369 void Builtins::Generate_MathCbrt(CodeStubAssembler* assembler) {
2370   using compiler::Node;
2371 
2372   Node* x = assembler->Parameter(1);
2373   Node* context = assembler->Parameter(4);
2374   Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
2375   Node* value = assembler->Float64Cbrt(x_value);
2376   Node* result = assembler->ChangeFloat64ToTagged(value);
2377   assembler->Return(result);
2378 }
2379 
2380 // ES6 section 20.2.2.11 Math.clz32 ( x )
Generate_MathClz32(CodeStubAssembler * assembler)2381 void Builtins::Generate_MathClz32(CodeStubAssembler* assembler) {
2382   typedef CodeStubAssembler::Label Label;
2383   typedef compiler::Node Node;
2384   typedef CodeStubAssembler::Variable Variable;
2385 
2386   Node* context = assembler->Parameter(4);
2387 
2388   // Shared entry point for the clz32 operation.
2389   Variable var_clz32_x(assembler, MachineRepresentation::kWord32);
2390   Label do_clz32(assembler);
2391 
2392   // We might need to loop once for ToNumber conversion.
2393   Variable var_x(assembler, MachineRepresentation::kTagged);
2394   Label loop(assembler, &var_x);
2395   var_x.Bind(assembler->Parameter(1));
2396   assembler->Goto(&loop);
2397   assembler->Bind(&loop);
2398   {
2399     // Load the current {x} value.
2400     Node* x = var_x.value();
2401 
2402     // Check if {x} is a Smi or a HeapObject.
2403     Label if_xissmi(assembler), if_xisnotsmi(assembler);
2404     assembler->Branch(assembler->WordIsSmi(x), &if_xissmi, &if_xisnotsmi);
2405 
2406     assembler->Bind(&if_xissmi);
2407     {
2408       var_clz32_x.Bind(assembler->SmiToWord32(x));
2409       assembler->Goto(&do_clz32);
2410     }
2411 
2412     assembler->Bind(&if_xisnotsmi);
2413     {
2414       // Check if {x} is a HeapNumber.
2415       Label if_xisheapnumber(assembler),
2416           if_xisnotheapnumber(assembler, Label::kDeferred);
2417       assembler->Branch(
2418           assembler->WordEqual(assembler->LoadMap(x),
2419                                assembler->HeapNumberMapConstant()),
2420           &if_xisheapnumber, &if_xisnotheapnumber);
2421 
2422       assembler->Bind(&if_xisheapnumber);
2423       {
2424         var_clz32_x.Bind(assembler->TruncateHeapNumberValueToWord32(x));
2425         assembler->Goto(&do_clz32);
2426       }
2427 
2428       assembler->Bind(&if_xisnotheapnumber);
2429       {
2430         // Need to convert {x} to a Number first.
2431         Callable callable =
2432             CodeFactory::NonNumberToNumber(assembler->isolate());
2433         var_x.Bind(assembler->CallStub(callable, context, x));
2434         assembler->Goto(&loop);
2435       }
2436     }
2437   }
2438 
2439   assembler->Bind(&do_clz32);
2440   {
2441     Node* x_value = var_clz32_x.value();
2442     Node* value = assembler->Word32Clz(x_value);
2443     Node* result = assembler->ChangeInt32ToTagged(value);
2444     assembler->Return(result);
2445   }
2446 }
2447 
2448 // ES6 section 20.2.2.12 Math.cos ( x )
Generate_MathCos(CodeStubAssembler * assembler)2449 void Builtins::Generate_MathCos(CodeStubAssembler* assembler) {
2450   using compiler::Node;
2451 
2452   Node* x = assembler->Parameter(1);
2453   Node* context = assembler->Parameter(4);
2454   Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
2455   Node* value = assembler->Float64Cos(x_value);
2456   Node* result = assembler->ChangeFloat64ToTagged(value);
2457   assembler->Return(result);
2458 }
2459 
2460 // ES6 section 20.2.2.14 Math.exp ( x )
Generate_MathExp(CodeStubAssembler * assembler)2461 void Builtins::Generate_MathExp(CodeStubAssembler* assembler) {
2462   using compiler::Node;
2463 
2464   Node* x = assembler->Parameter(1);
2465   Node* context = assembler->Parameter(4);
2466   Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
2467   Node* value = assembler->Float64Exp(x_value);
2468   Node* result = assembler->ChangeFloat64ToTagged(value);
2469   assembler->Return(result);
2470 }
2471 
2472 // ES6 section 20.2.2.16 Math.floor ( x )
Generate_MathFloor(CodeStubAssembler * assembler)2473 void Builtins::Generate_MathFloor(CodeStubAssembler* assembler) {
2474   Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Floor);
2475 }
2476 
2477 // ES6 section 20.2.2.17 Math.fround ( x )
BUILTIN(MathFround)2478 BUILTIN(MathFround) {
2479   HandleScope scope(isolate);
2480   DCHECK_EQ(2, args.length());
2481   Handle<Object> x = args.at<Object>(1);
2482   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x, Object::ToNumber(x));
2483   float x32 = DoubleToFloat32(x->Number());
2484   return *isolate->factory()->NewNumber(x32);
2485 }
2486 
2487 // ES6 section 20.2.2.19 Math.imul ( x, y )
BUILTIN(MathImul)2488 BUILTIN(MathImul) {
2489   HandleScope scope(isolate);
2490   DCHECK_EQ(3, args.length());
2491   Handle<Object> x = args.at<Object>(1);
2492   Handle<Object> y = args.at<Object>(2);
2493   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x, Object::ToNumber(x));
2494   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, y, Object::ToNumber(y));
2495   int product = static_cast<int>(NumberToUint32(*x) * NumberToUint32(*y));
2496   return *isolate->factory()->NewNumberFromInt(product);
2497 }
2498 
2499 // ES6 section 20.2.2.20 Math.log ( x )
Generate_MathLog(CodeStubAssembler * assembler)2500 void Builtins::Generate_MathLog(CodeStubAssembler* assembler) {
2501   using compiler::Node;
2502 
2503   Node* x = assembler->Parameter(1);
2504   Node* context = assembler->Parameter(4);
2505   Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
2506   Node* value = assembler->Float64Log(x_value);
2507   Node* result = assembler->ChangeFloat64ToTagged(value);
2508   assembler->Return(result);
2509 }
2510 
2511 // ES6 section 20.2.2.21 Math.log1p ( x )
Generate_MathLog1p(CodeStubAssembler * assembler)2512 void Builtins::Generate_MathLog1p(CodeStubAssembler* assembler) {
2513   using compiler::Node;
2514 
2515   Node* x = assembler->Parameter(1);
2516   Node* context = assembler->Parameter(4);
2517   Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
2518   Node* value = assembler->Float64Log1p(x_value);
2519   Node* result = assembler->ChangeFloat64ToTagged(value);
2520   assembler->Return(result);
2521 }
2522 
2523 // ES6 section 20.2.2.23 Math.log2 ( x )
Generate_MathLog2(CodeStubAssembler * assembler)2524 void Builtins::Generate_MathLog2(CodeStubAssembler* assembler) {
2525   using compiler::Node;
2526 
2527   Node* x = assembler->Parameter(1);
2528   Node* context = assembler->Parameter(4);
2529   Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
2530   Node* value = assembler->Float64Log2(x_value);
2531   Node* result = assembler->ChangeFloat64ToTagged(value);
2532   assembler->Return(result);
2533 }
2534 
2535 // ES6 section 20.2.2.22 Math.log10 ( x )
Generate_MathLog10(CodeStubAssembler * assembler)2536 void Builtins::Generate_MathLog10(CodeStubAssembler* assembler) {
2537   using compiler::Node;
2538 
2539   Node* x = assembler->Parameter(1);
2540   Node* context = assembler->Parameter(4);
2541   Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
2542   Node* value = assembler->Float64Log10(x_value);
2543   Node* result = assembler->ChangeFloat64ToTagged(value);
2544   assembler->Return(result);
2545 }
2546 
2547 // ES6 section 20.2.2.15 Math.expm1 ( x )
Generate_MathExpm1(CodeStubAssembler * assembler)2548 void Builtins::Generate_MathExpm1(CodeStubAssembler* assembler) {
2549   using compiler::Node;
2550 
2551   Node* x = assembler->Parameter(1);
2552   Node* context = assembler->Parameter(4);
2553   Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
2554   Node* value = assembler->Float64Expm1(x_value);
2555   Node* result = assembler->ChangeFloat64ToTagged(value);
2556   assembler->Return(result);
2557 }
2558 
2559 // ES6 section 20.2.2.28 Math.round ( x )
Generate_MathRound(CodeStubAssembler * assembler)2560 void Builtins::Generate_MathRound(CodeStubAssembler* assembler) {
2561   Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Round);
2562 }
2563 
2564 // ES6 section 20.2.2.30 Math.sin ( x )
Generate_MathSin(CodeStubAssembler * assembler)2565 void Builtins::Generate_MathSin(CodeStubAssembler* assembler) {
2566   using compiler::Node;
2567 
2568   Node* x = assembler->Parameter(1);
2569   Node* context = assembler->Parameter(4);
2570   Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
2571   Node* value = assembler->Float64Sin(x_value);
2572   Node* result = assembler->ChangeFloat64ToTagged(value);
2573   assembler->Return(result);
2574 }
2575 
2576 // ES6 section 20.2.2.32 Math.sqrt ( x )
Generate_MathSqrt(CodeStubAssembler * assembler)2577 void Builtins::Generate_MathSqrt(CodeStubAssembler* assembler) {
2578   using compiler::Node;
2579 
2580   Node* x = assembler->Parameter(1);
2581   Node* context = assembler->Parameter(4);
2582   Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
2583   Node* value = assembler->Float64Sqrt(x_value);
2584   Node* result = assembler->ChangeFloat64ToTagged(value);
2585   assembler->Return(result);
2586 }
2587 
2588 // ES6 section 20.2.2.33 Math.tan ( x )
Generate_MathTan(CodeStubAssembler * assembler)2589 void Builtins::Generate_MathTan(CodeStubAssembler* assembler) {
2590   using compiler::Node;
2591 
2592   Node* x = assembler->Parameter(1);
2593   Node* context = assembler->Parameter(4);
2594   Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
2595   Node* value = assembler->Float64Tan(x_value);
2596   Node* result = assembler->ChangeFloat64ToTagged(value);
2597   assembler->Return(result);
2598 }
2599 
2600 // ES6 section 20.2.2.35 Math.trunc ( x )
Generate_MathTrunc(CodeStubAssembler * assembler)2601 void Builtins::Generate_MathTrunc(CodeStubAssembler* assembler) {
2602   Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Trunc);
2603 }
2604 
2605 // -----------------------------------------------------------------------------
2606 // ES6 section 19.2 Function Objects
2607 
2608 // ES6 section 19.2.3.6 Function.prototype [ @@hasInstance ] ( V )
Generate_FunctionPrototypeHasInstance(CodeStubAssembler * assembler)2609 void Builtins::Generate_FunctionPrototypeHasInstance(
2610     CodeStubAssembler* assembler) {
2611   using compiler::Node;
2612 
2613   Node* f = assembler->Parameter(0);
2614   Node* v = assembler->Parameter(1);
2615   Node* context = assembler->Parameter(4);
2616   Node* result = assembler->OrdinaryHasInstance(context, f, v);
2617   assembler->Return(result);
2618 }
2619 
2620 // -----------------------------------------------------------------------------
2621 // ES6 section 25.3 Generator Objects
2622 
2623 namespace {
2624 
Generate_GeneratorPrototypeResume(CodeStubAssembler * assembler,JSGeneratorObject::ResumeMode resume_mode,char const * const method_name)2625 void Generate_GeneratorPrototypeResume(
2626     CodeStubAssembler* assembler, JSGeneratorObject::ResumeMode resume_mode,
2627     char const* const method_name) {
2628   typedef CodeStubAssembler::Label Label;
2629   typedef compiler::Node Node;
2630 
2631   Node* receiver = assembler->Parameter(0);
2632   Node* value = assembler->Parameter(1);
2633   Node* context = assembler->Parameter(4);
2634   Node* closed = assembler->SmiConstant(
2635       Smi::FromInt(JSGeneratorObject::kGeneratorClosed));
2636 
2637   // Check if the {receiver} is actually a JSGeneratorObject.
2638   Label if_receiverisincompatible(assembler, Label::kDeferred);
2639   assembler->GotoIf(assembler->WordIsSmi(receiver), &if_receiverisincompatible);
2640   Node* receiver_instance_type = assembler->LoadInstanceType(receiver);
2641   assembler->GotoUnless(assembler->Word32Equal(
2642                             receiver_instance_type,
2643                             assembler->Int32Constant(JS_GENERATOR_OBJECT_TYPE)),
2644                         &if_receiverisincompatible);
2645 
2646   // Check if the {receiver} is running or already closed.
2647   Node* receiver_continuation = assembler->LoadObjectField(
2648       receiver, JSGeneratorObject::kContinuationOffset);
2649   Label if_receiverisclosed(assembler, Label::kDeferred),
2650       if_receiverisrunning(assembler, Label::kDeferred);
2651   assembler->GotoIf(assembler->SmiEqual(receiver_continuation, closed),
2652                     &if_receiverisclosed);
2653   DCHECK_LT(JSGeneratorObject::kGeneratorExecuting,
2654             JSGeneratorObject::kGeneratorClosed);
2655   assembler->GotoIf(assembler->SmiLessThan(receiver_continuation, closed),
2656                     &if_receiverisrunning);
2657 
2658   // Resume the {receiver} using our trampoline.
2659   Node* result = assembler->CallStub(
2660       CodeFactory::ResumeGenerator(assembler->isolate()), context, value,
2661       receiver, assembler->SmiConstant(Smi::FromInt(resume_mode)));
2662   assembler->Return(result);
2663 
2664   assembler->Bind(&if_receiverisincompatible);
2665   {
2666     // The {receiver} is not a valid JSGeneratorObject.
2667     Node* result = assembler->CallRuntime(
2668         Runtime::kThrowIncompatibleMethodReceiver, context,
2669         assembler->HeapConstant(assembler->factory()->NewStringFromAsciiChecked(
2670             method_name, TENURED)),
2671         receiver);
2672     assembler->Return(result);  // Never reached.
2673   }
2674 
2675   assembler->Bind(&if_receiverisclosed);
2676   {
2677     // The {receiver} is closed already.
2678     Node* result = nullptr;
2679     switch (resume_mode) {
2680       case JSGeneratorObject::kNext:
2681         result = assembler->CallRuntime(Runtime::kCreateIterResultObject,
2682                                         context, assembler->UndefinedConstant(),
2683                                         assembler->BooleanConstant(true));
2684         break;
2685       case JSGeneratorObject::kReturn:
2686         result =
2687             assembler->CallRuntime(Runtime::kCreateIterResultObject, context,
2688                                    value, assembler->BooleanConstant(true));
2689         break;
2690       case JSGeneratorObject::kThrow:
2691         result = assembler->CallRuntime(Runtime::kThrow, context, value);
2692         break;
2693     }
2694     assembler->Return(result);
2695   }
2696 
2697   assembler->Bind(&if_receiverisrunning);
2698   {
2699     Node* result =
2700         assembler->CallRuntime(Runtime::kThrowGeneratorRunning, context);
2701     assembler->Return(result);  // Never reached.
2702   }
2703 }
2704 
2705 }  // namespace
2706 
2707 // ES6 section 25.3.1.2 Generator.prototype.next ( value )
Generate_GeneratorPrototypeNext(CodeStubAssembler * assembler)2708 void Builtins::Generate_GeneratorPrototypeNext(CodeStubAssembler* assembler) {
2709   Generate_GeneratorPrototypeResume(assembler, JSGeneratorObject::kNext,
2710                                     "[Generator].prototype.next");
2711 }
2712 
2713 // ES6 section 25.3.1.3 Generator.prototype.return ( value )
Generate_GeneratorPrototypeReturn(CodeStubAssembler * assembler)2714 void Builtins::Generate_GeneratorPrototypeReturn(CodeStubAssembler* assembler) {
2715   Generate_GeneratorPrototypeResume(assembler, JSGeneratorObject::kReturn,
2716                                     "[Generator].prototype.return");
2717 }
2718 
2719 // ES6 section 25.3.1.4 Generator.prototype.throw ( exception )
Generate_GeneratorPrototypeThrow(CodeStubAssembler * assembler)2720 void Builtins::Generate_GeneratorPrototypeThrow(CodeStubAssembler* assembler) {
2721   Generate_GeneratorPrototypeResume(assembler, JSGeneratorObject::kThrow,
2722                                     "[Generator].prototype.throw");
2723 }
2724 
2725 // -----------------------------------------------------------------------------
2726 // ES6 section 26.1 The Reflect Object
2727 
2728 // ES6 section 26.1.3 Reflect.defineProperty
BUILTIN(ReflectDefineProperty)2729 BUILTIN(ReflectDefineProperty) {
2730   HandleScope scope(isolate);
2731   DCHECK_EQ(4, args.length());
2732   Handle<Object> target = args.at<Object>(1);
2733   Handle<Object> key = args.at<Object>(2);
2734   Handle<Object> attributes = args.at<Object>(3);
2735 
2736   if (!target->IsJSReceiver()) {
2737     THROW_NEW_ERROR_RETURN_FAILURE(
2738         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2739                               isolate->factory()->NewStringFromAsciiChecked(
2740                                   "Reflect.defineProperty")));
2741   }
2742 
2743   Handle<Name> name;
2744   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
2745                                      Object::ToName(isolate, key));
2746 
2747   PropertyDescriptor desc;
2748   if (!PropertyDescriptor::ToPropertyDescriptor(isolate, attributes, &desc)) {
2749     return isolate->heap()->exception();
2750   }
2751 
2752   Maybe<bool> result =
2753       JSReceiver::DefineOwnProperty(isolate, Handle<JSReceiver>::cast(target),
2754                                     name, &desc, Object::DONT_THROW);
2755   MAYBE_RETURN(result, isolate->heap()->exception());
2756   return *isolate->factory()->ToBoolean(result.FromJust());
2757 }
2758 
2759 
2760 // ES6 section 26.1.4 Reflect.deleteProperty
BUILTIN(ReflectDeleteProperty)2761 BUILTIN(ReflectDeleteProperty) {
2762   HandleScope scope(isolate);
2763   DCHECK_EQ(3, args.length());
2764   Handle<Object> target = args.at<Object>(1);
2765   Handle<Object> key = args.at<Object>(2);
2766 
2767   if (!target->IsJSReceiver()) {
2768     THROW_NEW_ERROR_RETURN_FAILURE(
2769         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2770                               isolate->factory()->NewStringFromAsciiChecked(
2771                                   "Reflect.deleteProperty")));
2772   }
2773 
2774   Handle<Name> name;
2775   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
2776                                      Object::ToName(isolate, key));
2777 
2778   Maybe<bool> result = JSReceiver::DeletePropertyOrElement(
2779       Handle<JSReceiver>::cast(target), name, SLOPPY);
2780   MAYBE_RETURN(result, isolate->heap()->exception());
2781   return *isolate->factory()->ToBoolean(result.FromJust());
2782 }
2783 
2784 
2785 // ES6 section 26.1.6 Reflect.get
BUILTIN(ReflectGet)2786 BUILTIN(ReflectGet) {
2787   HandleScope scope(isolate);
2788   Handle<Object> target = args.atOrUndefined(isolate, 1);
2789   Handle<Object> key = args.atOrUndefined(isolate, 2);
2790   Handle<Object> receiver = args.length() > 3 ? args.at<Object>(3) : target;
2791 
2792   if (!target->IsJSReceiver()) {
2793     THROW_NEW_ERROR_RETURN_FAILURE(
2794         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2795                               isolate->factory()->NewStringFromAsciiChecked(
2796                                   "Reflect.get")));
2797   }
2798 
2799   Handle<Name> name;
2800   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
2801                                      Object::ToName(isolate, key));
2802 
2803   RETURN_RESULT_OR_FAILURE(
2804       isolate, Object::GetPropertyOrElement(receiver, name,
2805                                             Handle<JSReceiver>::cast(target)));
2806 }
2807 
2808 
2809 // ES6 section 26.1.7 Reflect.getOwnPropertyDescriptor
BUILTIN(ReflectGetOwnPropertyDescriptor)2810 BUILTIN(ReflectGetOwnPropertyDescriptor) {
2811   HandleScope scope(isolate);
2812   DCHECK_EQ(3, args.length());
2813   Handle<Object> target = args.at<Object>(1);
2814   Handle<Object> key = args.at<Object>(2);
2815 
2816   if (!target->IsJSReceiver()) {
2817     THROW_NEW_ERROR_RETURN_FAILURE(
2818         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2819                               isolate->factory()->NewStringFromAsciiChecked(
2820                                   "Reflect.getOwnPropertyDescriptor")));
2821   }
2822 
2823   Handle<Name> name;
2824   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
2825                                      Object::ToName(isolate, key));
2826 
2827   PropertyDescriptor desc;
2828   Maybe<bool> found = JSReceiver::GetOwnPropertyDescriptor(
2829       isolate, Handle<JSReceiver>::cast(target), name, &desc);
2830   MAYBE_RETURN(found, isolate->heap()->exception());
2831   if (!found.FromJust()) return isolate->heap()->undefined_value();
2832   return *desc.ToObject(isolate);
2833 }
2834 
2835 
2836 // ES6 section 26.1.8 Reflect.getPrototypeOf
BUILTIN(ReflectGetPrototypeOf)2837 BUILTIN(ReflectGetPrototypeOf) {
2838   HandleScope scope(isolate);
2839   DCHECK_EQ(2, args.length());
2840   Handle<Object> target = args.at<Object>(1);
2841 
2842   if (!target->IsJSReceiver()) {
2843     THROW_NEW_ERROR_RETURN_FAILURE(
2844         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2845                               isolate->factory()->NewStringFromAsciiChecked(
2846                                   "Reflect.getPrototypeOf")));
2847   }
2848   Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(target);
2849   RETURN_RESULT_OR_FAILURE(isolate,
2850                            JSReceiver::GetPrototype(isolate, receiver));
2851 }
2852 
2853 
2854 // ES6 section 26.1.9 Reflect.has
BUILTIN(ReflectHas)2855 BUILTIN(ReflectHas) {
2856   HandleScope scope(isolate);
2857   DCHECK_EQ(3, args.length());
2858   Handle<Object> target = args.at<Object>(1);
2859   Handle<Object> key = args.at<Object>(2);
2860 
2861   if (!target->IsJSReceiver()) {
2862     THROW_NEW_ERROR_RETURN_FAILURE(
2863         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2864                               isolate->factory()->NewStringFromAsciiChecked(
2865                                   "Reflect.has")));
2866   }
2867 
2868   Handle<Name> name;
2869   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
2870                                      Object::ToName(isolate, key));
2871 
2872   Maybe<bool> result =
2873       JSReceiver::HasProperty(Handle<JSReceiver>::cast(target), name);
2874   return result.IsJust() ? *isolate->factory()->ToBoolean(result.FromJust())
2875                          : isolate->heap()->exception();
2876 }
2877 
2878 
2879 // ES6 section 26.1.10 Reflect.isExtensible
BUILTIN(ReflectIsExtensible)2880 BUILTIN(ReflectIsExtensible) {
2881   HandleScope scope(isolate);
2882   DCHECK_EQ(2, args.length());
2883   Handle<Object> target = args.at<Object>(1);
2884 
2885   if (!target->IsJSReceiver()) {
2886     THROW_NEW_ERROR_RETURN_FAILURE(
2887         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2888                               isolate->factory()->NewStringFromAsciiChecked(
2889                                   "Reflect.isExtensible")));
2890   }
2891 
2892   Maybe<bool> result =
2893       JSReceiver::IsExtensible(Handle<JSReceiver>::cast(target));
2894   MAYBE_RETURN(result, isolate->heap()->exception());
2895   return *isolate->factory()->ToBoolean(result.FromJust());
2896 }
2897 
2898 
2899 // ES6 section 26.1.11 Reflect.ownKeys
BUILTIN(ReflectOwnKeys)2900 BUILTIN(ReflectOwnKeys) {
2901   HandleScope scope(isolate);
2902   DCHECK_EQ(2, args.length());
2903   Handle<Object> target = args.at<Object>(1);
2904 
2905   if (!target->IsJSReceiver()) {
2906     THROW_NEW_ERROR_RETURN_FAILURE(
2907         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2908                               isolate->factory()->NewStringFromAsciiChecked(
2909                                   "Reflect.ownKeys")));
2910   }
2911 
2912   Handle<FixedArray> keys;
2913   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2914       isolate, keys,
2915       KeyAccumulator::GetKeys(Handle<JSReceiver>::cast(target),
2916                               KeyCollectionMode::kOwnOnly, ALL_PROPERTIES,
2917                               GetKeysConversion::kConvertToString));
2918   return *isolate->factory()->NewJSArrayWithElements(keys);
2919 }
2920 
2921 
2922 // ES6 section 26.1.12 Reflect.preventExtensions
BUILTIN(ReflectPreventExtensions)2923 BUILTIN(ReflectPreventExtensions) {
2924   HandleScope scope(isolate);
2925   DCHECK_EQ(2, args.length());
2926   Handle<Object> target = args.at<Object>(1);
2927 
2928   if (!target->IsJSReceiver()) {
2929     THROW_NEW_ERROR_RETURN_FAILURE(
2930         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2931                               isolate->factory()->NewStringFromAsciiChecked(
2932                                   "Reflect.preventExtensions")));
2933   }
2934 
2935   Maybe<bool> result = JSReceiver::PreventExtensions(
2936       Handle<JSReceiver>::cast(target), Object::DONT_THROW);
2937   MAYBE_RETURN(result, isolate->heap()->exception());
2938   return *isolate->factory()->ToBoolean(result.FromJust());
2939 }
2940 
2941 
2942 // ES6 section 26.1.13 Reflect.set
BUILTIN(ReflectSet)2943 BUILTIN(ReflectSet) {
2944   HandleScope scope(isolate);
2945   Handle<Object> target = args.atOrUndefined(isolate, 1);
2946   Handle<Object> key = args.atOrUndefined(isolate, 2);
2947   Handle<Object> value = args.atOrUndefined(isolate, 3);
2948   Handle<Object> receiver = args.length() > 4 ? args.at<Object>(4) : target;
2949 
2950   if (!target->IsJSReceiver()) {
2951     THROW_NEW_ERROR_RETURN_FAILURE(
2952         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2953                               isolate->factory()->NewStringFromAsciiChecked(
2954                                   "Reflect.set")));
2955   }
2956 
2957   Handle<Name> name;
2958   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
2959                                      Object::ToName(isolate, key));
2960 
2961   LookupIterator it = LookupIterator::PropertyOrElement(
2962       isolate, receiver, name, Handle<JSReceiver>::cast(target));
2963   Maybe<bool> result = Object::SetSuperProperty(
2964       &it, value, SLOPPY, Object::MAY_BE_STORE_FROM_KEYED);
2965   MAYBE_RETURN(result, isolate->heap()->exception());
2966   return *isolate->factory()->ToBoolean(result.FromJust());
2967 }
2968 
2969 
2970 // ES6 section 26.1.14 Reflect.setPrototypeOf
BUILTIN(ReflectSetPrototypeOf)2971 BUILTIN(ReflectSetPrototypeOf) {
2972   HandleScope scope(isolate);
2973   DCHECK_EQ(3, args.length());
2974   Handle<Object> target = args.at<Object>(1);
2975   Handle<Object> proto = args.at<Object>(2);
2976 
2977   if (!target->IsJSReceiver()) {
2978     THROW_NEW_ERROR_RETURN_FAILURE(
2979         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2980                               isolate->factory()->NewStringFromAsciiChecked(
2981                                   "Reflect.setPrototypeOf")));
2982   }
2983 
2984   if (!proto->IsJSReceiver() && !proto->IsNull(isolate)) {
2985     THROW_NEW_ERROR_RETURN_FAILURE(
2986         isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, proto));
2987   }
2988 
2989   Maybe<bool> result = JSReceiver::SetPrototype(
2990       Handle<JSReceiver>::cast(target), proto, true, Object::DONT_THROW);
2991   MAYBE_RETURN(result, isolate->heap()->exception());
2992   return *isolate->factory()->ToBoolean(result.FromJust());
2993 }
2994 
2995 
2996 // -----------------------------------------------------------------------------
2997 // ES6 section 19.3 Boolean Objects
2998 
2999 
3000 // ES6 section 19.3.1.1 Boolean ( value ) for the [[Call]] case.
BUILTIN(BooleanConstructor)3001 BUILTIN(BooleanConstructor) {
3002   HandleScope scope(isolate);
3003   Handle<Object> value = args.atOrUndefined(isolate, 1);
3004   return isolate->heap()->ToBoolean(value->BooleanValue());
3005 }
3006 
3007 
3008 // ES6 section 19.3.1.1 Boolean ( value ) for the [[Construct]] case.
BUILTIN(BooleanConstructor_ConstructStub)3009 BUILTIN(BooleanConstructor_ConstructStub) {
3010   HandleScope scope(isolate);
3011   Handle<Object> value = args.atOrUndefined(isolate, 1);
3012   Handle<JSFunction> target = args.target<JSFunction>();
3013   Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
3014   DCHECK(*target == target->native_context()->boolean_function());
3015   Handle<JSObject> result;
3016   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
3017                                      JSObject::New(target, new_target));
3018   Handle<JSValue>::cast(result)->set_value(
3019       isolate->heap()->ToBoolean(value->BooleanValue()));
3020   return *result;
3021 }
3022 
3023 
3024 // ES6 section 19.3.3.2 Boolean.prototype.toString ( )
BUILTIN(BooleanPrototypeToString)3025 BUILTIN(BooleanPrototypeToString) {
3026   HandleScope scope(isolate);
3027   Handle<Object> receiver = args.receiver();
3028   if (receiver->IsJSValue()) {
3029     receiver = handle(Handle<JSValue>::cast(receiver)->value(), isolate);
3030   }
3031   if (!receiver->IsBoolean()) {
3032     THROW_NEW_ERROR_RETURN_FAILURE(
3033         isolate, NewTypeError(MessageTemplate::kNotGeneric,
3034                               isolate->factory()->NewStringFromAsciiChecked(
3035                                   "Boolean.prototype.toString")));
3036   }
3037   return Handle<Oddball>::cast(receiver)->to_string();
3038 }
3039 
3040 
3041 // ES6 section 19.3.3.3 Boolean.prototype.valueOf ( )
BUILTIN(BooleanPrototypeValueOf)3042 BUILTIN(BooleanPrototypeValueOf) {
3043   HandleScope scope(isolate);
3044   Handle<Object> receiver = args.receiver();
3045   if (receiver->IsJSValue()) {
3046     receiver = handle(Handle<JSValue>::cast(receiver)->value(), isolate);
3047   }
3048   if (!receiver->IsBoolean()) {
3049     THROW_NEW_ERROR_RETURN_FAILURE(
3050         isolate, NewTypeError(MessageTemplate::kNotGeneric,
3051                               isolate->factory()->NewStringFromAsciiChecked(
3052                                   "Boolean.prototype.valueOf")));
3053   }
3054   return *receiver;
3055 }
3056 
3057 
3058 // -----------------------------------------------------------------------------
3059 // ES6 section 24.2 DataView Objects
3060 
3061 
3062 // ES6 section 24.2.2 The DataView Constructor for the [[Call]] case.
BUILTIN(DataViewConstructor)3063 BUILTIN(DataViewConstructor) {
3064   HandleScope scope(isolate);
3065   THROW_NEW_ERROR_RETURN_FAILURE(
3066       isolate,
3067       NewTypeError(MessageTemplate::kConstructorNotFunction,
3068                    isolate->factory()->NewStringFromAsciiChecked("DataView")));
3069 }
3070 
3071 
3072 // ES6 section 24.2.2 The DataView Constructor for the [[Construct]] case.
BUILTIN(DataViewConstructor_ConstructStub)3073 BUILTIN(DataViewConstructor_ConstructStub) {
3074   HandleScope scope(isolate);
3075   Handle<JSFunction> target = args.target<JSFunction>();
3076   Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
3077   Handle<Object> buffer = args.atOrUndefined(isolate, 1);
3078   Handle<Object> byte_offset = args.atOrUndefined(isolate, 2);
3079   Handle<Object> byte_length = args.atOrUndefined(isolate, 3);
3080 
3081   // 2. If Type(buffer) is not Object, throw a TypeError exception.
3082   // 3. If buffer does not have an [[ArrayBufferData]] internal slot, throw a
3083   //    TypeError exception.
3084   if (!buffer->IsJSArrayBuffer()) {
3085     THROW_NEW_ERROR_RETURN_FAILURE(
3086         isolate, NewTypeError(MessageTemplate::kDataViewNotArrayBuffer));
3087   }
3088   Handle<JSArrayBuffer> array_buffer = Handle<JSArrayBuffer>::cast(buffer);
3089 
3090   // 4. Let numberOffset be ? ToNumber(byteOffset).
3091   Handle<Object> number_offset;
3092   if (byte_offset->IsUndefined(isolate)) {
3093     // We intentionally violate the specification at this point to allow
3094     // for new DataView(buffer) invocations to be equivalent to the full
3095     // new DataView(buffer, 0) invocation.
3096     number_offset = handle(Smi::FromInt(0), isolate);
3097   } else {
3098     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, number_offset,
3099                                        Object::ToNumber(byte_offset));
3100   }
3101 
3102   // 5. Let offset be ToInteger(numberOffset).
3103   Handle<Object> offset;
3104   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, offset,
3105                                      Object::ToInteger(isolate, number_offset));
3106 
3107   // 6. If numberOffset ≠ offset or offset < 0, throw a RangeError exception.
3108   if (number_offset->Number() != offset->Number() || offset->Number() < 0.0) {
3109     THROW_NEW_ERROR_RETURN_FAILURE(
3110         isolate, NewRangeError(MessageTemplate::kInvalidDataViewOffset));
3111   }
3112 
3113   // 7. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
3114   // We currently violate the specification at this point.
3115 
3116   // 8. Let bufferByteLength be the value of buffer's [[ArrayBufferByteLength]]
3117   // internal slot.
3118   double const buffer_byte_length = array_buffer->byte_length()->Number();
3119 
3120   // 9. If offset > bufferByteLength, throw a RangeError exception
3121   if (offset->Number() > buffer_byte_length) {
3122     THROW_NEW_ERROR_RETURN_FAILURE(
3123         isolate, NewRangeError(MessageTemplate::kInvalidDataViewOffset));
3124   }
3125 
3126   Handle<Object> view_byte_length;
3127   if (byte_length->IsUndefined(isolate)) {
3128     // 10. If byteLength is undefined, then
3129     //       a. Let viewByteLength be bufferByteLength - offset.
3130     view_byte_length =
3131         isolate->factory()->NewNumber(buffer_byte_length - offset->Number());
3132   } else {
3133     // 11. Else,
3134     //       a. Let viewByteLength be ? ToLength(byteLength).
3135     //       b. If offset+viewByteLength > bufferByteLength, throw a RangeError
3136     //          exception
3137     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3138         isolate, view_byte_length, Object::ToLength(isolate, byte_length));
3139     if (offset->Number() + view_byte_length->Number() > buffer_byte_length) {
3140       THROW_NEW_ERROR_RETURN_FAILURE(
3141           isolate, NewRangeError(MessageTemplate::kInvalidDataViewLength));
3142     }
3143   }
3144 
3145   // 12. Let O be ? OrdinaryCreateFromConstructor(NewTarget,
3146   //     "%DataViewPrototype%", «[[DataView]], [[ViewedArrayBuffer]],
3147   //     [[ByteLength]], [[ByteOffset]]»).
3148   // 13. Set O's [[DataView]] internal slot to true.
3149   Handle<JSObject> result;
3150   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
3151                                      JSObject::New(target, new_target));
3152   for (int i = 0; i < ArrayBufferView::kInternalFieldCount; ++i) {
3153     Handle<JSDataView>::cast(result)->SetInternalField(i, Smi::FromInt(0));
3154   }
3155 
3156   // 14. Set O's [[ViewedArrayBuffer]] internal slot to buffer.
3157   Handle<JSDataView>::cast(result)->set_buffer(*array_buffer);
3158 
3159   // 15. Set O's [[ByteLength]] internal slot to viewByteLength.
3160   Handle<JSDataView>::cast(result)->set_byte_length(*view_byte_length);
3161 
3162   // 16. Set O's [[ByteOffset]] internal slot to offset.
3163   Handle<JSDataView>::cast(result)->set_byte_offset(*offset);
3164 
3165   // 17. Return O.
3166   return *result;
3167 }
3168 
3169 // ES6 section 24.2.4.1 get DataView.prototype.buffer
BUILTIN(DataViewPrototypeGetBuffer)3170 BUILTIN(DataViewPrototypeGetBuffer) {
3171   HandleScope scope(isolate);
3172   CHECK_RECEIVER(JSDataView, data_view, "get DataView.prototype.buffer");
3173   return data_view->buffer();
3174 }
3175 
3176 // ES6 section 24.2.4.2 get DataView.prototype.byteLength
BUILTIN(DataViewPrototypeGetByteLength)3177 BUILTIN(DataViewPrototypeGetByteLength) {
3178   HandleScope scope(isolate);
3179   CHECK_RECEIVER(JSDataView, data_view, "get DataView.prototype.byteLength");
3180   // TODO(bmeurer): According to the ES6 spec, we should throw a TypeError
3181   // here if the JSArrayBuffer of the {data_view} was neutered.
3182   return data_view->byte_length();
3183 }
3184 
3185 // ES6 section 24.2.4.3 get DataView.prototype.byteOffset
BUILTIN(DataViewPrototypeGetByteOffset)3186 BUILTIN(DataViewPrototypeGetByteOffset) {
3187   HandleScope scope(isolate);
3188   CHECK_RECEIVER(JSDataView, data_view, "get DataView.prototype.byteOffset");
3189   // TODO(bmeurer): According to the ES6 spec, we should throw a TypeError
3190   // here if the JSArrayBuffer of the {data_view} was neutered.
3191   return data_view->byte_offset();
3192 }
3193 
3194 // -----------------------------------------------------------------------------
3195 // ES6 section 22.2 TypedArray Objects
3196 
3197 // ES6 section 22.2.3.1 get %TypedArray%.prototype.buffer
BUILTIN(TypedArrayPrototypeBuffer)3198 BUILTIN(TypedArrayPrototypeBuffer) {
3199   HandleScope scope(isolate);
3200   CHECK_RECEIVER(JSTypedArray, typed_array, "get TypedArray.prototype.buffer");
3201   return *typed_array->GetBuffer();
3202 }
3203 
3204 namespace {
3205 
Generate_TypedArrayProtoypeGetter(CodeStubAssembler * assembler,const char * method_name,int object_offset)3206 void Generate_TypedArrayProtoypeGetter(CodeStubAssembler* assembler,
3207                                        const char* method_name,
3208                                        int object_offset) {
3209   typedef CodeStubAssembler::Label Label;
3210   typedef compiler::Node Node;
3211 
3212   Node* receiver = assembler->Parameter(0);
3213   Node* context = assembler->Parameter(3);
3214 
3215   // Check if the {receiver} is actually a JSTypedArray.
3216   Label if_receiverisincompatible(assembler, Label::kDeferred);
3217   assembler->GotoIf(assembler->WordIsSmi(receiver), &if_receiverisincompatible);
3218   Node* receiver_instance_type = assembler->LoadInstanceType(receiver);
3219   assembler->GotoUnless(
3220       assembler->Word32Equal(receiver_instance_type,
3221                              assembler->Int32Constant(JS_TYPED_ARRAY_TYPE)),
3222       &if_receiverisincompatible);
3223 
3224   // Check if the {receiver}'s JSArrayBuffer was neutered.
3225   Node* receiver_buffer =
3226       assembler->LoadObjectField(receiver, JSTypedArray::kBufferOffset);
3227   Node* receiver_buffer_bit_field = assembler->LoadObjectField(
3228       receiver_buffer, JSArrayBuffer::kBitFieldOffset, MachineType::Uint32());
3229   Label if_receiverisneutered(assembler, Label::kDeferred);
3230   assembler->GotoUnless(
3231       assembler->Word32Equal(
3232           assembler->Word32And(
3233               receiver_buffer_bit_field,
3234               assembler->Int32Constant(JSArrayBuffer::WasNeutered::kMask)),
3235           assembler->Int32Constant(0)),
3236       &if_receiverisneutered);
3237   assembler->Return(assembler->LoadObjectField(receiver, object_offset));
3238 
3239   assembler->Bind(&if_receiverisneutered);
3240   {
3241     // The {receiver}s buffer was neutered, default to zero.
3242     assembler->Return(assembler->SmiConstant(0));
3243   }
3244 
3245   assembler->Bind(&if_receiverisincompatible);
3246   {
3247     // The {receiver} is not a valid JSGeneratorObject.
3248     Node* result = assembler->CallRuntime(
3249         Runtime::kThrowIncompatibleMethodReceiver, context,
3250         assembler->HeapConstant(assembler->factory()->NewStringFromAsciiChecked(
3251             method_name, TENURED)),
3252         receiver);
3253     assembler->Return(result);  // Never reached.
3254   }
3255 }
3256 
3257 }  // namespace
3258 
3259 // ES6 section 22.2.3.2 get %TypedArray%.prototype.byteLength
Generate_TypedArrayPrototypeByteLength(CodeStubAssembler * assembler)3260 void Builtins::Generate_TypedArrayPrototypeByteLength(
3261     CodeStubAssembler* assembler) {
3262   Generate_TypedArrayProtoypeGetter(assembler,
3263                                     "get TypedArray.prototype.byteLength",
3264                                     JSTypedArray::kByteLengthOffset);
3265 }
3266 
3267 // ES6 section 22.2.3.3 get %TypedArray%.prototype.byteOffset
Generate_TypedArrayPrototypeByteOffset(CodeStubAssembler * assembler)3268 void Builtins::Generate_TypedArrayPrototypeByteOffset(
3269     CodeStubAssembler* assembler) {
3270   Generate_TypedArrayProtoypeGetter(assembler,
3271                                     "get TypedArray.prototype.byteOffset",
3272                                     JSTypedArray::kByteOffsetOffset);
3273 }
3274 
3275 // ES6 section 22.2.3.18 get %TypedArray%.prototype.length
Generate_TypedArrayPrototypeLength(CodeStubAssembler * assembler)3276 void Builtins::Generate_TypedArrayPrototypeLength(
3277     CodeStubAssembler* assembler) {
3278   Generate_TypedArrayProtoypeGetter(assembler,
3279                                     "get TypedArray.prototype.length",
3280                                     JSTypedArray::kLengthOffset);
3281 }
3282 
3283 // -----------------------------------------------------------------------------
3284 // ES6 section 20.3 Date Objects
3285 
3286 
3287 namespace {
3288 
3289 // ES6 section 20.3.1.1 Time Values and Time Range
3290 const double kMinYear = -1000000.0;
3291 const double kMaxYear = -kMinYear;
3292 const double kMinMonth = -10000000.0;
3293 const double kMaxMonth = -kMinMonth;
3294 
3295 
3296 // 20.3.1.2 Day Number and Time within Day
3297 const double kMsPerDay = 86400000.0;
3298 
3299 
3300 // ES6 section 20.3.1.11 Hours, Minutes, Second, and Milliseconds
3301 const double kMsPerSecond = 1000.0;
3302 const double kMsPerMinute = 60000.0;
3303 const double kMsPerHour = 3600000.0;
3304 
3305 
3306 // ES6 section 20.3.1.14 MakeDate (day, time)
MakeDate(double day,double time)3307 double MakeDate(double day, double time) {
3308   if (std::isfinite(day) && std::isfinite(time)) {
3309     return time + day * kMsPerDay;
3310   }
3311   return std::numeric_limits<double>::quiet_NaN();
3312 }
3313 
3314 
3315 // ES6 section 20.3.1.13 MakeDay (year, month, date)
MakeDay(double year,double month,double date)3316 double MakeDay(double year, double month, double date) {
3317   if ((kMinYear <= year && year <= kMaxYear) &&
3318       (kMinMonth <= month && month <= kMaxMonth) && std::isfinite(date)) {
3319     int y = FastD2I(year);
3320     int m = FastD2I(month);
3321     y += m / 12;
3322     m %= 12;
3323     if (m < 0) {
3324       m += 12;
3325       y -= 1;
3326     }
3327     DCHECK_LE(0, m);
3328     DCHECK_LT(m, 12);
3329 
3330     // kYearDelta is an arbitrary number such that:
3331     // a) kYearDelta = -1 (mod 400)
3332     // b) year + kYearDelta > 0 for years in the range defined by
3333     //    ECMA 262 - 15.9.1.1, i.e. upto 100,000,000 days on either side of
3334     //    Jan 1 1970. This is required so that we don't run into integer
3335     //    division of negative numbers.
3336     // c) there shouldn't be an overflow for 32-bit integers in the following
3337     //    operations.
3338     static const int kYearDelta = 399999;
3339     static const int kBaseDay =
3340         365 * (1970 + kYearDelta) + (1970 + kYearDelta) / 4 -
3341         (1970 + kYearDelta) / 100 + (1970 + kYearDelta) / 400;
3342     int day_from_year = 365 * (y + kYearDelta) + (y + kYearDelta) / 4 -
3343                         (y + kYearDelta) / 100 + (y + kYearDelta) / 400 -
3344                         kBaseDay;
3345     if ((y % 4 != 0) || (y % 100 == 0 && y % 400 != 0)) {
3346       static const int kDayFromMonth[] = {0,   31,  59,  90,  120, 151,
3347                                           181, 212, 243, 273, 304, 334};
3348       day_from_year += kDayFromMonth[m];
3349     } else {
3350       static const int kDayFromMonth[] = {0,   31,  60,  91,  121, 152,
3351                                           182, 213, 244, 274, 305, 335};
3352       day_from_year += kDayFromMonth[m];
3353     }
3354     return static_cast<double>(day_from_year - 1) + date;
3355   }
3356   return std::numeric_limits<double>::quiet_NaN();
3357 }
3358 
3359 
3360 // ES6 section 20.3.1.12 MakeTime (hour, min, sec, ms)
MakeTime(double hour,double min,double sec,double ms)3361 double MakeTime(double hour, double min, double sec, double ms) {
3362   if (std::isfinite(hour) && std::isfinite(min) && std::isfinite(sec) &&
3363       std::isfinite(ms)) {
3364     double const h = DoubleToInteger(hour);
3365     double const m = DoubleToInteger(min);
3366     double const s = DoubleToInteger(sec);
3367     double const milli = DoubleToInteger(ms);
3368     return h * kMsPerHour + m * kMsPerMinute + s * kMsPerSecond + milli;
3369   }
3370   return std::numeric_limits<double>::quiet_NaN();
3371 }
3372 
3373 
3374 // ES6 section 20.3.1.15 TimeClip (time)
TimeClip(double time)3375 double TimeClip(double time) {
3376   if (-DateCache::kMaxTimeInMs <= time && time <= DateCache::kMaxTimeInMs) {
3377     return DoubleToInteger(time) + 0.0;
3378   }
3379   return std::numeric_limits<double>::quiet_NaN();
3380 }
3381 
3382 
3383 const char* kShortWeekDays[] = {"Sun", "Mon", "Tue", "Wed",
3384                                 "Thu", "Fri", "Sat"};
3385 const char* kShortMonths[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
3386                               "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
3387 
3388 
3389 // ES6 section 20.3.1.16 Date Time String Format
ParseDateTimeString(Handle<String> str)3390 double ParseDateTimeString(Handle<String> str) {
3391   Isolate* const isolate = str->GetIsolate();
3392   str = String::Flatten(str);
3393   // TODO(bmeurer): Change DateParser to not use the FixedArray.
3394   Handle<FixedArray> tmp =
3395       isolate->factory()->NewFixedArray(DateParser::OUTPUT_SIZE);
3396   DisallowHeapAllocation no_gc;
3397   String::FlatContent str_content = str->GetFlatContent();
3398   bool result;
3399   if (str_content.IsOneByte()) {
3400     result = DateParser::Parse(isolate, str_content.ToOneByteVector(), *tmp);
3401   } else {
3402     result = DateParser::Parse(isolate, str_content.ToUC16Vector(), *tmp);
3403   }
3404   if (!result) return std::numeric_limits<double>::quiet_NaN();
3405   double const day = MakeDay(tmp->get(0)->Number(), tmp->get(1)->Number(),
3406                              tmp->get(2)->Number());
3407   double const time = MakeTime(tmp->get(3)->Number(), tmp->get(4)->Number(),
3408                                tmp->get(5)->Number(), tmp->get(6)->Number());
3409   double date = MakeDate(day, time);
3410   if (tmp->get(7)->IsNull(isolate)) {
3411     if (!std::isnan(date)) {
3412       date = isolate->date_cache()->ToUTC(static_cast<int64_t>(date));
3413     }
3414   } else {
3415     date -= tmp->get(7)->Number() * 1000.0;
3416   }
3417   return date;
3418 }
3419 
3420 
3421 enum ToDateStringMode { kDateOnly, kTimeOnly, kDateAndTime };
3422 
3423 
3424 // ES6 section 20.3.4.41.1 ToDateString(tv)
ToDateString(double time_val,Vector<char> str,DateCache * date_cache,ToDateStringMode mode=kDateAndTime)3425 void ToDateString(double time_val, Vector<char> str, DateCache* date_cache,
3426                   ToDateStringMode mode = kDateAndTime) {
3427   if (std::isnan(time_val)) {
3428     SNPrintF(str, "Invalid Date");
3429     return;
3430   }
3431   int64_t time_ms = static_cast<int64_t>(time_val);
3432   int64_t local_time_ms = date_cache->ToLocal(time_ms);
3433   int year, month, day, weekday, hour, min, sec, ms;
3434   date_cache->BreakDownTime(local_time_ms, &year, &month, &day, &weekday, &hour,
3435                             &min, &sec, &ms);
3436   int timezone_offset = -date_cache->TimezoneOffset(time_ms);
3437   int timezone_hour = std::abs(timezone_offset) / 60;
3438   int timezone_min = std::abs(timezone_offset) % 60;
3439   const char* local_timezone = date_cache->LocalTimezone(time_ms);
3440   switch (mode) {
3441     case kDateOnly:
3442       SNPrintF(str, "%s %s %02d %4d", kShortWeekDays[weekday],
3443                kShortMonths[month], day, year);
3444       return;
3445     case kTimeOnly:
3446       SNPrintF(str, "%02d:%02d:%02d GMT%c%02d%02d (%s)", hour, min, sec,
3447                (timezone_offset < 0) ? '-' : '+', timezone_hour, timezone_min,
3448                local_timezone);
3449       return;
3450     case kDateAndTime:
3451       SNPrintF(str, "%s %s %02d %4d %02d:%02d:%02d GMT%c%02d%02d (%s)",
3452                kShortWeekDays[weekday], kShortMonths[month], day, year, hour,
3453                min, sec, (timezone_offset < 0) ? '-' : '+', timezone_hour,
3454                timezone_min, local_timezone);
3455       return;
3456   }
3457   UNREACHABLE();
3458 }
3459 
3460 
SetLocalDateValue(Handle<JSDate> date,double time_val)3461 Object* SetLocalDateValue(Handle<JSDate> date, double time_val) {
3462   if (time_val >= -DateCache::kMaxTimeBeforeUTCInMs &&
3463       time_val <= DateCache::kMaxTimeBeforeUTCInMs) {
3464     Isolate* const isolate = date->GetIsolate();
3465     time_val = isolate->date_cache()->ToUTC(static_cast<int64_t>(time_val));
3466   } else {
3467     time_val = std::numeric_limits<double>::quiet_NaN();
3468   }
3469   return *JSDate::SetValue(date, TimeClip(time_val));
3470 }
3471 
3472 }  // namespace
3473 
3474 
3475 // ES6 section 20.3.2 The Date Constructor for the [[Call]] case.
BUILTIN(DateConstructor)3476 BUILTIN(DateConstructor) {
3477   HandleScope scope(isolate);
3478   double const time_val = JSDate::CurrentTimeValue(isolate);
3479   char buffer[128];
3480   ToDateString(time_val, ArrayVector(buffer), isolate->date_cache());
3481   RETURN_RESULT_OR_FAILURE(
3482       isolate, isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
3483 }
3484 
3485 
3486 // ES6 section 20.3.2 The Date Constructor for the [[Construct]] case.
BUILTIN(DateConstructor_ConstructStub)3487 BUILTIN(DateConstructor_ConstructStub) {
3488   HandleScope scope(isolate);
3489   int const argc = args.length() - 1;
3490   Handle<JSFunction> target = args.target<JSFunction>();
3491   Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
3492   double time_val;
3493   if (argc == 0) {
3494     time_val = JSDate::CurrentTimeValue(isolate);
3495   } else if (argc == 1) {
3496     Handle<Object> value = args.at<Object>(1);
3497     if (value->IsJSDate()) {
3498       time_val = Handle<JSDate>::cast(value)->value()->Number();
3499     } else {
3500       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
3501                                          Object::ToPrimitive(value));
3502       if (value->IsString()) {
3503         time_val = ParseDateTimeString(Handle<String>::cast(value));
3504       } else {
3505         ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
3506                                            Object::ToNumber(value));
3507         time_val = value->Number();
3508       }
3509     }
3510   } else {
3511     Handle<Object> year_object;
3512     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year_object,
3513                                        Object::ToNumber(args.at<Object>(1)));
3514     Handle<Object> month_object;
3515     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month_object,
3516                                        Object::ToNumber(args.at<Object>(2)));
3517     double year = year_object->Number();
3518     double month = month_object->Number();
3519     double date = 1.0, hours = 0.0, minutes = 0.0, seconds = 0.0, ms = 0.0;
3520     if (argc >= 3) {
3521       Handle<Object> date_object;
3522       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date_object,
3523                                          Object::ToNumber(args.at<Object>(3)));
3524       date = date_object->Number();
3525       if (argc >= 4) {
3526         Handle<Object> hours_object;
3527         ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3528             isolate, hours_object, Object::ToNumber(args.at<Object>(4)));
3529         hours = hours_object->Number();
3530         if (argc >= 5) {
3531           Handle<Object> minutes_object;
3532           ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3533               isolate, minutes_object, Object::ToNumber(args.at<Object>(5)));
3534           minutes = minutes_object->Number();
3535           if (argc >= 6) {
3536             Handle<Object> seconds_object;
3537             ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3538                 isolate, seconds_object, Object::ToNumber(args.at<Object>(6)));
3539             seconds = seconds_object->Number();
3540             if (argc >= 7) {
3541               Handle<Object> ms_object;
3542               ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3543                   isolate, ms_object, Object::ToNumber(args.at<Object>(7)));
3544               ms = ms_object->Number();
3545             }
3546           }
3547         }
3548       }
3549     }
3550     if (!std::isnan(year)) {
3551       double const y = DoubleToInteger(year);
3552       if (0.0 <= y && y <= 99) year = 1900 + y;
3553     }
3554     double const day = MakeDay(year, month, date);
3555     double const time = MakeTime(hours, minutes, seconds, ms);
3556     time_val = MakeDate(day, time);
3557     if (time_val >= -DateCache::kMaxTimeBeforeUTCInMs &&
3558         time_val <= DateCache::kMaxTimeBeforeUTCInMs) {
3559       time_val = isolate->date_cache()->ToUTC(static_cast<int64_t>(time_val));
3560     } else {
3561       time_val = std::numeric_limits<double>::quiet_NaN();
3562     }
3563   }
3564   RETURN_RESULT_OR_FAILURE(isolate, JSDate::New(target, new_target, time_val));
3565 }
3566 
3567 
3568 // ES6 section 20.3.3.1 Date.now ( )
BUILTIN(DateNow)3569 BUILTIN(DateNow) {
3570   HandleScope scope(isolate);
3571   return *isolate->factory()->NewNumber(JSDate::CurrentTimeValue(isolate));
3572 }
3573 
3574 
3575 // ES6 section 20.3.3.2 Date.parse ( string )
BUILTIN(DateParse)3576 BUILTIN(DateParse) {
3577   HandleScope scope(isolate);
3578   Handle<String> string;
3579   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3580       isolate, string,
3581       Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
3582   return *isolate->factory()->NewNumber(ParseDateTimeString(string));
3583 }
3584 
3585 
3586 // ES6 section 20.3.3.4 Date.UTC (year,month,date,hours,minutes,seconds,ms)
BUILTIN(DateUTC)3587 BUILTIN(DateUTC) {
3588   HandleScope scope(isolate);
3589   int const argc = args.length() - 1;
3590   double year = std::numeric_limits<double>::quiet_NaN();
3591   double month = std::numeric_limits<double>::quiet_NaN();
3592   double date = 1.0, hours = 0.0, minutes = 0.0, seconds = 0.0, ms = 0.0;
3593   if (argc >= 1) {
3594     Handle<Object> year_object;
3595     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year_object,
3596                                        Object::ToNumber(args.at<Object>(1)));
3597     year = year_object->Number();
3598     if (argc >= 2) {
3599       Handle<Object> month_object;
3600       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month_object,
3601                                          Object::ToNumber(args.at<Object>(2)));
3602       month = month_object->Number();
3603       if (argc >= 3) {
3604         Handle<Object> date_object;
3605         ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3606             isolate, date_object, Object::ToNumber(args.at<Object>(3)));
3607         date = date_object->Number();
3608         if (argc >= 4) {
3609           Handle<Object> hours_object;
3610           ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3611               isolate, hours_object, Object::ToNumber(args.at<Object>(4)));
3612           hours = hours_object->Number();
3613           if (argc >= 5) {
3614             Handle<Object> minutes_object;
3615             ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3616                 isolate, minutes_object, Object::ToNumber(args.at<Object>(5)));
3617             minutes = minutes_object->Number();
3618             if (argc >= 6) {
3619               Handle<Object> seconds_object;
3620               ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3621                   isolate, seconds_object,
3622                   Object::ToNumber(args.at<Object>(6)));
3623               seconds = seconds_object->Number();
3624               if (argc >= 7) {
3625                 Handle<Object> ms_object;
3626                 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3627                     isolate, ms_object, Object::ToNumber(args.at<Object>(7)));
3628                 ms = ms_object->Number();
3629               }
3630             }
3631           }
3632         }
3633       }
3634     }
3635   }
3636   if (!std::isnan(year)) {
3637     double const y = DoubleToInteger(year);
3638     if (0.0 <= y && y <= 99) year = 1900 + y;
3639   }
3640   double const day = MakeDay(year, month, date);
3641   double const time = MakeTime(hours, minutes, seconds, ms);
3642   return *isolate->factory()->NewNumber(TimeClip(MakeDate(day, time)));
3643 }
3644 
3645 
3646 // ES6 section 20.3.4.20 Date.prototype.setDate ( date )
BUILTIN(DatePrototypeSetDate)3647 BUILTIN(DatePrototypeSetDate) {
3648   HandleScope scope(isolate);
3649   CHECK_RECEIVER(JSDate, date, "Date.prototype.setDate");
3650   Handle<Object> value = args.atOrUndefined(isolate, 1);
3651   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(value));
3652   double time_val = date->value()->Number();
3653   if (!std::isnan(time_val)) {
3654     int64_t const time_ms = static_cast<int64_t>(time_val);
3655     int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
3656     int const days = isolate->date_cache()->DaysFromTime(local_time_ms);
3657     int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days);
3658     int year, month, day;
3659     isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
3660     time_val = MakeDate(MakeDay(year, month, value->Number()), time_within_day);
3661   }
3662   return SetLocalDateValue(date, time_val);
3663 }
3664 
3665 
3666 // ES6 section 20.3.4.21 Date.prototype.setFullYear (year, month, date)
BUILTIN(DatePrototypeSetFullYear)3667 BUILTIN(DatePrototypeSetFullYear) {
3668   HandleScope scope(isolate);
3669   CHECK_RECEIVER(JSDate, date, "Date.prototype.setFullYear");
3670   int const argc = args.length() - 1;
3671   Handle<Object> year = args.atOrUndefined(isolate, 1);
3672   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, Object::ToNumber(year));
3673   double y = year->Number(), m = 0.0, dt = 1.0;
3674   int time_within_day = 0;
3675   if (!std::isnan(date->value()->Number())) {
3676     int64_t const time_ms = static_cast<int64_t>(date->value()->Number());
3677     int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
3678     int const days = isolate->date_cache()->DaysFromTime(local_time_ms);
3679     time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days);
3680     int year, month, day;
3681     isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
3682     m = month;
3683     dt = day;
3684   }
3685   if (argc >= 2) {
3686     Handle<Object> month = args.at<Object>(2);
3687     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month));
3688     m = month->Number();
3689     if (argc >= 3) {
3690       Handle<Object> date = args.at<Object>(3);
3691       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date));
3692       dt = date->Number();
3693     }
3694   }
3695   double time_val = MakeDate(MakeDay(y, m, dt), time_within_day);
3696   return SetLocalDateValue(date, time_val);
3697 }
3698 
3699 
3700 // ES6 section 20.3.4.22 Date.prototype.setHours(hour, min, sec, ms)
BUILTIN(DatePrototypeSetHours)3701 BUILTIN(DatePrototypeSetHours) {
3702   HandleScope scope(isolate);
3703   CHECK_RECEIVER(JSDate, date, "Date.prototype.setHours");
3704   int const argc = args.length() - 1;
3705   Handle<Object> hour = args.atOrUndefined(isolate, 1);
3706   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, hour, Object::ToNumber(hour));
3707   double h = hour->Number();
3708   double time_val = date->value()->Number();
3709   if (!std::isnan(time_val)) {
3710     int64_t const time_ms = static_cast<int64_t>(time_val);
3711     int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
3712     int day = isolate->date_cache()->DaysFromTime(local_time_ms);
3713     int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day);
3714     double m = (time_within_day / (60 * 1000)) % 60;
3715     double s = (time_within_day / 1000) % 60;
3716     double milli = time_within_day % 1000;
3717     if (argc >= 2) {
3718       Handle<Object> min = args.at<Object>(2);
3719       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min));
3720       m = min->Number();
3721       if (argc >= 3) {
3722         Handle<Object> sec = args.at<Object>(3);
3723         ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
3724         s = sec->Number();
3725         if (argc >= 4) {
3726           Handle<Object> ms = args.at<Object>(4);
3727           ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3728           milli = ms->Number();
3729         }
3730       }
3731     }
3732     time_val = MakeDate(day, MakeTime(h, m, s, milli));
3733   }
3734   return SetLocalDateValue(date, time_val);
3735 }
3736 
3737 
3738 // ES6 section 20.3.4.23 Date.prototype.setMilliseconds(ms)
BUILTIN(DatePrototypeSetMilliseconds)3739 BUILTIN(DatePrototypeSetMilliseconds) {
3740   HandleScope scope(isolate);
3741   CHECK_RECEIVER(JSDate, date, "Date.prototype.setMilliseconds");
3742   Handle<Object> ms = args.atOrUndefined(isolate, 1);
3743   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3744   double time_val = date->value()->Number();
3745   if (!std::isnan(time_val)) {
3746     int64_t const time_ms = static_cast<int64_t>(time_val);
3747     int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
3748     int day = isolate->date_cache()->DaysFromTime(local_time_ms);
3749     int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day);
3750     int h = time_within_day / (60 * 60 * 1000);
3751     int m = (time_within_day / (60 * 1000)) % 60;
3752     int s = (time_within_day / 1000) % 60;
3753     time_val = MakeDate(day, MakeTime(h, m, s, ms->Number()));
3754   }
3755   return SetLocalDateValue(date, time_val);
3756 }
3757 
3758 
3759 // ES6 section 20.3.4.24 Date.prototype.setMinutes ( min, sec, ms )
BUILTIN(DatePrototypeSetMinutes)3760 BUILTIN(DatePrototypeSetMinutes) {
3761   HandleScope scope(isolate);
3762   CHECK_RECEIVER(JSDate, date, "Date.prototype.setMinutes");
3763   int const argc = args.length() - 1;
3764   Handle<Object> min = args.atOrUndefined(isolate, 1);
3765   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min));
3766   double time_val = date->value()->Number();
3767   if (!std::isnan(time_val)) {
3768     int64_t const time_ms = static_cast<int64_t>(time_val);
3769     int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
3770     int day = isolate->date_cache()->DaysFromTime(local_time_ms);
3771     int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day);
3772     int h = time_within_day / (60 * 60 * 1000);
3773     double m = min->Number();
3774     double s = (time_within_day / 1000) % 60;
3775     double milli = time_within_day % 1000;
3776     if (argc >= 2) {
3777       Handle<Object> sec = args.at<Object>(2);
3778       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
3779       s = sec->Number();
3780       if (argc >= 3) {
3781         Handle<Object> ms = args.at<Object>(3);
3782         ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3783         milli = ms->Number();
3784       }
3785     }
3786     time_val = MakeDate(day, MakeTime(h, m, s, milli));
3787   }
3788   return SetLocalDateValue(date, time_val);
3789 }
3790 
3791 
3792 // ES6 section 20.3.4.25 Date.prototype.setMonth ( month, date )
BUILTIN(DatePrototypeSetMonth)3793 BUILTIN(DatePrototypeSetMonth) {
3794   HandleScope scope(isolate);
3795   CHECK_RECEIVER(JSDate, date, "Date.prototype.setMonth");
3796   int const argc = args.length() - 1;
3797   Handle<Object> month = args.atOrUndefined(isolate, 1);
3798   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month));
3799   double time_val = date->value()->Number();
3800   if (!std::isnan(time_val)) {
3801     int64_t const time_ms = static_cast<int64_t>(time_val);
3802     int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
3803     int days = isolate->date_cache()->DaysFromTime(local_time_ms);
3804     int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days);
3805     int year, unused, day;
3806     isolate->date_cache()->YearMonthDayFromDays(days, &year, &unused, &day);
3807     double m = month->Number();
3808     double dt = day;
3809     if (argc >= 2) {
3810       Handle<Object> date = args.at<Object>(2);
3811       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date));
3812       dt = date->Number();
3813     }
3814     time_val = MakeDate(MakeDay(year, m, dt), time_within_day);
3815   }
3816   return SetLocalDateValue(date, time_val);
3817 }
3818 
3819 
3820 // ES6 section 20.3.4.26 Date.prototype.setSeconds ( sec, ms )
BUILTIN(DatePrototypeSetSeconds)3821 BUILTIN(DatePrototypeSetSeconds) {
3822   HandleScope scope(isolate);
3823   CHECK_RECEIVER(JSDate, date, "Date.prototype.setSeconds");
3824   int const argc = args.length() - 1;
3825   Handle<Object> sec = args.atOrUndefined(isolate, 1);
3826   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
3827   double time_val = date->value()->Number();
3828   if (!std::isnan(time_val)) {
3829     int64_t const time_ms = static_cast<int64_t>(time_val);
3830     int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
3831     int day = isolate->date_cache()->DaysFromTime(local_time_ms);
3832     int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day);
3833     int h = time_within_day / (60 * 60 * 1000);
3834     double m = (time_within_day / (60 * 1000)) % 60;
3835     double s = sec->Number();
3836     double milli = time_within_day % 1000;
3837     if (argc >= 2) {
3838       Handle<Object> ms = args.at<Object>(2);
3839       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3840       milli = ms->Number();
3841     }
3842     time_val = MakeDate(day, MakeTime(h, m, s, milli));
3843   }
3844   return SetLocalDateValue(date, time_val);
3845 }
3846 
3847 
3848 // ES6 section 20.3.4.27 Date.prototype.setTime ( time )
BUILTIN(DatePrototypeSetTime)3849 BUILTIN(DatePrototypeSetTime) {
3850   HandleScope scope(isolate);
3851   CHECK_RECEIVER(JSDate, date, "Date.prototype.setTime");
3852   Handle<Object> value = args.atOrUndefined(isolate, 1);
3853   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(value));
3854   return *JSDate::SetValue(date, TimeClip(value->Number()));
3855 }
3856 
3857 
3858 // ES6 section 20.3.4.28 Date.prototype.setUTCDate ( date )
BUILTIN(DatePrototypeSetUTCDate)3859 BUILTIN(DatePrototypeSetUTCDate) {
3860   HandleScope scope(isolate);
3861   CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCDate");
3862   Handle<Object> value = args.atOrUndefined(isolate, 1);
3863   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(value));
3864   if (std::isnan(date->value()->Number())) return date->value();
3865   int64_t const time_ms = static_cast<int64_t>(date->value()->Number());
3866   int const days = isolate->date_cache()->DaysFromTime(time_ms);
3867   int const time_within_day = isolate->date_cache()->TimeInDay(time_ms, days);
3868   int year, month, day;
3869   isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
3870   double const time_val =
3871       MakeDate(MakeDay(year, month, value->Number()), time_within_day);
3872   return *JSDate::SetValue(date, TimeClip(time_val));
3873 }
3874 
3875 
3876 // ES6 section 20.3.4.29 Date.prototype.setUTCFullYear (year, month, date)
BUILTIN(DatePrototypeSetUTCFullYear)3877 BUILTIN(DatePrototypeSetUTCFullYear) {
3878   HandleScope scope(isolate);
3879   CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCFullYear");
3880   int const argc = args.length() - 1;
3881   Handle<Object> year = args.atOrUndefined(isolate, 1);
3882   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, Object::ToNumber(year));
3883   double y = year->Number(), m = 0.0, dt = 1.0;
3884   int time_within_day = 0;
3885   if (!std::isnan(date->value()->Number())) {
3886     int64_t const time_ms = static_cast<int64_t>(date->value()->Number());
3887     int const days = isolate->date_cache()->DaysFromTime(time_ms);
3888     time_within_day = isolate->date_cache()->TimeInDay(time_ms, days);
3889     int year, month, day;
3890     isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
3891     m = month;
3892     dt = day;
3893   }
3894   if (argc >= 2) {
3895     Handle<Object> month = args.at<Object>(2);
3896     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month));
3897     m = month->Number();
3898     if (argc >= 3) {
3899       Handle<Object> date = args.at<Object>(3);
3900       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date));
3901       dt = date->Number();
3902     }
3903   }
3904   double const time_val = MakeDate(MakeDay(y, m, dt), time_within_day);
3905   return *JSDate::SetValue(date, TimeClip(time_val));
3906 }
3907 
3908 
3909 // ES6 section 20.3.4.30 Date.prototype.setUTCHours(hour, min, sec, ms)
BUILTIN(DatePrototypeSetUTCHours)3910 BUILTIN(DatePrototypeSetUTCHours) {
3911   HandleScope scope(isolate);
3912   CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCHours");
3913   int const argc = args.length() - 1;
3914   Handle<Object> hour = args.atOrUndefined(isolate, 1);
3915   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, hour, Object::ToNumber(hour));
3916   double h = hour->Number();
3917   double time_val = date->value()->Number();
3918   if (!std::isnan(time_val)) {
3919     int64_t const time_ms = static_cast<int64_t>(time_val);
3920     int day = isolate->date_cache()->DaysFromTime(time_ms);
3921     int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day);
3922     double m = (time_within_day / (60 * 1000)) % 60;
3923     double s = (time_within_day / 1000) % 60;
3924     double milli = time_within_day % 1000;
3925     if (argc >= 2) {
3926       Handle<Object> min = args.at<Object>(2);
3927       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min));
3928       m = min->Number();
3929       if (argc >= 3) {
3930         Handle<Object> sec = args.at<Object>(3);
3931         ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
3932         s = sec->Number();
3933         if (argc >= 4) {
3934           Handle<Object> ms = args.at<Object>(4);
3935           ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3936           milli = ms->Number();
3937         }
3938       }
3939     }
3940     time_val = MakeDate(day, MakeTime(h, m, s, milli));
3941   }
3942   return *JSDate::SetValue(date, TimeClip(time_val));
3943 }
3944 
3945 
3946 // ES6 section 20.3.4.31 Date.prototype.setUTCMilliseconds(ms)
BUILTIN(DatePrototypeSetUTCMilliseconds)3947 BUILTIN(DatePrototypeSetUTCMilliseconds) {
3948   HandleScope scope(isolate);
3949   CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMilliseconds");
3950   Handle<Object> ms = args.atOrUndefined(isolate, 1);
3951   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3952   double time_val = date->value()->Number();
3953   if (!std::isnan(time_val)) {
3954     int64_t const time_ms = static_cast<int64_t>(time_val);
3955     int day = isolate->date_cache()->DaysFromTime(time_ms);
3956     int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day);
3957     int h = time_within_day / (60 * 60 * 1000);
3958     int m = (time_within_day / (60 * 1000)) % 60;
3959     int s = (time_within_day / 1000) % 60;
3960     time_val = MakeDate(day, MakeTime(h, m, s, ms->Number()));
3961   }
3962   return *JSDate::SetValue(date, TimeClip(time_val));
3963 }
3964 
3965 
3966 // ES6 section 20.3.4.32 Date.prototype.setUTCMinutes ( min, sec, ms )
BUILTIN(DatePrototypeSetUTCMinutes)3967 BUILTIN(DatePrototypeSetUTCMinutes) {
3968   HandleScope scope(isolate);
3969   CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMinutes");
3970   int const argc = args.length() - 1;
3971   Handle<Object> min = args.atOrUndefined(isolate, 1);
3972   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min));
3973   double time_val = date->value()->Number();
3974   if (!std::isnan(time_val)) {
3975     int64_t const time_ms = static_cast<int64_t>(time_val);
3976     int day = isolate->date_cache()->DaysFromTime(time_ms);
3977     int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day);
3978     int h = time_within_day / (60 * 60 * 1000);
3979     double m = min->Number();
3980     double s = (time_within_day / 1000) % 60;
3981     double milli = time_within_day % 1000;
3982     if (argc >= 2) {
3983       Handle<Object> sec = args.at<Object>(2);
3984       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
3985       s = sec->Number();
3986       if (argc >= 3) {
3987         Handle<Object> ms = args.at<Object>(3);
3988         ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3989         milli = ms->Number();
3990       }
3991     }
3992     time_val = MakeDate(day, MakeTime(h, m, s, milli));
3993   }
3994   return *JSDate::SetValue(date, TimeClip(time_val));
3995 }
3996 
3997 
3998 // ES6 section 20.3.4.31 Date.prototype.setUTCMonth ( month, date )
BUILTIN(DatePrototypeSetUTCMonth)3999 BUILTIN(DatePrototypeSetUTCMonth) {
4000   HandleScope scope(isolate);
4001   CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMonth");
4002   int const argc = args.length() - 1;
4003   Handle<Object> month = args.atOrUndefined(isolate, 1);
4004   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month));
4005   double time_val = date->value()->Number();
4006   if (!std::isnan(time_val)) {
4007     int64_t const time_ms = static_cast<int64_t>(time_val);
4008     int days = isolate->date_cache()->DaysFromTime(time_ms);
4009     int time_within_day = isolate->date_cache()->TimeInDay(time_ms, days);
4010     int year, unused, day;
4011     isolate->date_cache()->YearMonthDayFromDays(days, &year, &unused, &day);
4012     double m = month->Number();
4013     double dt = day;
4014     if (argc >= 2) {
4015       Handle<Object> date = args.at<Object>(2);
4016       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date));
4017       dt = date->Number();
4018     }
4019     time_val = MakeDate(MakeDay(year, m, dt), time_within_day);
4020   }
4021   return *JSDate::SetValue(date, TimeClip(time_val));
4022 }
4023 
4024 
4025 // ES6 section 20.3.4.34 Date.prototype.setUTCSeconds ( sec, ms )
BUILTIN(DatePrototypeSetUTCSeconds)4026 BUILTIN(DatePrototypeSetUTCSeconds) {
4027   HandleScope scope(isolate);
4028   CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCSeconds");
4029   int const argc = args.length() - 1;
4030   Handle<Object> sec = args.atOrUndefined(isolate, 1);
4031   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
4032   double time_val = date->value()->Number();
4033   if (!std::isnan(time_val)) {
4034     int64_t const time_ms = static_cast<int64_t>(time_val);
4035     int day = isolate->date_cache()->DaysFromTime(time_ms);
4036     int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day);
4037     int h = time_within_day / (60 * 60 * 1000);
4038     double m = (time_within_day / (60 * 1000)) % 60;
4039     double s = sec->Number();
4040     double milli = time_within_day % 1000;
4041     if (argc >= 2) {
4042       Handle<Object> ms = args.at<Object>(2);
4043       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
4044       milli = ms->Number();
4045     }
4046     time_val = MakeDate(day, MakeTime(h, m, s, milli));
4047   }
4048   return *JSDate::SetValue(date, TimeClip(time_val));
4049 }
4050 
4051 
4052 // ES6 section 20.3.4.35 Date.prototype.toDateString ( )
BUILTIN(DatePrototypeToDateString)4053 BUILTIN(DatePrototypeToDateString) {
4054   HandleScope scope(isolate);
4055   CHECK_RECEIVER(JSDate, date, "Date.prototype.toDateString");
4056   char buffer[128];
4057   ToDateString(date->value()->Number(), ArrayVector(buffer),
4058                isolate->date_cache(), kDateOnly);
4059   RETURN_RESULT_OR_FAILURE(
4060       isolate, isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
4061 }
4062 
4063 
4064 // ES6 section 20.3.4.36 Date.prototype.toISOString ( )
BUILTIN(DatePrototypeToISOString)4065 BUILTIN(DatePrototypeToISOString) {
4066   HandleScope scope(isolate);
4067   CHECK_RECEIVER(JSDate, date, "Date.prototype.toISOString");
4068   double const time_val = date->value()->Number();
4069   if (std::isnan(time_val)) {
4070     THROW_NEW_ERROR_RETURN_FAILURE(
4071         isolate, NewRangeError(MessageTemplate::kInvalidTimeValue));
4072   }
4073   int64_t const time_ms = static_cast<int64_t>(time_val);
4074   int year, month, day, weekday, hour, min, sec, ms;
4075   isolate->date_cache()->BreakDownTime(time_ms, &year, &month, &day, &weekday,
4076                                        &hour, &min, &sec, &ms);
4077   char buffer[128];
4078   if (year >= 0 && year <= 9999) {
4079     SNPrintF(ArrayVector(buffer), "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", year,
4080              month + 1, day, hour, min, sec, ms);
4081   } else if (year < 0) {
4082     SNPrintF(ArrayVector(buffer), "-%06d-%02d-%02dT%02d:%02d:%02d.%03dZ", -year,
4083              month + 1, day, hour, min, sec, ms);
4084   } else {
4085     SNPrintF(ArrayVector(buffer), "+%06d-%02d-%02dT%02d:%02d:%02d.%03dZ", year,
4086              month + 1, day, hour, min, sec, ms);
4087   }
4088   return *isolate->factory()->NewStringFromAsciiChecked(buffer);
4089 }
4090 
4091 
4092 // ES6 section 20.3.4.41 Date.prototype.toString ( )
BUILTIN(DatePrototypeToString)4093 BUILTIN(DatePrototypeToString) {
4094   HandleScope scope(isolate);
4095   CHECK_RECEIVER(JSDate, date, "Date.prototype.toString");
4096   char buffer[128];
4097   ToDateString(date->value()->Number(), ArrayVector(buffer),
4098                isolate->date_cache());
4099   RETURN_RESULT_OR_FAILURE(
4100       isolate, isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
4101 }
4102 
4103 
4104 // ES6 section 20.3.4.42 Date.prototype.toTimeString ( )
BUILTIN(DatePrototypeToTimeString)4105 BUILTIN(DatePrototypeToTimeString) {
4106   HandleScope scope(isolate);
4107   CHECK_RECEIVER(JSDate, date, "Date.prototype.toTimeString");
4108   char buffer[128];
4109   ToDateString(date->value()->Number(), ArrayVector(buffer),
4110                isolate->date_cache(), kTimeOnly);
4111   RETURN_RESULT_OR_FAILURE(
4112       isolate, isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
4113 }
4114 
4115 
4116 // ES6 section 20.3.4.43 Date.prototype.toUTCString ( )
BUILTIN(DatePrototypeToUTCString)4117 BUILTIN(DatePrototypeToUTCString) {
4118   HandleScope scope(isolate);
4119   CHECK_RECEIVER(JSDate, date, "Date.prototype.toUTCString");
4120   double const time_val = date->value()->Number();
4121   if (std::isnan(time_val)) {
4122     return *isolate->factory()->NewStringFromAsciiChecked("Invalid Date");
4123   }
4124   char buffer[128];
4125   int64_t time_ms = static_cast<int64_t>(time_val);
4126   int year, month, day, weekday, hour, min, sec, ms;
4127   isolate->date_cache()->BreakDownTime(time_ms, &year, &month, &day, &weekday,
4128                                        &hour, &min, &sec, &ms);
4129   SNPrintF(ArrayVector(buffer), "%s, %02d %s %4d %02d:%02d:%02d GMT",
4130            kShortWeekDays[weekday], day, kShortMonths[month], year, hour, min,
4131            sec);
4132   return *isolate->factory()->NewStringFromAsciiChecked(buffer);
4133 }
4134 
4135 
4136 // ES6 section 20.3.4.44 Date.prototype.valueOf ( )
BUILTIN(DatePrototypeValueOf)4137 BUILTIN(DatePrototypeValueOf) {
4138   HandleScope scope(isolate);
4139   CHECK_RECEIVER(JSDate, date, "Date.prototype.valueOf");
4140   return date->value();
4141 }
4142 
4143 
4144 // ES6 section 20.3.4.45 Date.prototype [ @@toPrimitive ] ( hint )
BUILTIN(DatePrototypeToPrimitive)4145 BUILTIN(DatePrototypeToPrimitive) {
4146   HandleScope scope(isolate);
4147   DCHECK_EQ(2, args.length());
4148   CHECK_RECEIVER(JSReceiver, receiver, "Date.prototype [ @@toPrimitive ]");
4149   Handle<Object> hint = args.at<Object>(1);
4150   RETURN_RESULT_OR_FAILURE(isolate, JSDate::ToPrimitive(receiver, hint));
4151 }
4152 
4153 
4154 // ES6 section B.2.4.1 Date.prototype.getYear ( )
BUILTIN(DatePrototypeGetYear)4155 BUILTIN(DatePrototypeGetYear) {
4156   HandleScope scope(isolate);
4157   CHECK_RECEIVER(JSDate, date, "Date.prototype.getYear");
4158   double time_val = date->value()->Number();
4159   if (std::isnan(time_val)) return date->value();
4160   int64_t time_ms = static_cast<int64_t>(time_val);
4161   int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
4162   int days = isolate->date_cache()->DaysFromTime(local_time_ms);
4163   int year, month, day;
4164   isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
4165   return Smi::FromInt(year - 1900);
4166 }
4167 
4168 
4169 // ES6 section B.2.4.2 Date.prototype.setYear ( year )
BUILTIN(DatePrototypeSetYear)4170 BUILTIN(DatePrototypeSetYear) {
4171   HandleScope scope(isolate);
4172   CHECK_RECEIVER(JSDate, date, "Date.prototype.setYear");
4173   Handle<Object> year = args.atOrUndefined(isolate, 1);
4174   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, Object::ToNumber(year));
4175   double m = 0.0, dt = 1.0, y = year->Number();
4176   if (0.0 <= y && y <= 99.0) {
4177     y = 1900.0 + DoubleToInteger(y);
4178   }
4179   int time_within_day = 0;
4180   if (!std::isnan(date->value()->Number())) {
4181     int64_t const time_ms = static_cast<int64_t>(date->value()->Number());
4182     int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
4183     int const days = isolate->date_cache()->DaysFromTime(local_time_ms);
4184     time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days);
4185     int year, month, day;
4186     isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
4187     m = month;
4188     dt = day;
4189   }
4190   double time_val = MakeDate(MakeDay(y, m, dt), time_within_day);
4191   return SetLocalDateValue(date, time_val);
4192 }
4193 
4194 // ES6 section 20.3.4.37 Date.prototype.toJSON ( key )
BUILTIN(DatePrototypeToJson)4195 BUILTIN(DatePrototypeToJson) {
4196   HandleScope scope(isolate);
4197   Handle<Object> receiver = args.atOrUndefined(isolate, 0);
4198   Handle<JSReceiver> receiver_obj;
4199   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver_obj,
4200                                      Object::ToObject(isolate, receiver));
4201   Handle<Object> primitive;
4202   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
4203       isolate, primitive,
4204       Object::ToPrimitive(receiver_obj, ToPrimitiveHint::kNumber));
4205   if (primitive->IsNumber() && !std::isfinite(primitive->Number())) {
4206     return isolate->heap()->null_value();
4207   } else {
4208     Handle<String> name =
4209         isolate->factory()->NewStringFromAsciiChecked("toISOString");
4210     Handle<Object> function;
4211     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, function,
4212                                        Object::GetProperty(receiver_obj, name));
4213     if (!function->IsCallable()) {
4214       THROW_NEW_ERROR_RETURN_FAILURE(
4215           isolate, NewTypeError(MessageTemplate::kCalledNonCallable, name));
4216     }
4217     RETURN_RESULT_OR_FAILURE(
4218         isolate, Execution::Call(isolate, function, receiver_obj, 0, NULL));
4219   }
4220 }
4221 
4222 // static
Generate_DatePrototypeGetDate(MacroAssembler * masm)4223 void Builtins::Generate_DatePrototypeGetDate(MacroAssembler* masm) {
4224   Generate_DatePrototype_GetField(masm, JSDate::kDay);
4225 }
4226 
4227 
4228 // static
Generate_DatePrototypeGetDay(MacroAssembler * masm)4229 void Builtins::Generate_DatePrototypeGetDay(MacroAssembler* masm) {
4230   Generate_DatePrototype_GetField(masm, JSDate::kWeekday);
4231 }
4232 
4233 
4234 // static
Generate_DatePrototypeGetFullYear(MacroAssembler * masm)4235 void Builtins::Generate_DatePrototypeGetFullYear(MacroAssembler* masm) {
4236   Generate_DatePrototype_GetField(masm, JSDate::kYear);
4237 }
4238 
4239 
4240 // static
Generate_DatePrototypeGetHours(MacroAssembler * masm)4241 void Builtins::Generate_DatePrototypeGetHours(MacroAssembler* masm) {
4242   Generate_DatePrototype_GetField(masm, JSDate::kHour);
4243 }
4244 
4245 
4246 // static
Generate_DatePrototypeGetMilliseconds(MacroAssembler * masm)4247 void Builtins::Generate_DatePrototypeGetMilliseconds(MacroAssembler* masm) {
4248   Generate_DatePrototype_GetField(masm, JSDate::kMillisecond);
4249 }
4250 
4251 
4252 // static
Generate_DatePrototypeGetMinutes(MacroAssembler * masm)4253 void Builtins::Generate_DatePrototypeGetMinutes(MacroAssembler* masm) {
4254   Generate_DatePrototype_GetField(masm, JSDate::kMinute);
4255 }
4256 
4257 
4258 // static
Generate_DatePrototypeGetMonth(MacroAssembler * masm)4259 void Builtins::Generate_DatePrototypeGetMonth(MacroAssembler* masm) {
4260   Generate_DatePrototype_GetField(masm, JSDate::kMonth);
4261 }
4262 
4263 
4264 // static
Generate_DatePrototypeGetSeconds(MacroAssembler * masm)4265 void Builtins::Generate_DatePrototypeGetSeconds(MacroAssembler* masm) {
4266   Generate_DatePrototype_GetField(masm, JSDate::kSecond);
4267 }
4268 
4269 
4270 // static
Generate_DatePrototypeGetTime(MacroAssembler * masm)4271 void Builtins::Generate_DatePrototypeGetTime(MacroAssembler* masm) {
4272   Generate_DatePrototype_GetField(masm, JSDate::kDateValue);
4273 }
4274 
4275 
4276 // static
Generate_DatePrototypeGetTimezoneOffset(MacroAssembler * masm)4277 void Builtins::Generate_DatePrototypeGetTimezoneOffset(MacroAssembler* masm) {
4278   Generate_DatePrototype_GetField(masm, JSDate::kTimezoneOffset);
4279 }
4280 
4281 
4282 // static
Generate_DatePrototypeGetUTCDate(MacroAssembler * masm)4283 void Builtins::Generate_DatePrototypeGetUTCDate(MacroAssembler* masm) {
4284   Generate_DatePrototype_GetField(masm, JSDate::kDayUTC);
4285 }
4286 
4287 
4288 // static
Generate_DatePrototypeGetUTCDay(MacroAssembler * masm)4289 void Builtins::Generate_DatePrototypeGetUTCDay(MacroAssembler* masm) {
4290   Generate_DatePrototype_GetField(masm, JSDate::kWeekdayUTC);
4291 }
4292 
4293 
4294 // static
Generate_DatePrototypeGetUTCFullYear(MacroAssembler * masm)4295 void Builtins::Generate_DatePrototypeGetUTCFullYear(MacroAssembler* masm) {
4296   Generate_DatePrototype_GetField(masm, JSDate::kYearUTC);
4297 }
4298 
4299 
4300 // static
Generate_DatePrototypeGetUTCHours(MacroAssembler * masm)4301 void Builtins::Generate_DatePrototypeGetUTCHours(MacroAssembler* masm) {
4302   Generate_DatePrototype_GetField(masm, JSDate::kHourUTC);
4303 }
4304 
4305 
4306 // static
Generate_DatePrototypeGetUTCMilliseconds(MacroAssembler * masm)4307 void Builtins::Generate_DatePrototypeGetUTCMilliseconds(MacroAssembler* masm) {
4308   Generate_DatePrototype_GetField(masm, JSDate::kMillisecondUTC);
4309 }
4310 
4311 
4312 // static
Generate_DatePrototypeGetUTCMinutes(MacroAssembler * masm)4313 void Builtins::Generate_DatePrototypeGetUTCMinutes(MacroAssembler* masm) {
4314   Generate_DatePrototype_GetField(masm, JSDate::kMinuteUTC);
4315 }
4316 
4317 
4318 // static
Generate_DatePrototypeGetUTCMonth(MacroAssembler * masm)4319 void Builtins::Generate_DatePrototypeGetUTCMonth(MacroAssembler* masm) {
4320   Generate_DatePrototype_GetField(masm, JSDate::kMonthUTC);
4321 }
4322 
4323 
4324 // static
Generate_DatePrototypeGetUTCSeconds(MacroAssembler * masm)4325 void Builtins::Generate_DatePrototypeGetUTCSeconds(MacroAssembler* masm) {
4326   Generate_DatePrototype_GetField(masm, JSDate::kSecondUTC);
4327 }
4328 
4329 
4330 namespace {
4331 
4332 // ES6 section 19.2.1.1.1 CreateDynamicFunction
CreateDynamicFunction(Isolate * isolate,BuiltinArguments args,const char * token)4333 MaybeHandle<JSFunction> CreateDynamicFunction(Isolate* isolate,
4334                                               BuiltinArguments args,
4335                                               const char* token) {
4336   // Compute number of arguments, ignoring the receiver.
4337   DCHECK_LE(1, args.length());
4338   int const argc = args.length() - 1;
4339 
4340   // Build the source string.
4341   Handle<String> source;
4342   {
4343     IncrementalStringBuilder builder(isolate);
4344     builder.AppendCharacter('(');
4345     builder.AppendCString(token);
4346     builder.AppendCharacter('(');
4347     bool parenthesis_in_arg_string = false;
4348     if (argc > 1) {
4349       for (int i = 1; i < argc; ++i) {
4350         if (i > 1) builder.AppendCharacter(',');
4351         Handle<String> param;
4352         ASSIGN_RETURN_ON_EXCEPTION(
4353             isolate, param, Object::ToString(isolate, args.at<Object>(i)),
4354             JSFunction);
4355         param = String::Flatten(param);
4356         builder.AppendString(param);
4357         // If the formal parameters string include ) - an illegal
4358         // character - it may make the combined function expression
4359         // compile. We avoid this problem by checking for this early on.
4360         DisallowHeapAllocation no_gc;  // Ensure vectors stay valid.
4361         String::FlatContent param_content = param->GetFlatContent();
4362         for (int i = 0, length = param->length(); i < length; ++i) {
4363           if (param_content.Get(i) == ')') {
4364             parenthesis_in_arg_string = true;
4365             break;
4366           }
4367         }
4368       }
4369       // If the formal parameters include an unbalanced block comment, the
4370       // function must be rejected. Since JavaScript does not allow nested
4371       // comments we can include a trailing block comment to catch this.
4372       builder.AppendCString("\n/**/");
4373     }
4374     builder.AppendCString(") {\n");
4375     if (argc > 0) {
4376       Handle<String> body;
4377       ASSIGN_RETURN_ON_EXCEPTION(
4378           isolate, body, Object::ToString(isolate, args.at<Object>(argc)),
4379           JSFunction);
4380       builder.AppendString(body);
4381     }
4382     builder.AppendCString("\n})");
4383     ASSIGN_RETURN_ON_EXCEPTION(isolate, source, builder.Finish(), JSFunction);
4384 
4385     // The SyntaxError must be thrown after all the (observable) ToString
4386     // conversions are done.
4387     if (parenthesis_in_arg_string) {
4388       THROW_NEW_ERROR(isolate,
4389                       NewSyntaxError(MessageTemplate::kParenthesisInArgString),
4390                       JSFunction);
4391     }
4392   }
4393 
4394   // Compile the string in the constructor and not a helper so that errors to
4395   // come from here.
4396   Handle<JSFunction> target = args.target<JSFunction>();
4397   Handle<JSObject> target_global_proxy(target->global_proxy(), isolate);
4398   Handle<JSFunction> function;
4399   {
4400     ASSIGN_RETURN_ON_EXCEPTION(
4401         isolate, function,
4402         CompileString(handle(target->native_context(), isolate), source,
4403                       ONLY_SINGLE_FUNCTION_LITERAL),
4404         JSFunction);
4405     Handle<Object> result;
4406     ASSIGN_RETURN_ON_EXCEPTION(
4407         isolate, result,
4408         Execution::Call(isolate, function, target_global_proxy, 0, nullptr),
4409         JSFunction);
4410     function = Handle<JSFunction>::cast(result);
4411     function->shared()->set_name_should_print_as_anonymous(true);
4412   }
4413 
4414   // If new.target is equal to target then the function created
4415   // is already correctly setup and nothing else should be done
4416   // here. But if new.target is not equal to target then we are
4417   // have a Function builtin subclassing case and therefore the
4418   // function has wrong initial map. To fix that we create a new
4419   // function object with correct initial map.
4420   Handle<Object> unchecked_new_target = args.new_target();
4421   if (!unchecked_new_target->IsUndefined(isolate) &&
4422       !unchecked_new_target.is_identical_to(target)) {
4423     Handle<JSReceiver> new_target =
4424         Handle<JSReceiver>::cast(unchecked_new_target);
4425     Handle<Map> initial_map;
4426     ASSIGN_RETURN_ON_EXCEPTION(
4427         isolate, initial_map,
4428         JSFunction::GetDerivedMap(isolate, target, new_target), JSFunction);
4429 
4430     Handle<SharedFunctionInfo> shared_info(function->shared(), isolate);
4431     Handle<Map> map = Map::AsLanguageMode(
4432         initial_map, shared_info->language_mode(), shared_info->kind());
4433 
4434     Handle<Context> context(function->context(), isolate);
4435     function = isolate->factory()->NewFunctionFromSharedFunctionInfo(
4436         map, shared_info, context, NOT_TENURED);
4437   }
4438   return function;
4439 }
4440 
4441 }  // namespace
4442 
4443 
4444 // ES6 section 19.2.1.1 Function ( p1, p2, ... , pn, body )
BUILTIN(FunctionConstructor)4445 BUILTIN(FunctionConstructor) {
4446   HandleScope scope(isolate);
4447   Handle<JSFunction> result;
4448   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
4449       isolate, result, CreateDynamicFunction(isolate, args, "function"));
4450   return *result;
4451 }
4452 
4453 namespace {
4454 
DoFunctionBind(Isolate * isolate,BuiltinArguments args)4455 Object* DoFunctionBind(Isolate* isolate, BuiltinArguments args) {
4456   HandleScope scope(isolate);
4457   DCHECK_LE(1, args.length());
4458   if (!args.receiver()->IsCallable()) {
4459     THROW_NEW_ERROR_RETURN_FAILURE(
4460         isolate, NewTypeError(MessageTemplate::kFunctionBind));
4461   }
4462 
4463   // Allocate the bound function with the given {this_arg} and {args}.
4464   Handle<JSReceiver> target = args.at<JSReceiver>(0);
4465   Handle<Object> this_arg = isolate->factory()->undefined_value();
4466   ScopedVector<Handle<Object>> argv(std::max(0, args.length() - 2));
4467   if (args.length() > 1) {
4468     this_arg = args.at<Object>(1);
4469     for (int i = 2; i < args.length(); ++i) {
4470       argv[i - 2] = args.at<Object>(i);
4471     }
4472   }
4473   Handle<JSBoundFunction> function;
4474   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
4475       isolate, function,
4476       isolate->factory()->NewJSBoundFunction(target, this_arg, argv));
4477 
4478   LookupIterator length_lookup(target, isolate->factory()->length_string(),
4479                                target, LookupIterator::OWN);
4480   // Setup the "length" property based on the "length" of the {target}.
4481   // If the targets length is the default JSFunction accessor, we can keep the
4482   // accessor that's installed by default on the JSBoundFunction. It lazily
4483   // computes the value from the underlying internal length.
4484   if (!target->IsJSFunction() ||
4485       length_lookup.state() != LookupIterator::ACCESSOR ||
4486       !length_lookup.GetAccessors()->IsAccessorInfo()) {
4487     Handle<Object> length(Smi::FromInt(0), isolate);
4488     Maybe<PropertyAttributes> attributes =
4489         JSReceiver::GetPropertyAttributes(&length_lookup);
4490     if (!attributes.IsJust()) return isolate->heap()->exception();
4491     if (attributes.FromJust() != ABSENT) {
4492       Handle<Object> target_length;
4493       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, target_length,
4494                                          Object::GetProperty(&length_lookup));
4495       if (target_length->IsNumber()) {
4496         length = isolate->factory()->NewNumber(std::max(
4497             0.0, DoubleToInteger(target_length->Number()) - argv.length()));
4498       }
4499     }
4500     LookupIterator it(function, isolate->factory()->length_string(), function);
4501     DCHECK_EQ(LookupIterator::ACCESSOR, it.state());
4502     RETURN_FAILURE_ON_EXCEPTION(isolate,
4503                                 JSObject::DefineOwnPropertyIgnoreAttributes(
4504                                     &it, length, it.property_attributes()));
4505   }
4506 
4507   // Setup the "name" property based on the "name" of the {target}.
4508   // If the targets name is the default JSFunction accessor, we can keep the
4509   // accessor that's installed by default on the JSBoundFunction. It lazily
4510   // computes the value from the underlying internal name.
4511   LookupIterator name_lookup(target, isolate->factory()->name_string(), target,
4512                              LookupIterator::OWN);
4513   if (!target->IsJSFunction() ||
4514       name_lookup.state() != LookupIterator::ACCESSOR ||
4515       !name_lookup.GetAccessors()->IsAccessorInfo()) {
4516     Handle<Object> target_name;
4517     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, target_name,
4518                                        Object::GetProperty(&name_lookup));
4519     Handle<String> name;
4520     if (target_name->IsString()) {
4521       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
4522           isolate, name,
4523           Name::ToFunctionName(Handle<String>::cast(target_name)));
4524       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
4525           isolate, name, isolate->factory()->NewConsString(
4526                              isolate->factory()->bound__string(), name));
4527     } else {
4528       name = isolate->factory()->bound__string();
4529     }
4530     LookupIterator it(function, isolate->factory()->name_string());
4531     DCHECK_EQ(LookupIterator::ACCESSOR, it.state());
4532     RETURN_FAILURE_ON_EXCEPTION(isolate,
4533                                 JSObject::DefineOwnPropertyIgnoreAttributes(
4534                                     &it, name, it.property_attributes()));
4535   }
4536   return *function;
4537 }
4538 
4539 }  // namespace
4540 
4541 // ES6 section 19.2.3.2 Function.prototype.bind ( thisArg, ...args )
BUILTIN(FunctionPrototypeBind)4542 BUILTIN(FunctionPrototypeBind) { return DoFunctionBind(isolate, args); }
4543 
4544 // TODO(verwaest): This is a temporary helper until the FastFunctionBind stub
4545 // can tailcall to the builtin directly.
RUNTIME_FUNCTION(Runtime_FunctionBind)4546 RUNTIME_FUNCTION(Runtime_FunctionBind) {
4547   DCHECK_EQ(2, args.length());
4548   Arguments* incoming = reinterpret_cast<Arguments*>(args[0]);
4549   // Rewrap the arguments as builtins arguments.
4550   BuiltinArguments caller_args(incoming->length() + 3,
4551                                incoming->arguments() + 1);
4552   return DoFunctionBind(isolate, caller_args);
4553 }
4554 
4555 // ES6 section 19.2.3.5 Function.prototype.toString ( )
BUILTIN(FunctionPrototypeToString)4556 BUILTIN(FunctionPrototypeToString) {
4557   HandleScope scope(isolate);
4558   Handle<Object> receiver = args.receiver();
4559   if (receiver->IsJSBoundFunction()) {
4560     return *JSBoundFunction::ToString(Handle<JSBoundFunction>::cast(receiver));
4561   } else if (receiver->IsJSFunction()) {
4562     return *JSFunction::ToString(Handle<JSFunction>::cast(receiver));
4563   }
4564   THROW_NEW_ERROR_RETURN_FAILURE(
4565       isolate, NewTypeError(MessageTemplate::kNotGeneric,
4566                             isolate->factory()->NewStringFromAsciiChecked(
4567                                 "Function.prototype.toString")));
4568 }
4569 
4570 
4571 // ES6 section 25.2.1.1 GeneratorFunction (p1, p2, ... , pn, body)
BUILTIN(GeneratorFunctionConstructor)4572 BUILTIN(GeneratorFunctionConstructor) {
4573   HandleScope scope(isolate);
4574   RETURN_RESULT_OR_FAILURE(isolate,
4575                            CreateDynamicFunction(isolate, args, "function*"));
4576 }
4577 
BUILTIN(AsyncFunctionConstructor)4578 BUILTIN(AsyncFunctionConstructor) {
4579   HandleScope scope(isolate);
4580   Handle<JSFunction> func;
4581   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
4582       isolate, func, CreateDynamicFunction(isolate, args, "async function"));
4583 
4584   // Do not lazily compute eval position for AsyncFunction, as they may not be
4585   // determined after the function is resumed.
4586   Handle<Script> script = handle(Script::cast(func->shared()->script()));
4587   int position = script->GetEvalPosition();
4588   USE(position);
4589 
4590   return *func;
4591 }
4592 
4593 // ES6 section 19.4.1.1 Symbol ( [ description ] ) for the [[Call]] case.
BUILTIN(SymbolConstructor)4594 BUILTIN(SymbolConstructor) {
4595   HandleScope scope(isolate);
4596   Handle<Symbol> result = isolate->factory()->NewSymbol();
4597   Handle<Object> description = args.atOrUndefined(isolate, 1);
4598   if (!description->IsUndefined(isolate)) {
4599     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, description,
4600                                        Object::ToString(isolate, description));
4601     result->set_name(*description);
4602   }
4603   return *result;
4604 }
4605 
4606 
4607 // ES6 section 19.4.1.1 Symbol ( [ description ] ) for the [[Construct]] case.
BUILTIN(SymbolConstructor_ConstructStub)4608 BUILTIN(SymbolConstructor_ConstructStub) {
4609   HandleScope scope(isolate);
4610   THROW_NEW_ERROR_RETURN_FAILURE(
4611       isolate, NewTypeError(MessageTemplate::kNotConstructor,
4612                             isolate->factory()->Symbol_string()));
4613 }
4614 
4615 
4616 // ES6 19.1.3.6 Object.prototype.toString
BUILTIN(ObjectProtoToString)4617 BUILTIN(ObjectProtoToString) {
4618   HandleScope scope(isolate);
4619   Handle<Object> object = args.at<Object>(0);
4620   RETURN_RESULT_OR_FAILURE(isolate,
4621                            Object::ObjectProtoToString(isolate, object));
4622 }
4623 
4624 // -----------------------------------------------------------------------------
4625 // ES6 section 21.1 String Objects
4626 
4627 // ES6 section 21.1.2.1 String.fromCharCode ( ...codeUnits )
Generate_StringFromCharCode(CodeStubAssembler * assembler)4628 void Builtins::Generate_StringFromCharCode(CodeStubAssembler* assembler) {
4629   typedef CodeStubAssembler::Label Label;
4630   typedef compiler::Node Node;
4631   typedef CodeStubAssembler::Variable Variable;
4632 
4633   Node* code = assembler->Parameter(1);
4634   Node* context = assembler->Parameter(4);
4635 
4636   // Check if we have exactly one argument (plus the implicit receiver), i.e.
4637   // if the parent frame is not an arguments adaptor frame.
4638   Label if_oneargument(assembler), if_notoneargument(assembler);
4639   Node* parent_frame_pointer = assembler->LoadParentFramePointer();
4640   Node* parent_frame_type =
4641       assembler->Load(MachineType::Pointer(), parent_frame_pointer,
4642                       assembler->IntPtrConstant(
4643                           CommonFrameConstants::kContextOrFrameTypeOffset));
4644   assembler->Branch(
4645       assembler->WordEqual(
4646           parent_frame_type,
4647           assembler->SmiConstant(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))),
4648       &if_notoneargument, &if_oneargument);
4649 
4650   assembler->Bind(&if_oneargument);
4651   {
4652     // Single argument case, perform fast single character string cache lookup
4653     // for one-byte code units, or fall back to creating a single character
4654     // string on the fly otherwise.
4655     Node* code32 = assembler->TruncateTaggedToWord32(context, code);
4656     Node* code16 = assembler->Word32And(
4657         code32, assembler->Int32Constant(String::kMaxUtf16CodeUnit));
4658     Node* result = assembler->StringFromCharCode(code16);
4659     assembler->Return(result);
4660   }
4661 
4662   assembler->Bind(&if_notoneargument);
4663   {
4664     // Determine the resulting string length.
4665     Node* parent_frame_length =
4666         assembler->Load(MachineType::Pointer(), parent_frame_pointer,
4667                         assembler->IntPtrConstant(
4668                             ArgumentsAdaptorFrameConstants::kLengthOffset));
4669     Node* length = assembler->SmiToWord(parent_frame_length);
4670 
4671     // Assume that the resulting string contains only one-byte characters.
4672     Node* result = assembler->AllocateSeqOneByteString(context, length);
4673 
4674     // Truncate all input parameters and append them to the resulting string.
4675     Variable var_offset(assembler, MachineType::PointerRepresentation());
4676     Label loop(assembler, &var_offset), done_loop(assembler);
4677     var_offset.Bind(assembler->IntPtrConstant(0));
4678     assembler->Goto(&loop);
4679     assembler->Bind(&loop);
4680     {
4681       // Load the current {offset}.
4682       Node* offset = var_offset.value();
4683 
4684       // Check if we're done with the string.
4685       assembler->GotoIf(assembler->WordEqual(offset, length), &done_loop);
4686 
4687       // Load the next code point and truncate it to a 16-bit value.
4688       Node* code = assembler->Load(
4689           MachineType::AnyTagged(), parent_frame_pointer,
4690           assembler->IntPtrAdd(
4691               assembler->WordShl(assembler->IntPtrSub(length, offset),
4692                                  assembler->IntPtrConstant(kPointerSizeLog2)),
4693               assembler->IntPtrConstant(
4694                   CommonFrameConstants::kFixedFrameSizeAboveFp -
4695                   kPointerSize)));
4696       Node* code32 = assembler->TruncateTaggedToWord32(context, code);
4697       Node* code16 = assembler->Word32And(
4698           code32, assembler->Int32Constant(String::kMaxUtf16CodeUnit));
4699 
4700       // Check if {code16} fits into a one-byte string.
4701       Label if_codeisonebyte(assembler), if_codeistwobyte(assembler);
4702       assembler->Branch(
4703           assembler->Int32LessThanOrEqual(
4704               code16, assembler->Int32Constant(String::kMaxOneByteCharCode)),
4705           &if_codeisonebyte, &if_codeistwobyte);
4706 
4707       assembler->Bind(&if_codeisonebyte);
4708       {
4709         // The {code16} fits into the SeqOneByteString {result}.
4710         assembler->StoreNoWriteBarrier(
4711             MachineRepresentation::kWord8, result,
4712             assembler->IntPtrAdd(
4713                 assembler->IntPtrConstant(SeqOneByteString::kHeaderSize -
4714                                           kHeapObjectTag),
4715                 offset),
4716             code16);
4717         var_offset.Bind(
4718             assembler->IntPtrAdd(offset, assembler->IntPtrConstant(1)));
4719         assembler->Goto(&loop);
4720       }
4721 
4722       assembler->Bind(&if_codeistwobyte);
4723       {
4724         // Allocate a SeqTwoByteString to hold the resulting string.
4725         Node* cresult = assembler->AllocateSeqTwoByteString(context, length);
4726 
4727         // Copy all characters that were previously written to the
4728         // SeqOneByteString in {result} over to the new {cresult}.
4729         Variable var_coffset(assembler, MachineType::PointerRepresentation());
4730         Label cloop(assembler, &var_coffset), done_cloop(assembler);
4731         var_coffset.Bind(assembler->IntPtrConstant(0));
4732         assembler->Goto(&cloop);
4733         assembler->Bind(&cloop);
4734         {
4735           Node* coffset = var_coffset.value();
4736           assembler->GotoIf(assembler->WordEqual(coffset, offset), &done_cloop);
4737           Node* ccode = assembler->Load(
4738               MachineType::Uint8(), result,
4739               assembler->IntPtrAdd(
4740                   assembler->IntPtrConstant(SeqOneByteString::kHeaderSize -
4741                                             kHeapObjectTag),
4742                   coffset));
4743           assembler->StoreNoWriteBarrier(
4744               MachineRepresentation::kWord16, cresult,
4745               assembler->IntPtrAdd(
4746                   assembler->IntPtrConstant(SeqTwoByteString::kHeaderSize -
4747                                             kHeapObjectTag),
4748                   assembler->WordShl(coffset, 1)),
4749               ccode);
4750           var_coffset.Bind(
4751               assembler->IntPtrAdd(coffset, assembler->IntPtrConstant(1)));
4752           assembler->Goto(&cloop);
4753         }
4754 
4755         // Write the pending {code16} to {offset}.
4756         assembler->Bind(&done_cloop);
4757         assembler->StoreNoWriteBarrier(
4758             MachineRepresentation::kWord16, cresult,
4759             assembler->IntPtrAdd(
4760                 assembler->IntPtrConstant(SeqTwoByteString::kHeaderSize -
4761                                           kHeapObjectTag),
4762                 assembler->WordShl(offset, 1)),
4763             code16);
4764 
4765         // Copy the remaining parameters to the SeqTwoByteString {cresult}.
4766         Label floop(assembler, &var_offset), done_floop(assembler);
4767         assembler->Goto(&floop);
4768         assembler->Bind(&floop);
4769         {
4770           // Compute the next {offset}.
4771           Node* offset = assembler->IntPtrAdd(var_offset.value(),
4772                                               assembler->IntPtrConstant(1));
4773 
4774           // Check if we're done with the string.
4775           assembler->GotoIf(assembler->WordEqual(offset, length), &done_floop);
4776 
4777           // Load the next code point and truncate it to a 16-bit value.
4778           Node* code = assembler->Load(
4779               MachineType::AnyTagged(), parent_frame_pointer,
4780               assembler->IntPtrAdd(
4781                   assembler->WordShl(
4782                       assembler->IntPtrSub(length, offset),
4783                       assembler->IntPtrConstant(kPointerSizeLog2)),
4784                   assembler->IntPtrConstant(
4785                       CommonFrameConstants::kFixedFrameSizeAboveFp -
4786                       kPointerSize)));
4787           Node* code32 = assembler->TruncateTaggedToWord32(context, code);
4788           Node* code16 = assembler->Word32And(
4789               code32, assembler->Int32Constant(String::kMaxUtf16CodeUnit));
4790 
4791           // Store the truncated {code} point at the next offset.
4792           assembler->StoreNoWriteBarrier(
4793               MachineRepresentation::kWord16, cresult,
4794               assembler->IntPtrAdd(
4795                   assembler->IntPtrConstant(SeqTwoByteString::kHeaderSize -
4796                                             kHeapObjectTag),
4797                   assembler->WordShl(offset, 1)),
4798               code16);
4799           var_offset.Bind(offset);
4800           assembler->Goto(&floop);
4801         }
4802 
4803         // Return the SeqTwoByteString.
4804         assembler->Bind(&done_floop);
4805         assembler->Return(cresult);
4806       }
4807     }
4808 
4809     assembler->Bind(&done_loop);
4810     assembler->Return(result);
4811   }
4812 }
4813 
4814 namespace {  // for String.fromCodePoint
4815 
IsValidCodePoint(Isolate * isolate,Handle<Object> value)4816 bool IsValidCodePoint(Isolate* isolate, Handle<Object> value) {
4817   if (!value->IsNumber() && !Object::ToNumber(value).ToHandle(&value)) {
4818     return false;
4819   }
4820 
4821   if (Object::ToInteger(isolate, value).ToHandleChecked()->Number() !=
4822       value->Number()) {
4823     return false;
4824   }
4825 
4826   if (value->Number() < 0 || value->Number() > 0x10FFFF) {
4827     return false;
4828   }
4829 
4830   return true;
4831 }
4832 
NextCodePoint(Isolate * isolate,BuiltinArguments args,int index)4833 uc32 NextCodePoint(Isolate* isolate, BuiltinArguments args, int index) {
4834   Handle<Object> value = args.at<Object>(1 + index);
4835   ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, value, Object::ToNumber(value), -1);
4836   if (!IsValidCodePoint(isolate, value)) {
4837     isolate->Throw(*isolate->factory()->NewRangeError(
4838         MessageTemplate::kInvalidCodePoint, value));
4839     return -1;
4840   }
4841   return DoubleToUint32(value->Number());
4842 }
4843 
4844 }  // namespace
4845 
4846 // ES6 section 21.1.2.2 String.fromCodePoint ( ...codePoints )
BUILTIN(StringFromCodePoint)4847 BUILTIN(StringFromCodePoint) {
4848   HandleScope scope(isolate);
4849   int const length = args.length() - 1;
4850   if (length == 0) return isolate->heap()->empty_string();
4851   DCHECK_LT(0, length);
4852 
4853   // Optimistically assume that the resulting String contains only one byte
4854   // characters.
4855   List<uint8_t> one_byte_buffer(length);
4856   uc32 code = 0;
4857   int index;
4858   for (index = 0; index < length; index++) {
4859     code = NextCodePoint(isolate, args, index);
4860     if (code < 0) {
4861       return isolate->heap()->exception();
4862     }
4863     if (code > String::kMaxOneByteCharCode) {
4864       break;
4865     }
4866     one_byte_buffer.Add(code);
4867   }
4868 
4869   if (index == length) {
4870     RETURN_RESULT_OR_FAILURE(isolate, isolate->factory()->NewStringFromOneByte(
4871                                           one_byte_buffer.ToConstVector()));
4872   }
4873 
4874   List<uc16> two_byte_buffer(length - index);
4875 
4876   while (true) {
4877     if (code <= unibrow::Utf16::kMaxNonSurrogateCharCode) {
4878       two_byte_buffer.Add(code);
4879     } else {
4880       two_byte_buffer.Add(unibrow::Utf16::LeadSurrogate(code));
4881       two_byte_buffer.Add(unibrow::Utf16::TrailSurrogate(code));
4882     }
4883 
4884     if (++index == length) {
4885       break;
4886     }
4887     code = NextCodePoint(isolate, args, index);
4888     if (code < 0) {
4889       return isolate->heap()->exception();
4890     }
4891   }
4892 
4893   Handle<SeqTwoByteString> result;
4894   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
4895       isolate, result,
4896       isolate->factory()->NewRawTwoByteString(one_byte_buffer.length() +
4897                                               two_byte_buffer.length()));
4898 
4899   CopyChars(result->GetChars(), one_byte_buffer.ToConstVector().start(),
4900             one_byte_buffer.length());
4901   CopyChars(result->GetChars() + one_byte_buffer.length(),
4902             two_byte_buffer.ToConstVector().start(), two_byte_buffer.length());
4903 
4904   return *result;
4905 }
4906 
4907 // ES6 section 21.1.3.1 String.prototype.charAt ( pos )
Generate_StringPrototypeCharAt(CodeStubAssembler * assembler)4908 void Builtins::Generate_StringPrototypeCharAt(CodeStubAssembler* assembler) {
4909   typedef CodeStubAssembler::Label Label;
4910   typedef compiler::Node Node;
4911   typedef CodeStubAssembler::Variable Variable;
4912 
4913   Node* receiver = assembler->Parameter(0);
4914   Node* position = assembler->Parameter(1);
4915   Node* context = assembler->Parameter(4);
4916 
4917   // Check that {receiver} is coercible to Object and convert it to a String.
4918   receiver =
4919       assembler->ToThisString(context, receiver, "String.prototype.charAt");
4920 
4921   // Convert the {position} to a Smi and check that it's in bounds of the
4922   // {receiver}.
4923   // TODO(bmeurer): Find an abstraction for this!
4924   {
4925     // Check if the {position} is already a Smi.
4926     Variable var_position(assembler, MachineRepresentation::kTagged);
4927     var_position.Bind(position);
4928     Label if_positionissmi(assembler),
4929         if_positionisnotsmi(assembler, Label::kDeferred);
4930     assembler->Branch(assembler->WordIsSmi(position), &if_positionissmi,
4931                       &if_positionisnotsmi);
4932     assembler->Bind(&if_positionisnotsmi);
4933     {
4934       // Convert the {position} to an Integer via the ToIntegerStub.
4935       Callable callable = CodeFactory::ToInteger(assembler->isolate());
4936       Node* index = assembler->CallStub(callable, context, position);
4937 
4938       // Check if the resulting {index} is now a Smi.
4939       Label if_indexissmi(assembler, Label::kDeferred),
4940           if_indexisnotsmi(assembler, Label::kDeferred);
4941       assembler->Branch(assembler->WordIsSmi(index), &if_indexissmi,
4942                         &if_indexisnotsmi);
4943 
4944       assembler->Bind(&if_indexissmi);
4945       {
4946         var_position.Bind(index);
4947         assembler->Goto(&if_positionissmi);
4948       }
4949 
4950       assembler->Bind(&if_indexisnotsmi);
4951       {
4952         // The ToIntegerStub canonicalizes everything in Smi range to Smi
4953         // representation, so any HeapNumber returned is not in Smi range.
4954         // The only exception here is -0.0, which we treat as 0.
4955         Node* index_value = assembler->LoadHeapNumberValue(index);
4956         Label if_indexiszero(assembler, Label::kDeferred),
4957             if_indexisnotzero(assembler, Label::kDeferred);
4958         assembler->Branch(assembler->Float64Equal(
4959                               index_value, assembler->Float64Constant(0.0)),
4960                           &if_indexiszero, &if_indexisnotzero);
4961 
4962         assembler->Bind(&if_indexiszero);
4963         {
4964           var_position.Bind(assembler->SmiConstant(Smi::FromInt(0)));
4965           assembler->Goto(&if_positionissmi);
4966         }
4967 
4968         assembler->Bind(&if_indexisnotzero);
4969         {
4970           // The {index} is some other integral Number, that is definitely
4971           // neither -0.0 nor in Smi range.
4972           assembler->Return(assembler->EmptyStringConstant());
4973         }
4974       }
4975     }
4976     assembler->Bind(&if_positionissmi);
4977     position = var_position.value();
4978 
4979     // Determine the actual length of the {receiver} String.
4980     Node* receiver_length =
4981         assembler->LoadObjectField(receiver, String::kLengthOffset);
4982 
4983     // Return "" if the Smi {position} is outside the bounds of the {receiver}.
4984     Label if_positioninbounds(assembler),
4985         if_positionnotinbounds(assembler, Label::kDeferred);
4986     assembler->Branch(assembler->SmiAboveOrEqual(position, receiver_length),
4987                       &if_positionnotinbounds, &if_positioninbounds);
4988     assembler->Bind(&if_positionnotinbounds);
4989     assembler->Return(assembler->EmptyStringConstant());
4990     assembler->Bind(&if_positioninbounds);
4991   }
4992 
4993   // Load the character code at the {position} from the {receiver}.
4994   Node* code = assembler->StringCharCodeAt(receiver, position);
4995 
4996   // And return the single character string with only that {code}.
4997   Node* result = assembler->StringFromCharCode(code);
4998   assembler->Return(result);
4999 }
5000 
5001 // ES6 section 21.1.3.2 String.prototype.charCodeAt ( pos )
Generate_StringPrototypeCharCodeAt(CodeStubAssembler * assembler)5002 void Builtins::Generate_StringPrototypeCharCodeAt(
5003     CodeStubAssembler* assembler) {
5004   typedef CodeStubAssembler::Label Label;
5005   typedef compiler::Node Node;
5006   typedef CodeStubAssembler::Variable Variable;
5007 
5008   Node* receiver = assembler->Parameter(0);
5009   Node* position = assembler->Parameter(1);
5010   Node* context = assembler->Parameter(4);
5011 
5012   // Check that {receiver} is coercible to Object and convert it to a String.
5013   receiver =
5014       assembler->ToThisString(context, receiver, "String.prototype.charCodeAt");
5015 
5016   // Convert the {position} to a Smi and check that it's in bounds of the
5017   // {receiver}.
5018   // TODO(bmeurer): Find an abstraction for this!
5019   {
5020     // Check if the {position} is already a Smi.
5021     Variable var_position(assembler, MachineRepresentation::kTagged);
5022     var_position.Bind(position);
5023     Label if_positionissmi(assembler),
5024         if_positionisnotsmi(assembler, Label::kDeferred);
5025     assembler->Branch(assembler->WordIsSmi(position), &if_positionissmi,
5026                       &if_positionisnotsmi);
5027     assembler->Bind(&if_positionisnotsmi);
5028     {
5029       // Convert the {position} to an Integer via the ToIntegerStub.
5030       Callable callable = CodeFactory::ToInteger(assembler->isolate());
5031       Node* index = assembler->CallStub(callable, context, position);
5032 
5033       // Check if the resulting {index} is now a Smi.
5034       Label if_indexissmi(assembler, Label::kDeferred),
5035           if_indexisnotsmi(assembler, Label::kDeferred);
5036       assembler->Branch(assembler->WordIsSmi(index), &if_indexissmi,
5037                         &if_indexisnotsmi);
5038 
5039       assembler->Bind(&if_indexissmi);
5040       {
5041         var_position.Bind(index);
5042         assembler->Goto(&if_positionissmi);
5043       }
5044 
5045       assembler->Bind(&if_indexisnotsmi);
5046       {
5047         // The ToIntegerStub canonicalizes everything in Smi range to Smi
5048         // representation, so any HeapNumber returned is not in Smi range.
5049         // The only exception here is -0.0, which we treat as 0.
5050         Node* index_value = assembler->LoadHeapNumberValue(index);
5051         Label if_indexiszero(assembler, Label::kDeferred),
5052             if_indexisnotzero(assembler, Label::kDeferred);
5053         assembler->Branch(assembler->Float64Equal(
5054                               index_value, assembler->Float64Constant(0.0)),
5055                           &if_indexiszero, &if_indexisnotzero);
5056 
5057         assembler->Bind(&if_indexiszero);
5058         {
5059           var_position.Bind(assembler->SmiConstant(Smi::FromInt(0)));
5060           assembler->Goto(&if_positionissmi);
5061         }
5062 
5063         assembler->Bind(&if_indexisnotzero);
5064         {
5065           // The {index} is some other integral Number, that is definitely
5066           // neither -0.0 nor in Smi range.
5067           assembler->Return(assembler->NaNConstant());
5068         }
5069       }
5070     }
5071     assembler->Bind(&if_positionissmi);
5072     position = var_position.value();
5073 
5074     // Determine the actual length of the {receiver} String.
5075     Node* receiver_length =
5076         assembler->LoadObjectField(receiver, String::kLengthOffset);
5077 
5078     // Return NaN if the Smi {position} is outside the bounds of the {receiver}.
5079     Label if_positioninbounds(assembler),
5080         if_positionnotinbounds(assembler, Label::kDeferred);
5081     assembler->Branch(assembler->SmiAboveOrEqual(position, receiver_length),
5082                       &if_positionnotinbounds, &if_positioninbounds);
5083     assembler->Bind(&if_positionnotinbounds);
5084     assembler->Return(assembler->NaNConstant());
5085     assembler->Bind(&if_positioninbounds);
5086   }
5087 
5088   // Load the character at the {position} from the {receiver}.
5089   Node* value = assembler->StringCharCodeAt(receiver, position);
5090   Node* result = assembler->SmiFromWord32(value);
5091   assembler->Return(result);
5092 }
5093 
5094 // ES6 section 21.1.3.25 String.prototype.trim ()
BUILTIN(StringPrototypeTrim)5095 BUILTIN(StringPrototypeTrim) {
5096   HandleScope scope(isolate);
5097   TO_THIS_STRING(string, "String.prototype.trim");
5098   return *String::Trim(string, String::kTrim);
5099 }
5100 
5101 // Non-standard WebKit extension
BUILTIN(StringPrototypeTrimLeft)5102 BUILTIN(StringPrototypeTrimLeft) {
5103   HandleScope scope(isolate);
5104   TO_THIS_STRING(string, "String.prototype.trimLeft");
5105   return *String::Trim(string, String::kTrimLeft);
5106 }
5107 
5108 // Non-standard WebKit extension
BUILTIN(StringPrototypeTrimRight)5109 BUILTIN(StringPrototypeTrimRight) {
5110   HandleScope scope(isolate);
5111   TO_THIS_STRING(string, "String.prototype.trimRight");
5112   return *String::Trim(string, String::kTrimRight);
5113 }
5114 
5115 // -----------------------------------------------------------------------------
5116 // ES6 section 21.1 ArrayBuffer Objects
5117 
5118 // ES6 section 24.1.2.1 ArrayBuffer ( length ) for the [[Call]] case.
BUILTIN(ArrayBufferConstructor)5119 BUILTIN(ArrayBufferConstructor) {
5120   HandleScope scope(isolate);
5121   Handle<JSFunction> target = args.target<JSFunction>();
5122   DCHECK(*target == target->native_context()->array_buffer_fun() ||
5123          *target == target->native_context()->shared_array_buffer_fun());
5124   THROW_NEW_ERROR_RETURN_FAILURE(
5125       isolate, NewTypeError(MessageTemplate::kConstructorNotFunction,
5126                             handle(target->shared()->name(), isolate)));
5127 }
5128 
5129 
5130 // ES6 section 24.1.2.1 ArrayBuffer ( length ) for the [[Construct]] case.
BUILTIN(ArrayBufferConstructor_ConstructStub)5131 BUILTIN(ArrayBufferConstructor_ConstructStub) {
5132   HandleScope scope(isolate);
5133   Handle<JSFunction> target = args.target<JSFunction>();
5134   Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
5135   Handle<Object> length = args.atOrUndefined(isolate, 1);
5136   DCHECK(*target == target->native_context()->array_buffer_fun() ||
5137          *target == target->native_context()->shared_array_buffer_fun());
5138   Handle<Object> number_length;
5139   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, number_length,
5140                                      Object::ToInteger(isolate, length));
5141   if (number_length->Number() < 0.0) {
5142     THROW_NEW_ERROR_RETURN_FAILURE(
5143         isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferLength));
5144   }
5145   Handle<JSObject> result;
5146   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
5147                                      JSObject::New(target, new_target));
5148   size_t byte_length;
5149   if (!TryNumberToSize(isolate, *number_length, &byte_length)) {
5150     THROW_NEW_ERROR_RETURN_FAILURE(
5151         isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferLength));
5152   }
5153   SharedFlag shared_flag =
5154       (*target == target->native_context()->array_buffer_fun())
5155           ? SharedFlag::kNotShared
5156           : SharedFlag::kShared;
5157   if (!JSArrayBuffer::SetupAllocatingData(Handle<JSArrayBuffer>::cast(result),
5158                                           isolate, byte_length, true,
5159                                           shared_flag)) {
5160     THROW_NEW_ERROR_RETURN_FAILURE(
5161         isolate, NewRangeError(MessageTemplate::kArrayBufferAllocationFailed));
5162   }
5163   return *result;
5164 }
5165 
5166 
5167 // ES6 section 24.1.3.1 ArrayBuffer.isView ( arg )
BUILTIN(ArrayBufferIsView)5168 BUILTIN(ArrayBufferIsView) {
5169   SealHandleScope shs(isolate);
5170   DCHECK_EQ(2, args.length());
5171   Object* arg = args[1];
5172   return isolate->heap()->ToBoolean(arg->IsJSArrayBufferView());
5173 }
5174 
5175 
5176 // ES6 section 26.2.1.1 Proxy ( target, handler ) for the [[Call]] case.
BUILTIN(ProxyConstructor)5177 BUILTIN(ProxyConstructor) {
5178   HandleScope scope(isolate);
5179   THROW_NEW_ERROR_RETURN_FAILURE(
5180       isolate,
5181       NewTypeError(MessageTemplate::kConstructorNotFunction,
5182                    isolate->factory()->NewStringFromAsciiChecked("Proxy")));
5183 }
5184 
5185 
5186 // ES6 section 26.2.1.1 Proxy ( target, handler ) for the [[Construct]] case.
BUILTIN(ProxyConstructor_ConstructStub)5187 BUILTIN(ProxyConstructor_ConstructStub) {
5188   HandleScope scope(isolate);
5189   DCHECK(isolate->proxy_function()->IsConstructor());
5190   Handle<Object> target = args.atOrUndefined(isolate, 1);
5191   Handle<Object> handler = args.atOrUndefined(isolate, 2);
5192   RETURN_RESULT_OR_FAILURE(isolate, JSProxy::New(isolate, target, handler));
5193 }
5194 
5195 
5196 // -----------------------------------------------------------------------------
5197 // Throwers for restricted function properties and strict arguments object
5198 // properties
5199 
5200 
BUILTIN(RestrictedFunctionPropertiesThrower)5201 BUILTIN(RestrictedFunctionPropertiesThrower) {
5202   HandleScope scope(isolate);
5203   THROW_NEW_ERROR_RETURN_FAILURE(
5204       isolate, NewTypeError(MessageTemplate::kRestrictedFunctionProperties));
5205 }
5206 
5207 
BUILTIN(RestrictedStrictArgumentsPropertiesThrower)5208 BUILTIN(RestrictedStrictArgumentsPropertiesThrower) {
5209   HandleScope scope(isolate);
5210   THROW_NEW_ERROR_RETURN_FAILURE(
5211       isolate, NewTypeError(MessageTemplate::kStrictPoisonPill));
5212 }
5213 
5214 
5215 // -----------------------------------------------------------------------------
5216 //
5217 
5218 
5219 namespace {
5220 
5221 // Returns the holder JSObject if the function can legally be called with this
5222 // receiver.  Returns nullptr if the call is illegal.
5223 // TODO(dcarney): CallOptimization duplicates this logic, merge.
GetCompatibleReceiver(Isolate * isolate,FunctionTemplateInfo * info,JSObject * receiver)5224 JSObject* GetCompatibleReceiver(Isolate* isolate, FunctionTemplateInfo* info,
5225                                 JSObject* receiver) {
5226   Object* recv_type = info->signature();
5227   // No signature, return holder.
5228   if (!recv_type->IsFunctionTemplateInfo()) return receiver;
5229   FunctionTemplateInfo* signature = FunctionTemplateInfo::cast(recv_type);
5230 
5231   // Check the receiver. Fast path for receivers with no hidden prototypes.
5232   if (signature->IsTemplateFor(receiver)) return receiver;
5233   if (!receiver->map()->has_hidden_prototype()) return nullptr;
5234   for (PrototypeIterator iter(isolate, receiver, kStartAtPrototype,
5235                               PrototypeIterator::END_AT_NON_HIDDEN);
5236        !iter.IsAtEnd(); iter.Advance()) {
5237     JSObject* current = iter.GetCurrent<JSObject>();
5238     if (signature->IsTemplateFor(current)) return current;
5239   }
5240   return nullptr;
5241 }
5242 
5243 template <bool is_construct>
HandleApiCallHelper(Isolate * isolate,Handle<HeapObject> function,Handle<HeapObject> new_target,Handle<FunctionTemplateInfo> fun_data,Handle<Object> receiver,BuiltinArguments args)5244 MUST_USE_RESULT MaybeHandle<Object> HandleApiCallHelper(
5245     Isolate* isolate, Handle<HeapObject> function,
5246     Handle<HeapObject> new_target, Handle<FunctionTemplateInfo> fun_data,
5247     Handle<Object> receiver, BuiltinArguments args) {
5248   Handle<JSObject> js_receiver;
5249   JSObject* raw_holder;
5250   if (is_construct) {
5251     DCHECK(args.receiver()->IsTheHole(isolate));
5252     if (fun_data->instance_template()->IsUndefined(isolate)) {
5253       v8::Local<ObjectTemplate> templ =
5254           ObjectTemplate::New(reinterpret_cast<v8::Isolate*>(isolate),
5255                               ToApiHandle<v8::FunctionTemplate>(fun_data));
5256       fun_data->set_instance_template(*Utils::OpenHandle(*templ));
5257     }
5258     Handle<ObjectTemplateInfo> instance_template(
5259         ObjectTemplateInfo::cast(fun_data->instance_template()), isolate);
5260     ASSIGN_RETURN_ON_EXCEPTION(
5261         isolate, js_receiver,
5262         ApiNatives::InstantiateObject(instance_template,
5263                                       Handle<JSReceiver>::cast(new_target)),
5264         Object);
5265     args[0] = *js_receiver;
5266     DCHECK_EQ(*js_receiver, *args.receiver());
5267 
5268     raw_holder = *js_receiver;
5269   } else {
5270     DCHECK(receiver->IsJSReceiver());
5271 
5272     if (!receiver->IsJSObject()) {
5273       // This function cannot be called with the given receiver.  Abort!
5274       THROW_NEW_ERROR(
5275           isolate, NewTypeError(MessageTemplate::kIllegalInvocation), Object);
5276     }
5277 
5278     js_receiver = Handle<JSObject>::cast(receiver);
5279 
5280     if (!fun_data->accept_any_receiver() &&
5281         js_receiver->IsAccessCheckNeeded() &&
5282         !isolate->MayAccess(handle(isolate->context()), js_receiver)) {
5283       isolate->ReportFailedAccessCheck(js_receiver);
5284       RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5285     }
5286 
5287     raw_holder = GetCompatibleReceiver(isolate, *fun_data, *js_receiver);
5288 
5289     if (raw_holder == nullptr) {
5290       // This function cannot be called with the given receiver.  Abort!
5291       THROW_NEW_ERROR(
5292           isolate, NewTypeError(MessageTemplate::kIllegalInvocation), Object);
5293     }
5294   }
5295 
5296   Object* raw_call_data = fun_data->call_code();
5297   if (!raw_call_data->IsUndefined(isolate)) {
5298     DCHECK(raw_call_data->IsCallHandlerInfo());
5299     CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data);
5300     Object* callback_obj = call_data->callback();
5301     v8::FunctionCallback callback =
5302         v8::ToCData<v8::FunctionCallback>(callback_obj);
5303     Object* data_obj = call_data->data();
5304 
5305     LOG(isolate, ApiObjectAccess("call", JSObject::cast(*js_receiver)));
5306 
5307     FunctionCallbackArguments custom(isolate, data_obj, *function, raw_holder,
5308                                      *new_target, &args[0] - 1,
5309                                      args.length() - 1);
5310 
5311     Handle<Object> result = custom.Call(callback);
5312 
5313     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5314     if (result.is_null()) {
5315       if (is_construct) return js_receiver;
5316       return isolate->factory()->undefined_value();
5317     }
5318     // Rebox the result.
5319     result->VerifyApiCallResultType();
5320     if (!is_construct || result->IsJSObject()) return handle(*result, isolate);
5321   }
5322 
5323   return js_receiver;
5324 }
5325 
5326 }  // namespace
5327 
5328 
BUILTIN(HandleApiCall)5329 BUILTIN(HandleApiCall) {
5330   HandleScope scope(isolate);
5331   Handle<JSFunction> function = args.target<JSFunction>();
5332   Handle<Object> receiver = args.receiver();
5333   Handle<HeapObject> new_target = args.new_target();
5334   Handle<FunctionTemplateInfo> fun_data(function->shared()->get_api_func_data(),
5335                                         isolate);
5336   if (new_target->IsJSReceiver()) {
5337     RETURN_RESULT_OR_FAILURE(
5338         isolate, HandleApiCallHelper<true>(isolate, function, new_target,
5339                                            fun_data, receiver, args));
5340   } else {
5341     RETURN_RESULT_OR_FAILURE(
5342         isolate, HandleApiCallHelper<false>(isolate, function, new_target,
5343                                             fun_data, receiver, args));
5344   }
5345 }
5346 
5347 
CallFunction(ConvertReceiverMode mode,TailCallMode tail_call_mode)5348 Handle<Code> Builtins::CallFunction(ConvertReceiverMode mode,
5349                                     TailCallMode tail_call_mode) {
5350   switch (tail_call_mode) {
5351     case TailCallMode::kDisallow:
5352       switch (mode) {
5353         case ConvertReceiverMode::kNullOrUndefined:
5354           return CallFunction_ReceiverIsNullOrUndefined();
5355         case ConvertReceiverMode::kNotNullOrUndefined:
5356           return CallFunction_ReceiverIsNotNullOrUndefined();
5357         case ConvertReceiverMode::kAny:
5358           return CallFunction_ReceiverIsAny();
5359       }
5360       break;
5361     case TailCallMode::kAllow:
5362       switch (mode) {
5363         case ConvertReceiverMode::kNullOrUndefined:
5364           return TailCallFunction_ReceiverIsNullOrUndefined();
5365         case ConvertReceiverMode::kNotNullOrUndefined:
5366           return TailCallFunction_ReceiverIsNotNullOrUndefined();
5367         case ConvertReceiverMode::kAny:
5368           return TailCallFunction_ReceiverIsAny();
5369       }
5370       break;
5371   }
5372   UNREACHABLE();
5373   return Handle<Code>::null();
5374 }
5375 
Call(ConvertReceiverMode mode,TailCallMode tail_call_mode)5376 Handle<Code> Builtins::Call(ConvertReceiverMode mode,
5377                             TailCallMode tail_call_mode) {
5378   switch (tail_call_mode) {
5379     case TailCallMode::kDisallow:
5380       switch (mode) {
5381         case ConvertReceiverMode::kNullOrUndefined:
5382           return Call_ReceiverIsNullOrUndefined();
5383         case ConvertReceiverMode::kNotNullOrUndefined:
5384           return Call_ReceiverIsNotNullOrUndefined();
5385         case ConvertReceiverMode::kAny:
5386           return Call_ReceiverIsAny();
5387       }
5388       break;
5389     case TailCallMode::kAllow:
5390       switch (mode) {
5391         case ConvertReceiverMode::kNullOrUndefined:
5392           return TailCall_ReceiverIsNullOrUndefined();
5393         case ConvertReceiverMode::kNotNullOrUndefined:
5394           return TailCall_ReceiverIsNotNullOrUndefined();
5395         case ConvertReceiverMode::kAny:
5396           return TailCall_ReceiverIsAny();
5397       }
5398       break;
5399   }
5400   UNREACHABLE();
5401   return Handle<Code>::null();
5402 }
5403 
CallBoundFunction(TailCallMode tail_call_mode)5404 Handle<Code> Builtins::CallBoundFunction(TailCallMode tail_call_mode) {
5405   switch (tail_call_mode) {
5406     case TailCallMode::kDisallow:
5407       return CallBoundFunction();
5408     case TailCallMode::kAllow:
5409       return TailCallBoundFunction();
5410   }
5411   UNREACHABLE();
5412   return Handle<Code>::null();
5413 }
5414 
InterpreterPushArgsAndCall(TailCallMode tail_call_mode)5415 Handle<Code> Builtins::InterpreterPushArgsAndCall(TailCallMode tail_call_mode) {
5416   switch (tail_call_mode) {
5417     case TailCallMode::kDisallow:
5418       return InterpreterPushArgsAndCall();
5419     case TailCallMode::kAllow:
5420       return InterpreterPushArgsAndTailCall();
5421   }
5422   UNREACHABLE();
5423   return Handle<Code>::null();
5424 }
5425 
5426 namespace {
5427 
5428 class RelocatableArguments : public BuiltinArguments, public Relocatable {
5429  public:
RelocatableArguments(Isolate * isolate,int length,Object ** arguments)5430   RelocatableArguments(Isolate* isolate, int length, Object** arguments)
5431       : BuiltinArguments(length, arguments), Relocatable(isolate) {}
5432 
IterateInstance(ObjectVisitor * v)5433   virtual inline void IterateInstance(ObjectVisitor* v) {
5434     if (length() == 0) return;
5435     v->VisitPointers(lowest_address(), highest_address() + 1);
5436   }
5437 
5438  private:
5439   DISALLOW_COPY_AND_ASSIGN(RelocatableArguments);
5440 };
5441 
5442 }  // namespace
5443 
InvokeApiFunction(Isolate * isolate,Handle<HeapObject> function,Handle<Object> receiver,int argc,Handle<Object> args[])5444 MaybeHandle<Object> Builtins::InvokeApiFunction(Isolate* isolate,
5445                                                 Handle<HeapObject> function,
5446                                                 Handle<Object> receiver,
5447                                                 int argc,
5448                                                 Handle<Object> args[]) {
5449   DCHECK(function->IsFunctionTemplateInfo() ||
5450          (function->IsJSFunction() &&
5451           JSFunction::cast(*function)->shared()->IsApiFunction()));
5452 
5453   // Do proper receiver conversion for non-strict mode api functions.
5454   if (!receiver->IsJSReceiver()) {
5455     if (function->IsFunctionTemplateInfo() ||
5456         is_sloppy(JSFunction::cast(*function)->shared()->language_mode())) {
5457       ASSIGN_RETURN_ON_EXCEPTION(isolate, receiver,
5458                                  Object::ConvertReceiver(isolate, receiver),
5459                                  Object);
5460     }
5461   }
5462 
5463   Handle<FunctionTemplateInfo> fun_data =
5464       function->IsFunctionTemplateInfo()
5465           ? Handle<FunctionTemplateInfo>::cast(function)
5466           : handle(JSFunction::cast(*function)->shared()->get_api_func_data(),
5467                    isolate);
5468   Handle<HeapObject> new_target = isolate->factory()->undefined_value();
5469   // Construct BuiltinArguments object:
5470   // new target, function, arguments reversed, receiver.
5471   const int kBufferSize = 32;
5472   Object* small_argv[kBufferSize];
5473   Object** argv;
5474   if (argc + 3 <= kBufferSize) {
5475     argv = small_argv;
5476   } else {
5477     argv = new Object*[argc + 3];
5478   }
5479   argv[argc + 2] = *receiver;
5480   for (int i = 0; i < argc; ++i) {
5481     argv[argc - i + 1] = *args[i];
5482   }
5483   argv[1] = *function;
5484   argv[0] = *new_target;
5485   MaybeHandle<Object> result;
5486   {
5487     RelocatableArguments arguments(isolate, argc + 3, &argv[argc] + 2);
5488     result = HandleApiCallHelper<false>(isolate, function, new_target, fun_data,
5489                                         receiver, arguments);
5490   }
5491   if (argv != small_argv) delete[] argv;
5492   return result;
5493 }
5494 
5495 
5496 // Helper function to handle calls to non-function objects created through the
5497 // API. The object can be called as either a constructor (using new) or just as
5498 // a function (without new).
HandleApiCallAsFunctionOrConstructor(Isolate * isolate,bool is_construct_call,BuiltinArguments args)5499 MUST_USE_RESULT static Object* HandleApiCallAsFunctionOrConstructor(
5500     Isolate* isolate, bool is_construct_call, BuiltinArguments args) {
5501   Handle<Object> receiver = args.receiver();
5502 
5503   // Get the object called.
5504   JSObject* obj = JSObject::cast(*receiver);
5505 
5506   // Set the new target.
5507   HeapObject* new_target;
5508   if (is_construct_call) {
5509     // TODO(adamk): This should be passed through in args instead of
5510     // being patched in here. We need to set a non-undefined value
5511     // for v8::FunctionCallbackInfo::IsConstructCall() to get the
5512     // right answer.
5513     new_target = obj;
5514   } else {
5515     new_target = isolate->heap()->undefined_value();
5516   }
5517 
5518   // Get the invocation callback from the function descriptor that was
5519   // used to create the called object.
5520   DCHECK(obj->map()->is_callable());
5521   JSFunction* constructor = JSFunction::cast(obj->map()->GetConstructor());
5522   // TODO(ishell): turn this back to a DCHECK.
5523   CHECK(constructor->shared()->IsApiFunction());
5524   Object* handler =
5525       constructor->shared()->get_api_func_data()->instance_call_handler();
5526   DCHECK(!handler->IsUndefined(isolate));
5527   // TODO(ishell): remove this debugging code.
5528   CHECK(handler->IsCallHandlerInfo());
5529   CallHandlerInfo* call_data = CallHandlerInfo::cast(handler);
5530   Object* callback_obj = call_data->callback();
5531   v8::FunctionCallback callback =
5532       v8::ToCData<v8::FunctionCallback>(callback_obj);
5533 
5534   // Get the data for the call and perform the callback.
5535   Object* result;
5536   {
5537     HandleScope scope(isolate);
5538     LOG(isolate, ApiObjectAccess("call non-function", obj));
5539 
5540     FunctionCallbackArguments custom(isolate, call_data->data(), constructor,
5541                                      obj, new_target, &args[0] - 1,
5542                                      args.length() - 1);
5543     Handle<Object> result_handle = custom.Call(callback);
5544     if (result_handle.is_null()) {
5545       result = isolate->heap()->undefined_value();
5546     } else {
5547       result = *result_handle;
5548     }
5549   }
5550   // Check for exceptions and return result.
5551   RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
5552   return result;
5553 }
5554 
5555 
5556 // Handle calls to non-function objects created through the API. This delegate
5557 // function is used when the call is a normal function call.
BUILTIN(HandleApiCallAsFunction)5558 BUILTIN(HandleApiCallAsFunction) {
5559   return HandleApiCallAsFunctionOrConstructor(isolate, false, args);
5560 }
5561 
5562 
5563 // Handle calls to non-function objects created through the API. This delegate
5564 // function is used when the call is a construct call.
BUILTIN(HandleApiCallAsConstructor)5565 BUILTIN(HandleApiCallAsConstructor) {
5566   return HandleApiCallAsFunctionOrConstructor(isolate, true, args);
5567 }
5568 
5569 namespace {
5570 
Generate_LoadIC_Miss(CodeStubAssembler * assembler)5571 void Generate_LoadIC_Miss(CodeStubAssembler* assembler) {
5572   typedef compiler::Node Node;
5573 
5574   Node* receiver = assembler->Parameter(0);
5575   Node* name = assembler->Parameter(1);
5576   Node* slot = assembler->Parameter(2);
5577   Node* vector = assembler->Parameter(3);
5578   Node* context = assembler->Parameter(4);
5579 
5580   assembler->TailCallRuntime(Runtime::kLoadIC_Miss, context, receiver, name,
5581                              slot, vector);
5582 }
5583 
Generate_LoadGlobalIC_Miss(CodeStubAssembler * assembler)5584 void Generate_LoadGlobalIC_Miss(CodeStubAssembler* assembler) {
5585   typedef compiler::Node Node;
5586 
5587   Node* slot = assembler->Parameter(0);
5588   Node* vector = assembler->Parameter(1);
5589   Node* context = assembler->Parameter(2);
5590 
5591   assembler->TailCallRuntime(Runtime::kLoadGlobalIC_Miss, context, slot,
5592                              vector);
5593 }
5594 
Generate_LoadIC_Normal(MacroAssembler * masm)5595 void Generate_LoadIC_Normal(MacroAssembler* masm) {
5596   LoadIC::GenerateNormal(masm);
5597 }
5598 
Generate_LoadIC_Getter_ForDeopt(MacroAssembler * masm)5599 void Generate_LoadIC_Getter_ForDeopt(MacroAssembler* masm) {
5600   NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(masm);
5601 }
5602 
Generate_LoadIC_Slow(CodeStubAssembler * assembler)5603 void Generate_LoadIC_Slow(CodeStubAssembler* assembler) {
5604   typedef compiler::Node Node;
5605 
5606   Node* receiver = assembler->Parameter(0);
5607   Node* name = assembler->Parameter(1);
5608   // Node* slot = assembler->Parameter(2);
5609   // Node* vector = assembler->Parameter(3);
5610   Node* context = assembler->Parameter(4);
5611 
5612   assembler->TailCallRuntime(Runtime::kGetProperty, context, receiver, name);
5613 }
5614 
Generate_LoadGlobalIC_Slow(CodeStubAssembler * assembler)5615 void Generate_LoadGlobalIC_Slow(CodeStubAssembler* assembler) {
5616   typedef compiler::Node Node;
5617 
5618   Node* slot = assembler->Parameter(0);
5619   Node* vector = assembler->Parameter(1);
5620   Node* context = assembler->Parameter(2);
5621 
5622   assembler->TailCallRuntime(Runtime::kLoadGlobalIC_Slow, context, slot,
5623                              vector);
5624 }
5625 
Generate_KeyedLoadIC_Slow(MacroAssembler * masm)5626 void Generate_KeyedLoadIC_Slow(MacroAssembler* masm) {
5627   KeyedLoadIC::GenerateRuntimeGetProperty(masm);
5628 }
5629 
Generate_KeyedLoadIC_Miss(MacroAssembler * masm)5630 void Generate_KeyedLoadIC_Miss(MacroAssembler* masm) {
5631   KeyedLoadIC::GenerateMiss(masm);
5632 }
5633 
Generate_KeyedLoadIC_Megamorphic(MacroAssembler * masm)5634 void Generate_KeyedLoadIC_Megamorphic(MacroAssembler* masm) {
5635   KeyedLoadIC::GenerateMegamorphic(masm);
5636 }
5637 
Generate_StoreIC_Miss(MacroAssembler * masm)5638 void Generate_StoreIC_Miss(MacroAssembler* masm) {
5639   StoreIC::GenerateMiss(masm);
5640 }
5641 
Generate_StoreIC_Normal(MacroAssembler * masm)5642 void Generate_StoreIC_Normal(MacroAssembler* masm) {
5643   StoreIC::GenerateNormal(masm);
5644 }
5645 
Generate_StoreIC_Slow(MacroAssembler * masm)5646 void Generate_StoreIC_Slow(MacroAssembler* masm) {
5647   NamedStoreHandlerCompiler::GenerateSlow(masm);
5648 }
5649 
Generate_KeyedStoreIC_Slow(MacroAssembler * masm)5650 void Generate_KeyedStoreIC_Slow(MacroAssembler* masm) {
5651   ElementHandlerCompiler::GenerateStoreSlow(masm);
5652 }
5653 
Generate_StoreIC_Setter_ForDeopt(MacroAssembler * masm)5654 void Generate_StoreIC_Setter_ForDeopt(MacroAssembler* masm) {
5655   NamedStoreHandlerCompiler::GenerateStoreViaSetterForDeopt(masm);
5656 }
5657 
Generate_KeyedStoreIC_Megamorphic(MacroAssembler * masm)5658 void Generate_KeyedStoreIC_Megamorphic(MacroAssembler* masm) {
5659   KeyedStoreIC::GenerateMegamorphic(masm, SLOPPY);
5660 }
5661 
Generate_KeyedStoreIC_Megamorphic_Strict(MacroAssembler * masm)5662 void Generate_KeyedStoreIC_Megamorphic_Strict(MacroAssembler* masm) {
5663   KeyedStoreIC::GenerateMegamorphic(masm, STRICT);
5664 }
5665 
Generate_KeyedStoreIC_Miss(MacroAssembler * masm)5666 void Generate_KeyedStoreIC_Miss(MacroAssembler* masm) {
5667   KeyedStoreIC::GenerateMiss(masm);
5668 }
5669 
Generate_Return_DebugBreak(MacroAssembler * masm)5670 void Generate_Return_DebugBreak(MacroAssembler* masm) {
5671   DebugCodegen::GenerateDebugBreakStub(masm,
5672                                        DebugCodegen::SAVE_RESULT_REGISTER);
5673 }
5674 
Generate_Slot_DebugBreak(MacroAssembler * masm)5675 void Generate_Slot_DebugBreak(MacroAssembler* masm) {
5676   DebugCodegen::GenerateDebugBreakStub(masm,
5677                                        DebugCodegen::IGNORE_RESULT_REGISTER);
5678 }
5679 
Generate_FrameDropper_LiveEdit(MacroAssembler * masm)5680 void Generate_FrameDropper_LiveEdit(MacroAssembler* masm) {
5681   DebugCodegen::GenerateFrameDropperLiveEdit(masm);
5682 }
5683 
5684 }  // namespace
5685 
Builtins()5686 Builtins::Builtins() : initialized_(false) {
5687   memset(builtins_, 0, sizeof(builtins_[0]) * builtin_count);
5688   memset(names_, 0, sizeof(names_[0]) * builtin_count);
5689 }
5690 
5691 
~Builtins()5692 Builtins::~Builtins() {
5693 }
5694 
5695 #define DEF_ENUM_C(name) FUNCTION_ADDR(Builtin_##name),
5696 Address const Builtins::c_functions_[cfunction_count] = {
5697   BUILTIN_LIST_C(DEF_ENUM_C)
5698 };
5699 #undef DEF_ENUM_C
5700 
5701 
5702 struct BuiltinDesc {
5703   Handle<Code> (*builder)(Isolate*, struct BuiltinDesc const*);
5704   byte* generator;
5705   byte* c_code;
5706   const char* s_name;  // name is only used for generating log information.
5707   int name;
5708   Code::Flags flags;
5709   int argc;
5710 };
5711 
5712 #define BUILTIN_FUNCTION_TABLE_INIT { V8_ONCE_INIT, {} }
5713 
5714 class BuiltinFunctionTable {
5715  public:
functions()5716   BuiltinDesc* functions() {
5717     base::CallOnce(&once_, &Builtins::InitBuiltinFunctionTable);
5718     return functions_;
5719   }
5720 
5721   base::OnceType once_;
5722   BuiltinDesc functions_[Builtins::builtin_count + 1];
5723 
5724   friend class Builtins;
5725 };
5726 
5727 namespace {
5728 
5729 BuiltinFunctionTable builtin_function_table = BUILTIN_FUNCTION_TABLE_INIT;
5730 
MacroAssemblerBuilder(Isolate * isolate,BuiltinDesc const * builtin_desc)5731 Handle<Code> MacroAssemblerBuilder(Isolate* isolate,
5732                                    BuiltinDesc const* builtin_desc) {
5733 // For now we generate builtin adaptor code into a stack-allocated
5734 // buffer, before copying it into individual code objects. Be careful
5735 // with alignment, some platforms don't like unaligned code.
5736 #ifdef DEBUG
5737   // We can generate a lot of debug code on Arm64.
5738   const size_t buffer_size = 32 * KB;
5739 #elif V8_TARGET_ARCH_PPC64
5740   // 8 KB is insufficient on PPC64 when FLAG_debug_code is on.
5741   const size_t buffer_size = 10 * KB;
5742 #else
5743   const size_t buffer_size = 8 * KB;
5744 #endif
5745   union {
5746     int force_alignment;
5747     byte buffer[buffer_size];  // NOLINT(runtime/arrays)
5748   } u;
5749 
5750   MacroAssembler masm(isolate, u.buffer, sizeof(u.buffer),
5751                       CodeObjectRequired::kYes);
5752   // Generate the code/adaptor.
5753   typedef void (*Generator)(MacroAssembler*, int);
5754   Generator g = FUNCTION_CAST<Generator>(builtin_desc->generator);
5755   // We pass all arguments to the generator, but it may not use all of
5756   // them.  This works because the first arguments are on top of the
5757   // stack.
5758   DCHECK(!masm.has_frame());
5759   g(&masm, builtin_desc->name);
5760   // Move the code into the object heap.
5761   CodeDesc desc;
5762   masm.GetCode(&desc);
5763   Code::Flags flags = builtin_desc->flags;
5764   return isolate->factory()->NewCode(desc, flags, masm.CodeObject());
5765 }
5766 
5767 // Builder for builtins implemented in TurboFan with JS linkage.
CodeStubAssemblerBuilderJS(Isolate * isolate,BuiltinDesc const * builtin_desc)5768 Handle<Code> CodeStubAssemblerBuilderJS(Isolate* isolate,
5769                                         BuiltinDesc const* builtin_desc) {
5770   Zone zone(isolate->allocator());
5771   CodeStubAssembler assembler(isolate, &zone, builtin_desc->argc,
5772                               builtin_desc->flags, builtin_desc->s_name);
5773   // Generate the code/adaptor.
5774   typedef void (*Generator)(CodeStubAssembler*);
5775   Generator g = FUNCTION_CAST<Generator>(builtin_desc->generator);
5776   g(&assembler);
5777   return assembler.GenerateCode();
5778 }
5779 
5780 // Builder for builtins implemented in TurboFan with CallStub linkage.
CodeStubAssemblerBuilderCS(Isolate * isolate,BuiltinDesc const * builtin_desc)5781 Handle<Code> CodeStubAssemblerBuilderCS(Isolate* isolate,
5782                                         BuiltinDesc const* builtin_desc) {
5783   Zone zone(isolate->allocator());
5784   // The interface descriptor with given key must be initialized at this point
5785   // and this construction just queries the details from the descriptors table.
5786   CallInterfaceDescriptor descriptor(
5787       isolate, static_cast<CallDescriptors::Key>(builtin_desc->argc));
5788   // Ensure descriptor is already initialized.
5789   DCHECK_NOT_NULL(descriptor.GetFunctionType());
5790   CodeStubAssembler assembler(isolate, &zone, descriptor, builtin_desc->flags,
5791                               builtin_desc->s_name);
5792   // Generate the code/adaptor.
5793   typedef void (*Generator)(CodeStubAssembler*);
5794   Generator g = FUNCTION_CAST<Generator>(builtin_desc->generator);
5795   g(&assembler);
5796   return assembler.GenerateCode();
5797 }
5798 
5799 }  // namespace
5800 
5801 // Define array of pointers to generators and C builtin functions.
5802 // We do this in a sort of roundabout way so that we can do the initialization
5803 // within the lexical scope of Builtins:: and within a context where
5804 // Code::Flags names a non-abstract type.
InitBuiltinFunctionTable()5805 void Builtins::InitBuiltinFunctionTable() {
5806   BuiltinDesc* functions = builtin_function_table.functions_;
5807   functions[builtin_count].builder = nullptr;
5808   functions[builtin_count].generator = nullptr;
5809   functions[builtin_count].c_code = nullptr;
5810   functions[builtin_count].s_name = nullptr;
5811   functions[builtin_count].name = builtin_count;
5812   functions[builtin_count].flags = static_cast<Code::Flags>(0);
5813   functions[builtin_count].argc = 0;
5814 
5815 #define DEF_FUNCTION_PTR_C(aname)                         \
5816   functions->builder = &MacroAssemblerBuilder;            \
5817   functions->generator = FUNCTION_ADDR(Generate_Adaptor); \
5818   functions->c_code = FUNCTION_ADDR(Builtin_##aname);     \
5819   functions->s_name = #aname;                             \
5820   functions->name = c_##aname;                            \
5821   functions->flags = Code::ComputeFlags(Code::BUILTIN);   \
5822   functions->argc = 0;                                    \
5823   ++functions;
5824 
5825 #define DEF_FUNCTION_PTR_A(aname, kind, extra)              \
5826   functions->builder = &MacroAssemblerBuilder;              \
5827   functions->generator = FUNCTION_ADDR(Generate_##aname);   \
5828   functions->c_code = NULL;                                 \
5829   functions->s_name = #aname;                               \
5830   functions->name = k##aname;                               \
5831   functions->flags = Code::ComputeFlags(Code::kind, extra); \
5832   functions->argc = 0;                                      \
5833   ++functions;
5834 
5835 #define DEF_FUNCTION_PTR_T(aname, aargc)                  \
5836   functions->builder = &CodeStubAssemblerBuilderJS;       \
5837   functions->generator = FUNCTION_ADDR(Generate_##aname); \
5838   functions->c_code = NULL;                               \
5839   functions->s_name = #aname;                             \
5840   functions->name = k##aname;                             \
5841   functions->flags = Code::ComputeFlags(Code::BUILTIN);   \
5842   functions->argc = aargc;                                \
5843   ++functions;
5844 
5845 #define DEF_FUNCTION_PTR_S(aname, kind, extra, interface_descriptor) \
5846   functions->builder = &CodeStubAssemblerBuilderCS;                  \
5847   functions->generator = FUNCTION_ADDR(Generate_##aname);            \
5848   functions->c_code = NULL;                                          \
5849   functions->s_name = #aname;                                        \
5850   functions->name = k##aname;                                        \
5851   functions->flags = Code::ComputeFlags(Code::kind, extra);          \
5852   functions->argc = CallDescriptors::interface_descriptor;           \
5853   ++functions;
5854 
5855 #define DEF_FUNCTION_PTR_H(aname, kind)                     \
5856   functions->builder = &MacroAssemblerBuilder;              \
5857   functions->generator = FUNCTION_ADDR(Generate_##aname);   \
5858   functions->c_code = NULL;                                 \
5859   functions->s_name = #aname;                               \
5860   functions->name = k##aname;                               \
5861   functions->flags = Code::ComputeHandlerFlags(Code::kind); \
5862   functions->argc = 0;                                      \
5863   ++functions;
5864 
5865   BUILTIN_LIST_C(DEF_FUNCTION_PTR_C)
5866   BUILTIN_LIST_A(DEF_FUNCTION_PTR_A)
5867   BUILTIN_LIST_T(DEF_FUNCTION_PTR_T)
5868   BUILTIN_LIST_S(DEF_FUNCTION_PTR_S)
5869   BUILTIN_LIST_H(DEF_FUNCTION_PTR_H)
5870   BUILTIN_LIST_DEBUG_A(DEF_FUNCTION_PTR_A)
5871 
5872 #undef DEF_FUNCTION_PTR_C
5873 #undef DEF_FUNCTION_PTR_A
5874 #undef DEF_FUNCTION_PTR_T
5875 #undef DEF_FUNCTION_PTR_S
5876 #undef DEF_FUNCTION_PTR_H
5877 }
5878 
5879 
SetUp(Isolate * isolate,bool create_heap_objects)5880 void Builtins::SetUp(Isolate* isolate, bool create_heap_objects) {
5881   DCHECK(!initialized_);
5882 
5883   // Create a scope for the handles in the builtins.
5884   HandleScope scope(isolate);
5885 
5886 #define INITIALIZE_CALL_DESCRIPTOR(name, kind, extra, interface_descriptor) \
5887   { interface_descriptor##Descriptor descriptor(isolate); }
5888   BUILTIN_LIST_S(INITIALIZE_CALL_DESCRIPTOR)
5889 #undef INITIALIZE_CALL_DESCRIPTOR
5890 
5891   const BuiltinDesc* functions = builtin_function_table.functions();
5892 
5893   // Traverse the list of builtins and generate an adaptor in a
5894   // separate code object for each one.
5895   for (int i = 0; i < builtin_count; i++) {
5896     if (create_heap_objects) {
5897       Handle<Code> code = (*functions[i].builder)(isolate, functions + i);
5898       // Log the event and add the code to the builtins array.
5899       PROFILE(isolate,
5900               CodeCreateEvent(CodeEventListener::BUILTIN_TAG,
5901                               AbstractCode::cast(*code), functions[i].s_name));
5902       builtins_[i] = *code;
5903       code->set_builtin_index(i);
5904 #ifdef ENABLE_DISASSEMBLER
5905       if (FLAG_print_builtin_code) {
5906         CodeTracer::Scope trace_scope(isolate->GetCodeTracer());
5907         OFStream os(trace_scope.file());
5908         os << "Builtin: " << functions[i].s_name << "\n";
5909         code->Disassemble(functions[i].s_name, os);
5910         os << "\n";
5911       }
5912 #endif
5913     } else {
5914       // Deserializing. The values will be filled in during IterateBuiltins.
5915       builtins_[i] = NULL;
5916     }
5917     names_[i] = functions[i].s_name;
5918   }
5919 
5920   // Mark as initialized.
5921   initialized_ = true;
5922 }
5923 
5924 
TearDown()5925 void Builtins::TearDown() {
5926   initialized_ = false;
5927 }
5928 
5929 
IterateBuiltins(ObjectVisitor * v)5930 void Builtins::IterateBuiltins(ObjectVisitor* v) {
5931   v->VisitPointers(&builtins_[0], &builtins_[0] + builtin_count);
5932 }
5933 
5934 
Lookup(byte * pc)5935 const char* Builtins::Lookup(byte* pc) {
5936   // may be called during initialization (disassembler!)
5937   if (initialized_) {
5938     for (int i = 0; i < builtin_count; i++) {
5939       Code* entry = Code::cast(builtins_[i]);
5940       if (entry->contains(pc)) {
5941         return names_[i];
5942       }
5943     }
5944   }
5945   return NULL;
5946 }
5947 
5948 
Generate_InterruptCheck(MacroAssembler * masm)5949 void Builtins::Generate_InterruptCheck(MacroAssembler* masm) {
5950   masm->TailCallRuntime(Runtime::kInterrupt);
5951 }
5952 
5953 
Generate_StackCheck(MacroAssembler * masm)5954 void Builtins::Generate_StackCheck(MacroAssembler* masm) {
5955   masm->TailCallRuntime(Runtime::kStackGuard);
5956 }
5957 
5958 namespace {
5959 
ValidateSharedTypedArray(CodeStubAssembler * a,compiler::Node * tagged,compiler::Node * context,compiler::Node ** out_instance_type,compiler::Node ** out_backing_store)5960 void ValidateSharedTypedArray(CodeStubAssembler* a, compiler::Node* tagged,
5961                               compiler::Node* context,
5962                               compiler::Node** out_instance_type,
5963                               compiler::Node** out_backing_store) {
5964   using namespace compiler;
5965   CodeStubAssembler::Label is_smi(a), not_smi(a), is_typed_array(a),
5966       not_typed_array(a), is_shared(a), not_shared(a), is_float_or_clamped(a),
5967       not_float_or_clamped(a), invalid(a);
5968 
5969   // Fail if it is not a heap object.
5970   a->Branch(a->WordIsSmi(tagged), &is_smi, &not_smi);
5971   a->Bind(&is_smi);
5972   a->Goto(&invalid);
5973 
5974   // Fail if the array's instance type is not JSTypedArray.
5975   a->Bind(&not_smi);
5976   a->Branch(a->WordEqual(a->LoadInstanceType(tagged),
5977                          a->Int32Constant(JS_TYPED_ARRAY_TYPE)),
5978             &is_typed_array, &not_typed_array);
5979   a->Bind(&not_typed_array);
5980   a->Goto(&invalid);
5981 
5982   // Fail if the array's JSArrayBuffer is not shared.
5983   a->Bind(&is_typed_array);
5984   Node* array_buffer = a->LoadObjectField(tagged, JSTypedArray::kBufferOffset);
5985   Node* is_buffer_shared = a->BitFieldDecode<JSArrayBuffer::IsShared>(
5986       a->LoadObjectField(array_buffer, JSArrayBuffer::kBitFieldSlot));
5987   a->Branch(is_buffer_shared, &is_shared, &not_shared);
5988   a->Bind(&not_shared);
5989   a->Goto(&invalid);
5990 
5991   // Fail if the array's element type is float32, float64 or clamped.
5992   a->Bind(&is_shared);
5993   Node* elements_instance_type = a->LoadInstanceType(
5994       a->LoadObjectField(tagged, JSObject::kElementsOffset));
5995   STATIC_ASSERT(FIXED_INT8_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE);
5996   STATIC_ASSERT(FIXED_INT16_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE);
5997   STATIC_ASSERT(FIXED_INT32_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE);
5998   STATIC_ASSERT(FIXED_UINT8_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE);
5999   STATIC_ASSERT(FIXED_UINT16_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE);
6000   STATIC_ASSERT(FIXED_UINT32_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE);
6001   a->Branch(a->Int32LessThan(elements_instance_type,
6002                              a->Int32Constant(FIXED_FLOAT32_ARRAY_TYPE)),
6003             &not_float_or_clamped, &is_float_or_clamped);
6004   a->Bind(&is_float_or_clamped);
6005   a->Goto(&invalid);
6006 
6007   a->Bind(&invalid);
6008   a->CallRuntime(Runtime::kThrowNotIntegerSharedTypedArrayError, context,
6009                  tagged);
6010   a->Return(a->UndefinedConstant());
6011 
6012   a->Bind(&not_float_or_clamped);
6013   *out_instance_type = elements_instance_type;
6014 
6015   Node* backing_store =
6016       a->LoadObjectField(array_buffer, JSArrayBuffer::kBackingStoreOffset);
6017   Node* byte_offset = a->ChangeUint32ToWord(a->TruncateTaggedToWord32(
6018       context,
6019       a->LoadObjectField(tagged, JSArrayBufferView::kByteOffsetOffset)));
6020   *out_backing_store = a->IntPtrAdd(backing_store, byte_offset);
6021 }
6022 
6023 // https://tc39.github.io/ecmascript_sharedmem/shmem.html#Atomics.ValidateAtomicAccess
ConvertTaggedAtomicIndexToWord32(CodeStubAssembler * a,compiler::Node * tagged,compiler::Node * context)6024 compiler::Node* ConvertTaggedAtomicIndexToWord32(CodeStubAssembler* a,
6025                                                  compiler::Node* tagged,
6026                                                  compiler::Node* context) {
6027   using namespace compiler;
6028   CodeStubAssembler::Variable var_result(a, MachineRepresentation::kWord32);
6029 
6030   Callable to_number = CodeFactory::ToNumber(a->isolate());
6031   Node* number_index = a->CallStub(to_number, context, tagged);
6032   CodeStubAssembler::Label done(a, &var_result);
6033 
6034   CodeStubAssembler::Label if_numberissmi(a), if_numberisnotsmi(a);
6035   a->Branch(a->WordIsSmi(number_index), &if_numberissmi, &if_numberisnotsmi);
6036 
6037   a->Bind(&if_numberissmi);
6038   {
6039     var_result.Bind(a->SmiToWord32(number_index));
6040     a->Goto(&done);
6041   }
6042 
6043   a->Bind(&if_numberisnotsmi);
6044   {
6045     Node* number_index_value = a->LoadHeapNumberValue(number_index);
6046     Node* access_index = a->TruncateFloat64ToWord32(number_index_value);
6047     Node* test_index = a->ChangeInt32ToFloat64(access_index);
6048 
6049     CodeStubAssembler::Label if_indexesareequal(a), if_indexesarenotequal(a);
6050     a->Branch(a->Float64Equal(number_index_value, test_index),
6051               &if_indexesareequal, &if_indexesarenotequal);
6052 
6053     a->Bind(&if_indexesareequal);
6054     {
6055       var_result.Bind(access_index);
6056       a->Goto(&done);
6057     }
6058 
6059     a->Bind(&if_indexesarenotequal);
6060     a->Return(
6061         a->CallRuntime(Runtime::kThrowInvalidAtomicAccessIndexError, context));
6062   }
6063 
6064   a->Bind(&done);
6065   return var_result.value();
6066 }
6067 
ValidateAtomicIndex(CodeStubAssembler * a,compiler::Node * index_word,compiler::Node * array_length_word,compiler::Node * context)6068 void ValidateAtomicIndex(CodeStubAssembler* a, compiler::Node* index_word,
6069                          compiler::Node* array_length_word,
6070                          compiler::Node* context) {
6071   using namespace compiler;
6072   // Check if the index is in bounds. If not, throw RangeError.
6073   CodeStubAssembler::Label if_inbounds(a), if_notinbounds(a);
6074   a->Branch(
6075       a->WordOr(a->Int32LessThan(index_word, a->Int32Constant(0)),
6076                 a->Int32GreaterThanOrEqual(index_word, array_length_word)),
6077       &if_notinbounds, &if_inbounds);
6078   a->Bind(&if_notinbounds);
6079   a->Return(
6080       a->CallRuntime(Runtime::kThrowInvalidAtomicAccessIndexError, context));
6081   a->Bind(&if_inbounds);
6082 }
6083 
6084 }  // anonymous namespace
6085 
Generate_AtomicsLoad(CodeStubAssembler * a)6086 void Builtins::Generate_AtomicsLoad(CodeStubAssembler* a) {
6087   using namespace compiler;
6088   Node* array = a->Parameter(1);
6089   Node* index = a->Parameter(2);
6090   Node* context = a->Parameter(3 + 2);
6091 
6092   Node* instance_type;
6093   Node* backing_store;
6094   ValidateSharedTypedArray(a, array, context, &instance_type, &backing_store);
6095 
6096   Node* index_word32 = ConvertTaggedAtomicIndexToWord32(a, index, context);
6097   Node* array_length_word32 = a->TruncateTaggedToWord32(
6098       context, a->LoadObjectField(array, JSTypedArray::kLengthOffset));
6099   ValidateAtomicIndex(a, index_word32, array_length_word32, context);
6100   Node* index_word = a->ChangeUint32ToWord(index_word32);
6101 
6102   CodeStubAssembler::Label i8(a), u8(a), i16(a), u16(a), i32(a), u32(a),
6103       other(a);
6104   int32_t case_values[] = {
6105       FIXED_INT8_ARRAY_TYPE,   FIXED_UINT8_ARRAY_TYPE, FIXED_INT16_ARRAY_TYPE,
6106       FIXED_UINT16_ARRAY_TYPE, FIXED_INT32_ARRAY_TYPE, FIXED_UINT32_ARRAY_TYPE,
6107   };
6108   CodeStubAssembler::Label* case_labels[] = {
6109       &i8, &u8, &i16, &u16, &i32, &u32,
6110   };
6111   a->Switch(instance_type, &other, case_values, case_labels,
6112             arraysize(case_labels));
6113 
6114   a->Bind(&i8);
6115   a->Return(
6116       a->SmiTag(a->AtomicLoad(MachineType::Int8(), backing_store, index_word)));
6117 
6118   a->Bind(&u8);
6119   a->Return(a->SmiTag(
6120       a->AtomicLoad(MachineType::Uint8(), backing_store, index_word)));
6121 
6122   a->Bind(&i16);
6123   a->Return(a->SmiTag(a->AtomicLoad(MachineType::Int16(), backing_store,
6124                                     a->WordShl(index_word, 1))));
6125 
6126   a->Bind(&u16);
6127   a->Return(a->SmiTag(a->AtomicLoad(MachineType::Uint16(), backing_store,
6128                                     a->WordShl(index_word, 1))));
6129 
6130   a->Bind(&i32);
6131   a->Return(a->ChangeInt32ToTagged(a->AtomicLoad(
6132       MachineType::Int32(), backing_store, a->WordShl(index_word, 2))));
6133 
6134   a->Bind(&u32);
6135   a->Return(a->ChangeUint32ToTagged(a->AtomicLoad(
6136       MachineType::Uint32(), backing_store, a->WordShl(index_word, 2))));
6137 
6138   // This shouldn't happen, we've already validated the type.
6139   a->Bind(&other);
6140   a->Return(a->Int32Constant(0));
6141 }
6142 
Generate_AtomicsStore(CodeStubAssembler * a)6143 void Builtins::Generate_AtomicsStore(CodeStubAssembler* a) {
6144   using namespace compiler;
6145   Node* array = a->Parameter(1);
6146   Node* index = a->Parameter(2);
6147   Node* value = a->Parameter(3);
6148   Node* context = a->Parameter(4 + 2);
6149 
6150   Node* instance_type;
6151   Node* backing_store;
6152   ValidateSharedTypedArray(a, array, context, &instance_type, &backing_store);
6153 
6154   Node* index_word32 = ConvertTaggedAtomicIndexToWord32(a, index, context);
6155   Node* array_length_word32 = a->TruncateTaggedToWord32(
6156       context, a->LoadObjectField(array, JSTypedArray::kLengthOffset));
6157   ValidateAtomicIndex(a, index_word32, array_length_word32, context);
6158   Node* index_word = a->ChangeUint32ToWord(index_word32);
6159 
6160   Callable to_integer = CodeFactory::ToInteger(a->isolate());
6161   Node* value_integer = a->CallStub(to_integer, context, value);
6162   Node* value_word32 = a->TruncateTaggedToWord32(context, value_integer);
6163 
6164   CodeStubAssembler::Label u8(a), u16(a), u32(a), other(a);
6165   int32_t case_values[] = {
6166       FIXED_INT8_ARRAY_TYPE,   FIXED_UINT8_ARRAY_TYPE, FIXED_INT16_ARRAY_TYPE,
6167       FIXED_UINT16_ARRAY_TYPE, FIXED_INT32_ARRAY_TYPE, FIXED_UINT32_ARRAY_TYPE,
6168   };
6169   CodeStubAssembler::Label* case_labels[] = {
6170       &u8, &u8, &u16, &u16, &u32, &u32,
6171   };
6172   a->Switch(instance_type, &other, case_values, case_labels,
6173             arraysize(case_labels));
6174 
6175   a->Bind(&u8);
6176   a->AtomicStore(MachineRepresentation::kWord8, backing_store, index_word,
6177                  value_word32);
6178   a->Return(value_integer);
6179 
6180   a->Bind(&u16);
6181   a->SmiTag(a->AtomicStore(MachineRepresentation::kWord16, backing_store,
6182                            a->WordShl(index_word, 1), value_word32));
6183   a->Return(value_integer);
6184 
6185   a->Bind(&u32);
6186   a->AtomicStore(MachineRepresentation::kWord32, backing_store,
6187                  a->WordShl(index_word, 2), value_word32);
6188   a->Return(value_integer);
6189 
6190   // This shouldn't happen, we've already validated the type.
6191   a->Bind(&other);
6192   a->Return(a->Int32Constant(0));
6193 }
6194 
6195 #define DEFINE_BUILTIN_ACCESSOR_C(name)                                       \
6196   Handle<Code> Builtins::name() {                                             \
6197     Code** code_address = reinterpret_cast<Code**>(builtin_address(k##name)); \
6198     return Handle<Code>(code_address);                                        \
6199   }
6200 #define DEFINE_BUILTIN_ACCESSOR_A(name, kind, extra)                          \
6201   Handle<Code> Builtins::name() {                                             \
6202     Code** code_address = reinterpret_cast<Code**>(builtin_address(k##name)); \
6203     return Handle<Code>(code_address);                                        \
6204   }
6205 #define DEFINE_BUILTIN_ACCESSOR_T(name, argc)                                 \
6206   Handle<Code> Builtins::name() {                                             \
6207     Code** code_address = reinterpret_cast<Code**>(builtin_address(k##name)); \
6208     return Handle<Code>(code_address);                                        \
6209   }
6210 #define DEFINE_BUILTIN_ACCESSOR_S(name, kind, extra, interface_descriptor)    \
6211   Handle<Code> Builtins::name() {                                             \
6212     Code** code_address = reinterpret_cast<Code**>(builtin_address(k##name)); \
6213     return Handle<Code>(code_address);                                        \
6214   }
6215 #define DEFINE_BUILTIN_ACCESSOR_H(name, kind)               \
6216 Handle<Code> Builtins::name() {                             \
6217   Code** code_address =                                     \
6218       reinterpret_cast<Code**>(builtin_address(k##name));   \
6219   return Handle<Code>(code_address);                        \
6220 }
6221 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C)
6222 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A)
6223 BUILTIN_LIST_T(DEFINE_BUILTIN_ACCESSOR_T)
6224 BUILTIN_LIST_S(DEFINE_BUILTIN_ACCESSOR_S)
6225 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H)
6226 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A)
6227 #undef DEFINE_BUILTIN_ACCESSOR_C
6228 #undef DEFINE_BUILTIN_ACCESSOR_A
6229 #undef DEFINE_BUILTIN_ACCESSOR_T
6230 #undef DEFINE_BUILTIN_ACCESSOR_S
6231 #undef DEFINE_BUILTIN_ACCESSOR_H
6232 
6233 }  // namespace internal
6234 }  // namespace v8
6235