Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: src/builtins.cc

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

Powered by Google App Engine
This is Rietveld 408576698