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

Side by Side Diff: src/builtins/builtins.cc

Issue 2165593002: [builtins] Move builtins into own files (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Remove builtins-error.cc from BUILD.gn 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/builtins.h ('k') | src/builtins/builtins-arraybuffer.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/builtins/builtins.h" 5 #include "src/builtins/builtins.h"
6 #include "src/builtins/builtins-utils.h" 6 #include "src/builtins/builtins-utils.h"
7 7
8 #include "src/api-arguments.h" 8 #include "src/api-arguments.h"
9 #include "src/api-natives.h" 9 #include "src/api-natives.h"
10 #include "src/base/ieee754.h"
11 #include "src/base/once.h"
12 #include "src/bootstrapper.h"
13 #include "src/code-factory.h" 10 #include "src/code-factory.h"
14 #include "src/dateparser-inl.h"
15 #include "src/frames-inl.h"
16 #include "src/gdb-jit.h"
17 #include "src/globals.h"
18 #include "src/ic/handler-compiler.h" 11 #include "src/ic/handler-compiler.h"
19 #include "src/ic/ic.h" 12 #include "src/ic/ic.h"
20 #include "src/isolate-inl.h"
21 #include "src/json-parser.h"
22 #include "src/json-stringifier.h"
23 #include "src/messages.h"
24 #include "src/property-descriptor.h"
25 #include "src/prototype.h"
26 #include "src/string-builder.h"
27 #include "src/uri.h"
28 #include "src/vm-state-inl.h" 13 #include "src/vm-state-inl.h"
29 14
30 namespace v8 { 15 namespace v8 {
31 namespace internal { 16 namespace internal {
32 17
33 // Forward declarations for C++ builtins. 18 // Forward declarations for C++ builtins.
34 #define FORWARD_DECLARE(Name) \ 19 #define FORWARD_DECLARE(Name) \
35 Object* Builtin_##Name(int argc, Object** args, Isolate* isolate); 20 Object* Builtin_##Name(int argc, Object** args, Isolate* isolate);
36 BUILTIN_LIST_C(FORWARD_DECLARE) 21 BUILTIN_LIST_C(FORWARD_DECLARE)
37 #undef FORWARD_DECLARE 22 #undef FORWARD_DECLARE
38 23
39 BUILTIN(Illegal) {
40 UNREACHABLE();
41 return isolate->heap()->undefined_value(); // Make compiler happy.
42 }
43
44 BUILTIN(EmptyFunction) { return isolate->heap()->undefined_value(); }
45
46
47 void Builtins::Generate_ObjectHasOwnProperty(CodeStubAssembler* assembler) {
48 typedef compiler::Node Node;
49 typedef CodeStubAssembler::Label Label;
50 typedef CodeStubAssembler::Variable Variable;
51
52 Node* object = assembler->Parameter(0);
53 Node* key = assembler->Parameter(1);
54 Node* context = assembler->Parameter(4);
55
56 Label call_runtime(assembler), return_true(assembler),
57 return_false(assembler);
58
59 // Smi receivers do not have own properties.
60 Label if_objectisnotsmi(assembler);
61 assembler->Branch(assembler->WordIsSmi(object), &return_false,
62 &if_objectisnotsmi);
63 assembler->Bind(&if_objectisnotsmi);
64
65 Node* map = assembler->LoadMap(object);
66 Node* instance_type = assembler->LoadMapInstanceType(map);
67
68 Variable var_index(assembler, MachineRepresentation::kWord32);
69
70 Label keyisindex(assembler), if_iskeyunique(assembler);
71 assembler->TryToName(key, &keyisindex, &var_index, &if_iskeyunique,
72 &call_runtime);
73
74 assembler->Bind(&if_iskeyunique);
75 assembler->TryHasOwnProperty(object, map, instance_type, key, &return_true,
76 &return_false, &call_runtime);
77
78 assembler->Bind(&keyisindex);
79 assembler->TryLookupElement(object, map, instance_type, var_index.value(),
80 &return_true, &return_false, &call_runtime);
81
82 assembler->Bind(&return_true);
83 assembler->Return(assembler->BooleanConstant(true));
84
85 assembler->Bind(&return_false);
86 assembler->Return(assembler->BooleanConstant(false));
87
88 assembler->Bind(&call_runtime);
89 assembler->Return(assembler->CallRuntime(Runtime::kObjectHasOwnProperty,
90 context, object, key));
91 }
92
93 namespace {
94
95 MUST_USE_RESULT Maybe<bool> FastAssign(Handle<JSReceiver> to,
96 Handle<Object> next_source) {
97 // Non-empty strings are the only non-JSReceivers that need to be handled
98 // explicitly by Object.assign.
99 if (!next_source->IsJSReceiver()) {
100 return Just(!next_source->IsString() ||
101 String::cast(*next_source)->length() == 0);
102 }
103
104 // If the target is deprecated, the object will be updated on first store. If
105 // the source for that store equals the target, this will invalidate the
106 // cached representation of the source. Preventively upgrade the target.
107 // Do this on each iteration since any property load could cause deprecation.
108 if (to->map()->is_deprecated()) {
109 JSObject::MigrateInstance(Handle<JSObject>::cast(to));
110 }
111
112 Isolate* isolate = to->GetIsolate();
113 Handle<Map> map(JSReceiver::cast(*next_source)->map(), isolate);
114
115 if (!map->IsJSObjectMap()) return Just(false);
116 if (!map->OnlyHasSimpleProperties()) return Just(false);
117
118 Handle<JSObject> from = Handle<JSObject>::cast(next_source);
119 if (from->elements() != isolate->heap()->empty_fixed_array()) {
120 return Just(false);
121 }
122
123 Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
124 int length = map->NumberOfOwnDescriptors();
125
126 bool stable = true;
127
128 for (int i = 0; i < length; i++) {
129 Handle<Name> next_key(descriptors->GetKey(i), isolate);
130 Handle<Object> prop_value;
131 // Directly decode from the descriptor array if |from| did not change shape.
132 if (stable) {
133 PropertyDetails details = descriptors->GetDetails(i);
134 if (!details.IsEnumerable()) continue;
135 if (details.kind() == kData) {
136 if (details.location() == kDescriptor) {
137 prop_value = handle(descriptors->GetValue(i), isolate);
138 } else {
139 Representation representation = details.representation();
140 FieldIndex index = FieldIndex::ForDescriptor(*map, i);
141 prop_value = JSObject::FastPropertyAt(from, representation, index);
142 }
143 } else {
144 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
145 isolate, prop_value, JSReceiver::GetProperty(from, next_key),
146 Nothing<bool>());
147 stable = from->map() == *map;
148 }
149 } else {
150 // If the map did change, do a slower lookup. We are still guaranteed that
151 // the object has a simple shape, and that the key is a name.
152 LookupIterator it(from, next_key, from,
153 LookupIterator::OWN_SKIP_INTERCEPTOR);
154 if (!it.IsFound()) continue;
155 DCHECK(it.state() == LookupIterator::DATA ||
156 it.state() == LookupIterator::ACCESSOR);
157 if (!it.IsEnumerable()) continue;
158 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
159 isolate, prop_value, Object::GetProperty(&it), Nothing<bool>());
160 }
161 LookupIterator it(to, next_key, to);
162 bool call_to_js = it.IsFound() && it.state() != LookupIterator::DATA;
163 Maybe<bool> result = Object::SetProperty(
164 &it, prop_value, STRICT, Object::CERTAINLY_NOT_STORE_FROM_KEYED);
165 if (result.IsNothing()) return result;
166 if (stable && call_to_js) stable = from->map() == *map;
167 }
168
169 return Just(true);
170 }
171
172 } // namespace
173
174 // ES6 19.1.2.1 Object.assign
175 BUILTIN(ObjectAssign) {
176 HandleScope scope(isolate);
177 Handle<Object> target = args.atOrUndefined(isolate, 1);
178
179 // 1. Let to be ? ToObject(target).
180 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, target,
181 Object::ToObject(isolate, target));
182 Handle<JSReceiver> to = Handle<JSReceiver>::cast(target);
183 // 2. If only one argument was passed, return to.
184 if (args.length() == 2) return *to;
185 // 3. Let sources be the List of argument values starting with the
186 // second argument.
187 // 4. For each element nextSource of sources, in ascending index order,
188 for (int i = 2; i < args.length(); ++i) {
189 Handle<Object> next_source = args.at<Object>(i);
190 Maybe<bool> fast_assign = FastAssign(to, next_source);
191 if (fast_assign.IsNothing()) return isolate->heap()->exception();
192 if (fast_assign.FromJust()) continue;
193 // 4a. If nextSource is undefined or null, let keys be an empty List.
194 // 4b. Else,
195 // 4b i. Let from be ToObject(nextSource).
196 // Only non-empty strings and JSReceivers have enumerable properties.
197 Handle<JSReceiver> from =
198 Object::ToObject(isolate, next_source).ToHandleChecked();
199 // 4b ii. Let keys be ? from.[[OwnPropertyKeys]]().
200 Handle<FixedArray> keys;
201 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
202 isolate, keys, KeyAccumulator::GetKeys(
203 from, KeyCollectionMode::kOwnOnly, ALL_PROPERTIES,
204 GetKeysConversion::kKeepNumbers));
205 // 4c. Repeat for each element nextKey of keys in List order,
206 for (int j = 0; j < keys->length(); ++j) {
207 Handle<Object> next_key(keys->get(j), isolate);
208 // 4c i. Let desc be ? from.[[GetOwnProperty]](nextKey).
209 PropertyDescriptor desc;
210 Maybe<bool> found =
211 JSReceiver::GetOwnPropertyDescriptor(isolate, from, next_key, &desc);
212 if (found.IsNothing()) return isolate->heap()->exception();
213 // 4c ii. If desc is not undefined and desc.[[Enumerable]] is true, then
214 if (found.FromJust() && desc.enumerable()) {
215 // 4c ii 1. Let propValue be ? Get(from, nextKey).
216 Handle<Object> prop_value;
217 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
218 isolate, prop_value,
219 Runtime::GetObjectProperty(isolate, from, next_key));
220 // 4c ii 2. Let status be ? Set(to, nextKey, propValue, true).
221 Handle<Object> status;
222 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
223 isolate, status, Runtime::SetObjectProperty(isolate, to, next_key,
224 prop_value, STRICT));
225 }
226 }
227 }
228 // 5. Return to.
229 return *to;
230 }
231
232 namespace { // anonymous namespace for ObjectProtoToString()
233
234 void IsString(CodeStubAssembler* assembler, compiler::Node* object,
235 CodeStubAssembler::Label* if_string,
236 CodeStubAssembler::Label* if_notstring) {
237 typedef compiler::Node Node;
238 typedef CodeStubAssembler::Label Label;
239
240 Label if_notsmi(assembler);
241 assembler->Branch(assembler->WordIsSmi(object), if_notstring, &if_notsmi);
242
243 assembler->Bind(&if_notsmi);
244 {
245 Node* instance_type = assembler->LoadInstanceType(object);
246
247 assembler->Branch(
248 assembler->Int32LessThan(
249 instance_type, assembler->Int32Constant(FIRST_NONSTRING_TYPE)),
250 if_string, if_notstring);
251 }
252 }
253
254 void ReturnToStringFormat(CodeStubAssembler* assembler, compiler::Node* context,
255 compiler::Node* string) {
256 typedef compiler::Node Node;
257
258 Node* lhs = assembler->HeapConstant(
259 assembler->factory()->NewStringFromStaticChars("[object "));
260 Node* rhs = assembler->HeapConstant(
261 assembler->factory()->NewStringFromStaticChars("]"));
262
263 Callable callable = CodeFactory::StringAdd(
264 assembler->isolate(), STRING_ADD_CHECK_NONE, NOT_TENURED);
265
266 assembler->Return(assembler->CallStub(
267 callable, context, assembler->CallStub(callable, context, lhs, string),
268 rhs));
269 }
270
271 void ReturnIfPrimitive(CodeStubAssembler* assembler,
272 compiler::Node* instance_type,
273 CodeStubAssembler::Label* return_string,
274 CodeStubAssembler::Label* return_boolean,
275 CodeStubAssembler::Label* return_number) {
276 assembler->GotoIf(
277 assembler->Int32LessThan(instance_type,
278 assembler->Int32Constant(FIRST_NONSTRING_TYPE)),
279 return_string);
280
281 assembler->GotoIf(assembler->Word32Equal(
282 instance_type, assembler->Int32Constant(ODDBALL_TYPE)),
283 return_boolean);
284
285 assembler->GotoIf(
286 assembler->Word32Equal(instance_type,
287 assembler->Int32Constant(HEAP_NUMBER_TYPE)),
288 return_number);
289 }
290
291 } // namespace
292
293 // ES6 section 19.1.3.6 Object.prototype.toString
294 void Builtins::Generate_ObjectProtoToString(CodeStubAssembler* assembler) {
295 typedef compiler::Node Node;
296 typedef CodeStubAssembler::Label Label;
297 typedef CodeStubAssembler::Variable Variable;
298
299 Label return_undefined(assembler, Label::kDeferred),
300 return_null(assembler, Label::kDeferred),
301 return_arguments(assembler, Label::kDeferred), return_array(assembler),
302 return_api(assembler, Label::kDeferred), return_object(assembler),
303 return_regexp(assembler), return_function(assembler),
304 return_error(assembler), return_date(assembler), return_string(assembler),
305 return_boolean(assembler), return_jsvalue(assembler),
306 return_jsproxy(assembler, Label::kDeferred), return_number(assembler);
307
308 Label if_isproxy(assembler, Label::kDeferred);
309
310 Label checkstringtag(assembler);
311 Label if_tostringtag(assembler), if_notostringtag(assembler);
312
313 Node* receiver = assembler->Parameter(0);
314 Node* context = assembler->Parameter(3);
315
316 assembler->GotoIf(
317 assembler->Word32Equal(receiver, assembler->UndefinedConstant()),
318 &return_undefined);
319
320 assembler->GotoIf(assembler->Word32Equal(receiver, assembler->NullConstant()),
321 &return_null);
322
323 assembler->GotoIf(assembler->WordIsSmi(receiver), &return_number);
324
325 Node* receiver_instance_type = assembler->LoadInstanceType(receiver);
326 ReturnIfPrimitive(assembler, receiver_instance_type, &return_string,
327 &return_boolean, &return_number);
328
329 // for proxies, check IsArray before getting @@toStringTag
330 Variable var_proxy_is_array(assembler, MachineRepresentation::kTagged);
331 var_proxy_is_array.Bind(assembler->BooleanConstant(false));
332
333 assembler->Branch(
334 assembler->Word32Equal(receiver_instance_type,
335 assembler->Int32Constant(JS_PROXY_TYPE)),
336 &if_isproxy, &checkstringtag);
337
338 assembler->Bind(&if_isproxy);
339 {
340 // This can throw
341 var_proxy_is_array.Bind(
342 assembler->CallRuntime(Runtime::kArrayIsArray, context, receiver));
343 assembler->Goto(&checkstringtag);
344 }
345
346 assembler->Bind(&checkstringtag);
347 {
348 Node* to_string_tag_symbol = assembler->HeapConstant(
349 assembler->isolate()->factory()->to_string_tag_symbol());
350
351 GetPropertyStub stub(assembler->isolate());
352 Callable get_property =
353 Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
354 Node* to_string_tag_value = assembler->CallStub(
355 get_property, context, receiver, to_string_tag_symbol);
356
357 IsString(assembler, to_string_tag_value, &if_tostringtag,
358 &if_notostringtag);
359
360 assembler->Bind(&if_tostringtag);
361 ReturnToStringFormat(assembler, context, to_string_tag_value);
362 }
363 assembler->Bind(&if_notostringtag);
364 {
365 size_t const kNumCases = 11;
366 Label* case_labels[kNumCases];
367 int32_t case_values[kNumCases];
368 case_labels[0] = &return_api;
369 case_values[0] = JS_API_OBJECT_TYPE;
370 case_labels[1] = &return_api;
371 case_values[1] = JS_SPECIAL_API_OBJECT_TYPE;
372 case_labels[2] = &return_arguments;
373 case_values[2] = JS_ARGUMENTS_TYPE;
374 case_labels[3] = &return_array;
375 case_values[3] = JS_ARRAY_TYPE;
376 case_labels[4] = &return_function;
377 case_values[4] = JS_BOUND_FUNCTION_TYPE;
378 case_labels[5] = &return_function;
379 case_values[5] = JS_FUNCTION_TYPE;
380 case_labels[6] = &return_error;
381 case_values[6] = JS_ERROR_TYPE;
382 case_labels[7] = &return_date;
383 case_values[7] = JS_DATE_TYPE;
384 case_labels[8] = &return_regexp;
385 case_values[8] = JS_REGEXP_TYPE;
386 case_labels[9] = &return_jsvalue;
387 case_values[9] = JS_VALUE_TYPE;
388 case_labels[10] = &return_jsproxy;
389 case_values[10] = JS_PROXY_TYPE;
390
391 assembler->Switch(receiver_instance_type, &return_object, case_values,
392 case_labels, arraysize(case_values));
393
394 assembler->Bind(&return_undefined);
395 assembler->Return(assembler->HeapConstant(
396 assembler->isolate()->factory()->undefined_to_string()));
397
398 assembler->Bind(&return_null);
399 assembler->Return(assembler->HeapConstant(
400 assembler->isolate()->factory()->null_to_string()));
401
402 assembler->Bind(&return_number);
403 assembler->Return(assembler->HeapConstant(
404 assembler->isolate()->factory()->number_to_string()));
405
406 assembler->Bind(&return_string);
407 assembler->Return(assembler->HeapConstant(
408 assembler->isolate()->factory()->string_to_string()));
409
410 assembler->Bind(&return_boolean);
411 assembler->Return(assembler->HeapConstant(
412 assembler->isolate()->factory()->boolean_to_string()));
413
414 assembler->Bind(&return_arguments);
415 assembler->Return(assembler->HeapConstant(
416 assembler->isolate()->factory()->arguments_to_string()));
417
418 assembler->Bind(&return_array);
419 assembler->Return(assembler->HeapConstant(
420 assembler->isolate()->factory()->array_to_string()));
421
422 assembler->Bind(&return_function);
423 assembler->Return(assembler->HeapConstant(
424 assembler->isolate()->factory()->function_to_string()));
425
426 assembler->Bind(&return_error);
427 assembler->Return(assembler->HeapConstant(
428 assembler->isolate()->factory()->error_to_string()));
429
430 assembler->Bind(&return_date);
431 assembler->Return(assembler->HeapConstant(
432 assembler->isolate()->factory()->date_to_string()));
433
434 assembler->Bind(&return_regexp);
435 assembler->Return(assembler->HeapConstant(
436 assembler->isolate()->factory()->regexp_to_string()));
437
438 assembler->Bind(&return_api);
439 {
440 Node* class_name =
441 assembler->CallRuntime(Runtime::kClassOf, context, receiver);
442 ReturnToStringFormat(assembler, context, class_name);
443 }
444
445 assembler->Bind(&return_jsvalue);
446 {
447 Node* value = assembler->LoadJSValueValue(receiver);
448 assembler->GotoIf(assembler->WordIsSmi(value), &return_number);
449
450 ReturnIfPrimitive(assembler, assembler->LoadInstanceType(value),
451 &return_string, &return_boolean, &return_number);
452 assembler->Goto(&return_object);
453 }
454
455 assembler->Bind(&return_jsproxy);
456 {
457 assembler->GotoIf(assembler->WordEqual(var_proxy_is_array.value(),
458 assembler->BooleanConstant(true)),
459 &return_array);
460
461 Node* map = assembler->LoadMap(receiver);
462
463 // Return object if the proxy {receiver} is not callable.
464 assembler->Branch(
465 assembler->Word32Equal(
466 assembler->Word32And(
467 assembler->LoadMapBitField(map),
468 assembler->Int32Constant(1 << Map::kIsCallable)),
469 assembler->Int32Constant(0)),
470 &return_object, &return_function);
471 }
472
473 // Default
474 assembler->Bind(&return_object);
475 assembler->Return(assembler->HeapConstant(
476 assembler->isolate()->factory()->object_to_string()));
477 }
478 }
479
480 // ES6 section 19.1.2.2 Object.create ( O [ , Properties ] )
481 // TODO(verwaest): Support the common cases with precached map directly in
482 // an Object.create stub.
483 BUILTIN(ObjectCreate) {
484 HandleScope scope(isolate);
485 Handle<Object> prototype = args.atOrUndefined(isolate, 1);
486 if (!prototype->IsNull(isolate) && !prototype->IsJSReceiver()) {
487 THROW_NEW_ERROR_RETURN_FAILURE(
488 isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, prototype));
489 }
490
491 // Generate the map with the specified {prototype} based on the Object
492 // function's initial map from the current native context.
493 // TODO(bmeurer): Use a dedicated cache for Object.create; think about
494 // slack tracking for Object.create.
495 Handle<Map> map(isolate->native_context()->object_function()->initial_map(),
496 isolate);
497 if (map->prototype() != *prototype) {
498 if (prototype->IsNull(isolate)) {
499 map = isolate->object_with_null_prototype_map();
500 } else if (prototype->IsJSObject()) {
501 Handle<JSObject> js_prototype = Handle<JSObject>::cast(prototype);
502 if (!js_prototype->map()->is_prototype_map()) {
503 JSObject::OptimizeAsPrototype(js_prototype, FAST_PROTOTYPE);
504 }
505 Handle<PrototypeInfo> info =
506 Map::GetOrCreatePrototypeInfo(js_prototype, isolate);
507 // TODO(verwaest): Use inobject slack tracking for this map.
508 if (info->HasObjectCreateMap()) {
509 map = handle(info->ObjectCreateMap(), isolate);
510 } else {
511 map = Map::CopyInitialMap(map);
512 Map::SetPrototype(map, prototype, FAST_PROTOTYPE);
513 PrototypeInfo::SetObjectCreateMap(info, map);
514 }
515 } else {
516 map = Map::TransitionToPrototype(map, prototype, REGULAR_PROTOTYPE);
517 }
518 }
519
520 // Actually allocate the object.
521 Handle<JSObject> object = isolate->factory()->NewJSObjectFromMap(map);
522
523 // Define the properties if properties was specified and is not undefined.
524 Handle<Object> properties = args.atOrUndefined(isolate, 2);
525 if (!properties->IsUndefined(isolate)) {
526 RETURN_FAILURE_ON_EXCEPTION(
527 isolate, JSReceiver::DefineProperties(isolate, object, properties));
528 }
529
530 return *object;
531 }
532
533 // ES6 section 19.1.2.3 Object.defineProperties
534 BUILTIN(ObjectDefineProperties) {
535 HandleScope scope(isolate);
536 DCHECK_EQ(3, args.length());
537 Handle<Object> target = args.at<Object>(1);
538 Handle<Object> properties = args.at<Object>(2);
539
540 RETURN_RESULT_OR_FAILURE(
541 isolate, JSReceiver::DefineProperties(isolate, target, properties));
542 }
543
544 // ES6 section 19.1.2.4 Object.defineProperty
545 BUILTIN(ObjectDefineProperty) {
546 HandleScope scope(isolate);
547 DCHECK_EQ(4, args.length());
548 Handle<Object> target = args.at<Object>(1);
549 Handle<Object> key = args.at<Object>(2);
550 Handle<Object> attributes = args.at<Object>(3);
551
552 return JSReceiver::DefineProperty(isolate, target, key, attributes);
553 }
554
555 namespace {
556
557 template <AccessorComponent which_accessor>
558 Object* ObjectDefineAccessor(Isolate* isolate, Handle<Object> object,
559 Handle<Object> name, Handle<Object> accessor) {
560 // 1. Let O be ? ToObject(this value).
561 Handle<JSReceiver> receiver;
562 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
563 Object::ConvertReceiver(isolate, object));
564 // 2. If IsCallable(getter) is false, throw a TypeError exception.
565 if (!accessor->IsCallable()) {
566 MessageTemplate::Template message =
567 which_accessor == ACCESSOR_GETTER
568 ? MessageTemplate::kObjectGetterExpectingFunction
569 : MessageTemplate::kObjectSetterExpectingFunction;
570 THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(message));
571 }
572 // 3. Let desc be PropertyDescriptor{[[Get]]: getter, [[Enumerable]]: true,
573 // [[Configurable]]: true}.
574 PropertyDescriptor desc;
575 if (which_accessor == ACCESSOR_GETTER) {
576 desc.set_get(accessor);
577 } else {
578 DCHECK(which_accessor == ACCESSOR_SETTER);
579 desc.set_set(accessor);
580 }
581 desc.set_enumerable(true);
582 desc.set_configurable(true);
583 // 4. Let key be ? ToPropertyKey(P).
584 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
585 Object::ToPropertyKey(isolate, name));
586 // 5. Perform ? DefinePropertyOrThrow(O, key, desc).
587 // To preserve legacy behavior, we ignore errors silently rather than
588 // throwing an exception.
589 Maybe<bool> success = JSReceiver::DefineOwnProperty(
590 isolate, receiver, name, &desc, Object::DONT_THROW);
591 MAYBE_RETURN(success, isolate->heap()->exception());
592 if (!success.FromJust()) {
593 isolate->CountUsage(v8::Isolate::kDefineGetterOrSetterWouldThrow);
594 }
595 // 6. Return undefined.
596 return isolate->heap()->undefined_value();
597 }
598
599 Object* ObjectLookupAccessor(Isolate* isolate, Handle<Object> object,
600 Handle<Object> key, AccessorComponent component) {
601 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, object,
602 Object::ConvertReceiver(isolate, object));
603 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key,
604 Object::ToPropertyKey(isolate, key));
605 bool success = false;
606 LookupIterator it = LookupIterator::PropertyOrElement(
607 isolate, object, key, &success,
608 LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
609 DCHECK(success);
610
611 for (; it.IsFound(); it.Next()) {
612 switch (it.state()) {
613 case LookupIterator::INTERCEPTOR:
614 case LookupIterator::NOT_FOUND:
615 case LookupIterator::TRANSITION:
616 UNREACHABLE();
617
618 case LookupIterator::ACCESS_CHECK:
619 if (it.HasAccess()) continue;
620 isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>());
621 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
622 return isolate->heap()->undefined_value();
623
624 case LookupIterator::JSPROXY:
625 return isolate->heap()->undefined_value();
626
627 case LookupIterator::INTEGER_INDEXED_EXOTIC:
628 return isolate->heap()->undefined_value();
629 case LookupIterator::DATA:
630 continue;
631 case LookupIterator::ACCESSOR: {
632 Handle<Object> maybe_pair = it.GetAccessors();
633 if (maybe_pair->IsAccessorPair()) {
634 return *AccessorPair::GetComponent(
635 Handle<AccessorPair>::cast(maybe_pair), component);
636 }
637 }
638 }
639 }
640
641 return isolate->heap()->undefined_value();
642 }
643
644 } // namespace
645
646 // ES6 B.2.2.2 a.k.a.
647 // https://tc39.github.io/ecma262/#sec-object.prototype.__defineGetter__
648 BUILTIN(ObjectDefineGetter) {
649 HandleScope scope(isolate);
650 Handle<Object> object = args.at<Object>(0); // Receiver.
651 Handle<Object> name = args.at<Object>(1);
652 Handle<Object> getter = args.at<Object>(2);
653 return ObjectDefineAccessor<ACCESSOR_GETTER>(isolate, object, name, getter);
654 }
655
656 // ES6 B.2.2.3 a.k.a.
657 // https://tc39.github.io/ecma262/#sec-object.prototype.__defineSetter__
658 BUILTIN(ObjectDefineSetter) {
659 HandleScope scope(isolate);
660 Handle<Object> object = args.at<Object>(0); // Receiver.
661 Handle<Object> name = args.at<Object>(1);
662 Handle<Object> setter = args.at<Object>(2);
663 return ObjectDefineAccessor<ACCESSOR_SETTER>(isolate, object, name, setter);
664 }
665
666 // ES6 B.2.2.4 a.k.a.
667 // https://tc39.github.io/ecma262/#sec-object.prototype.__lookupGetter__
668 BUILTIN(ObjectLookupGetter) {
669 HandleScope scope(isolate);
670 Handle<Object> object = args.at<Object>(0);
671 Handle<Object> name = args.at<Object>(1);
672 return ObjectLookupAccessor(isolate, object, name, ACCESSOR_GETTER);
673 }
674
675 // ES6 B.2.2.5 a.k.a.
676 // https://tc39.github.io/ecma262/#sec-object.prototype.__lookupSetter__
677 BUILTIN(ObjectLookupSetter) {
678 HandleScope scope(isolate);
679 Handle<Object> object = args.at<Object>(0);
680 Handle<Object> name = args.at<Object>(1);
681 return ObjectLookupAccessor(isolate, object, name, ACCESSOR_SETTER);
682 }
683
684 // ES6 section 19.1.2.5 Object.freeze ( O )
685 BUILTIN(ObjectFreeze) {
686 HandleScope scope(isolate);
687 Handle<Object> object = args.atOrUndefined(isolate, 1);
688 if (object->IsJSReceiver()) {
689 MAYBE_RETURN(JSReceiver::SetIntegrityLevel(Handle<JSReceiver>::cast(object),
690 FROZEN, Object::THROW_ON_ERROR),
691 isolate->heap()->exception());
692 }
693 return *object;
694 }
695
696 // ES section 19.1.2.9 Object.getPrototypeOf ( O )
697 BUILTIN(ObjectGetPrototypeOf) {
698 HandleScope scope(isolate);
699 Handle<Object> object = args.atOrUndefined(isolate, 1);
700
701 Handle<JSReceiver> receiver;
702 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
703 Object::ToObject(isolate, object));
704
705 RETURN_RESULT_OR_FAILURE(isolate,
706 JSReceiver::GetPrototype(isolate, receiver));
707 }
708
709 // ES6 section 19.1.2.6 Object.getOwnPropertyDescriptor ( O, P )
710 BUILTIN(ObjectGetOwnPropertyDescriptor) {
711 HandleScope scope(isolate);
712 // 1. Let obj be ? ToObject(O).
713 Handle<Object> object = args.atOrUndefined(isolate, 1);
714 Handle<JSReceiver> receiver;
715 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
716 Object::ToObject(isolate, object));
717 // 2. Let key be ? ToPropertyKey(P).
718 Handle<Object> property = args.atOrUndefined(isolate, 2);
719 Handle<Name> key;
720 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key,
721 Object::ToName(isolate, property));
722 // 3. Let desc be ? obj.[[GetOwnProperty]](key).
723 PropertyDescriptor desc;
724 Maybe<bool> found =
725 JSReceiver::GetOwnPropertyDescriptor(isolate, receiver, key, &desc);
726 MAYBE_RETURN(found, isolate->heap()->exception());
727 // 4. Return FromPropertyDescriptor(desc).
728 if (!found.FromJust()) return isolate->heap()->undefined_value();
729 return *desc.ToObject(isolate);
730 }
731
732 namespace {
733
734 Object* GetOwnPropertyKeys(Isolate* isolate, BuiltinArguments args,
735 PropertyFilter filter) {
736 HandleScope scope(isolate);
737 Handle<Object> object = args.atOrUndefined(isolate, 1);
738 Handle<JSReceiver> receiver;
739 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
740 Object::ToObject(isolate, object));
741 Handle<FixedArray> keys;
742 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
743 isolate, keys,
744 KeyAccumulator::GetKeys(receiver, KeyCollectionMode::kOwnOnly, filter,
745 GetKeysConversion::kConvertToString));
746 return *isolate->factory()->NewJSArrayWithElements(keys);
747 }
748
749 } // namespace
750
751 // ES6 section 19.1.2.7 Object.getOwnPropertyNames ( O )
752 BUILTIN(ObjectGetOwnPropertyNames) {
753 return GetOwnPropertyKeys(isolate, args, SKIP_SYMBOLS);
754 }
755
756 // ES6 section 19.1.2.8 Object.getOwnPropertySymbols ( O )
757 BUILTIN(ObjectGetOwnPropertySymbols) {
758 return GetOwnPropertyKeys(isolate, args, SKIP_STRINGS);
759 }
760
761 // ES#sec-object.is Object.is ( value1, value2 )
762 BUILTIN(ObjectIs) {
763 SealHandleScope shs(isolate);
764 DCHECK_EQ(3, args.length());
765 Handle<Object> value1 = args.at<Object>(1);
766 Handle<Object> value2 = args.at<Object>(2);
767 return isolate->heap()->ToBoolean(value1->SameValue(*value2));
768 }
769
770 // ES6 section 19.1.2.11 Object.isExtensible ( O )
771 BUILTIN(ObjectIsExtensible) {
772 HandleScope scope(isolate);
773 Handle<Object> object = args.atOrUndefined(isolate, 1);
774 Maybe<bool> result =
775 object->IsJSReceiver()
776 ? JSReceiver::IsExtensible(Handle<JSReceiver>::cast(object))
777 : Just(false);
778 MAYBE_RETURN(result, isolate->heap()->exception());
779 return isolate->heap()->ToBoolean(result.FromJust());
780 }
781
782 // ES6 section 19.1.2.12 Object.isFrozen ( O )
783 BUILTIN(ObjectIsFrozen) {
784 HandleScope scope(isolate);
785 Handle<Object> object = args.atOrUndefined(isolate, 1);
786 Maybe<bool> result = object->IsJSReceiver()
787 ? JSReceiver::TestIntegrityLevel(
788 Handle<JSReceiver>::cast(object), FROZEN)
789 : Just(true);
790 MAYBE_RETURN(result, isolate->heap()->exception());
791 return isolate->heap()->ToBoolean(result.FromJust());
792 }
793
794 // ES6 section 19.1.2.13 Object.isSealed ( O )
795 BUILTIN(ObjectIsSealed) {
796 HandleScope scope(isolate);
797 Handle<Object> object = args.atOrUndefined(isolate, 1);
798 Maybe<bool> result = object->IsJSReceiver()
799 ? JSReceiver::TestIntegrityLevel(
800 Handle<JSReceiver>::cast(object), SEALED)
801 : Just(true);
802 MAYBE_RETURN(result, isolate->heap()->exception());
803 return isolate->heap()->ToBoolean(result.FromJust());
804 }
805
806 // ES6 section 19.1.2.14 Object.keys ( O )
807 BUILTIN(ObjectKeys) {
808 HandleScope scope(isolate);
809 Handle<Object> object = args.atOrUndefined(isolate, 1);
810 Handle<JSReceiver> receiver;
811 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
812 Object::ToObject(isolate, object));
813
814 Handle<FixedArray> keys;
815 int enum_length = receiver->map()->EnumLength();
816 if (enum_length != kInvalidEnumCacheSentinel &&
817 JSObject::cast(*receiver)->elements() ==
818 isolate->heap()->empty_fixed_array()) {
819 DCHECK(receiver->IsJSObject());
820 DCHECK(!JSObject::cast(*receiver)->HasNamedInterceptor());
821 DCHECK(!JSObject::cast(*receiver)->IsAccessCheckNeeded());
822 DCHECK(!receiver->map()->has_hidden_prototype());
823 DCHECK(JSObject::cast(*receiver)->HasFastProperties());
824 if (enum_length == 0) {
825 keys = isolate->factory()->empty_fixed_array();
826 } else {
827 Handle<FixedArray> cache(
828 receiver->map()->instance_descriptors()->GetEnumCache());
829 keys = isolate->factory()->CopyFixedArrayUpTo(cache, enum_length);
830 }
831 } else {
832 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
833 isolate, keys,
834 KeyAccumulator::GetKeys(receiver, KeyCollectionMode::kOwnOnly,
835 ENUMERABLE_STRINGS,
836 GetKeysConversion::kConvertToString));
837 }
838 return *isolate->factory()->NewJSArrayWithElements(keys, FAST_ELEMENTS);
839 }
840
841 BUILTIN(ObjectValues) {
842 HandleScope scope(isolate);
843 Handle<Object> object = args.atOrUndefined(isolate, 1);
844 Handle<JSReceiver> receiver;
845 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
846 Object::ToObject(isolate, object));
847 Handle<FixedArray> values;
848 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
849 isolate, values, JSReceiver::GetOwnValues(receiver, ENUMERABLE_STRINGS));
850 return *isolate->factory()->NewJSArrayWithElements(values);
851 }
852
853 BUILTIN(ObjectEntries) {
854 HandleScope scope(isolate);
855 Handle<Object> object = args.atOrUndefined(isolate, 1);
856 Handle<JSReceiver> receiver;
857 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
858 Object::ToObject(isolate, object));
859 Handle<FixedArray> entries;
860 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
861 isolate, entries,
862 JSReceiver::GetOwnEntries(receiver, ENUMERABLE_STRINGS));
863 return *isolate->factory()->NewJSArrayWithElements(entries);
864 }
865
866 BUILTIN(ObjectGetOwnPropertyDescriptors) {
867 HandleScope scope(isolate);
868 Handle<Object> object = args.atOrUndefined(isolate, 1);
869
870 Handle<JSReceiver> receiver;
871 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
872 Object::ToObject(isolate, object));
873
874 Handle<FixedArray> keys;
875 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
876 isolate, keys, KeyAccumulator::GetKeys(
877 receiver, KeyCollectionMode::kOwnOnly, ALL_PROPERTIES,
878 GetKeysConversion::kConvertToString));
879
880 Handle<JSObject> descriptors =
881 isolate->factory()->NewJSObject(isolate->object_function());
882
883 for (int i = 0; i < keys->length(); ++i) {
884 Handle<Name> key = Handle<Name>::cast(FixedArray::get(*keys, i, isolate));
885 PropertyDescriptor descriptor;
886 Maybe<bool> did_get_descriptor = JSReceiver::GetOwnPropertyDescriptor(
887 isolate, receiver, key, &descriptor);
888 MAYBE_RETURN(did_get_descriptor, isolate->heap()->exception());
889
890 if (!did_get_descriptor.FromJust()) continue;
891 Handle<Object> from_descriptor = descriptor.ToObject(isolate);
892
893 LookupIterator it = LookupIterator::PropertyOrElement(
894 isolate, descriptors, key, descriptors, LookupIterator::OWN);
895 Maybe<bool> success = JSReceiver::CreateDataProperty(&it, from_descriptor,
896 Object::DONT_THROW);
897 CHECK(success.FromJust());
898 }
899
900 return *descriptors;
901 }
902
903 // ES6 section 19.1.2.15 Object.preventExtensions ( O )
904 BUILTIN(ObjectPreventExtensions) {
905 HandleScope scope(isolate);
906 Handle<Object> object = args.atOrUndefined(isolate, 1);
907 if (object->IsJSReceiver()) {
908 MAYBE_RETURN(JSReceiver::PreventExtensions(Handle<JSReceiver>::cast(object),
909 Object::THROW_ON_ERROR),
910 isolate->heap()->exception());
911 }
912 return *object;
913 }
914
915 // ES6 section 19.1.2.17 Object.seal ( O )
916 BUILTIN(ObjectSeal) {
917 HandleScope scope(isolate);
918 Handle<Object> object = args.atOrUndefined(isolate, 1);
919 if (object->IsJSReceiver()) {
920 MAYBE_RETURN(JSReceiver::SetIntegrityLevel(Handle<JSReceiver>::cast(object),
921 SEALED, Object::THROW_ON_ERROR),
922 isolate->heap()->exception());
923 }
924 return *object;
925 }
926
927 // ES6 section 18.2.6.2 decodeURI (encodedURI)
928 BUILTIN(GlobalDecodeURI) {
929 HandleScope scope(isolate);
930 Handle<String> encoded_uri;
931 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
932 isolate, encoded_uri,
933 Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
934
935 RETURN_RESULT_OR_FAILURE(isolate, Uri::DecodeUri(isolate, encoded_uri));
936 }
937
938 // ES6 section 18.2.6.3 decodeURIComponent (encodedURIComponent)
939 BUILTIN(GlobalDecodeURIComponent) {
940 HandleScope scope(isolate);
941 Handle<String> encoded_uri_component;
942 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
943 isolate, encoded_uri_component,
944 Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
945
946 RETURN_RESULT_OR_FAILURE(
947 isolate, Uri::DecodeUriComponent(isolate, encoded_uri_component));
948 }
949
950 // ES6 section 18.2.6.4 encodeURI (uri)
951 BUILTIN(GlobalEncodeURI) {
952 HandleScope scope(isolate);
953 Handle<String> uri;
954 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
955 isolate, uri, Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
956
957 RETURN_RESULT_OR_FAILURE(isolate, Uri::EncodeUri(isolate, uri));
958 }
959
960 // ES6 section 18.2.6.5 encodeURIComponenet (uriComponent)
961 BUILTIN(GlobalEncodeURIComponent) {
962 HandleScope scope(isolate);
963 Handle<String> uri_component;
964 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
965 isolate, uri_component,
966 Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
967
968 RETURN_RESULT_OR_FAILURE(isolate,
969 Uri::EncodeUriComponent(isolate, uri_component));
970 }
971
972 // ES6 section B.2.1.1 escape (string)
973 BUILTIN(GlobalEscape) {
974 HandleScope scope(isolate);
975 Handle<String> string;
976 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
977 isolate, string,
978 Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
979
980 RETURN_RESULT_OR_FAILURE(isolate, Uri::Escape(isolate, string));
981 }
982
983 // ES6 section B.2.1.2 unescape (string)
984 BUILTIN(GlobalUnescape) {
985 HandleScope scope(isolate);
986 Handle<String> string;
987 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
988 isolate, string,
989 Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
990
991 RETURN_RESULT_OR_FAILURE(isolate, Uri::Unescape(isolate, string));
992 }
993
994 namespace {
995
996 bool CodeGenerationFromStringsAllowed(Isolate* isolate,
997 Handle<Context> context) {
998 DCHECK(context->allow_code_gen_from_strings()->IsFalse(isolate));
999 // Check with callback if set.
1000 AllowCodeGenerationFromStringsCallback callback =
1001 isolate->allow_code_gen_callback();
1002 if (callback == NULL) {
1003 // No callback set and code generation disallowed.
1004 return false;
1005 } else {
1006 // Callback set. Let it decide if code generation is allowed.
1007 VMState<EXTERNAL> state(isolate);
1008 return callback(v8::Utils::ToLocal(context));
1009 }
1010 }
1011
1012 MaybeHandle<JSFunction> CompileString(Handle<Context> context,
1013 Handle<String> source,
1014 ParseRestriction restriction) {
1015 Isolate* const isolate = context->GetIsolate();
1016 Handle<Context> native_context(context->native_context(), isolate);
1017
1018 // Check if native context allows code generation from
1019 // strings. Throw an exception if it doesn't.
1020 if (native_context->allow_code_gen_from_strings()->IsFalse(isolate) &&
1021 !CodeGenerationFromStringsAllowed(isolate, native_context)) {
1022 Handle<Object> error_message =
1023 native_context->ErrorMessageForCodeGenerationFromStrings();
1024 THROW_NEW_ERROR(isolate, NewEvalError(MessageTemplate::kCodeGenFromStrings,
1025 error_message),
1026 JSFunction);
1027 }
1028
1029 // Compile source string in the native context.
1030 int eval_scope_position = 0;
1031 int eval_position = kNoSourcePosition;
1032 Handle<SharedFunctionInfo> outer_info(native_context->closure()->shared());
1033 return Compiler::GetFunctionFromEval(source, outer_info, native_context,
1034 SLOPPY, restriction, eval_scope_position,
1035 eval_position);
1036 }
1037
1038 } // namespace
1039
1040 // ES6 section 18.2.1 eval (x)
1041 BUILTIN(GlobalEval) {
1042 HandleScope scope(isolate);
1043 Handle<Object> x = args.atOrUndefined(isolate, 1);
1044 Handle<JSFunction> target = args.target<JSFunction>();
1045 Handle<JSObject> target_global_proxy(target->global_proxy(), isolate);
1046 if (!x->IsString()) return *x;
1047 Handle<JSFunction> function;
1048 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1049 isolate, function,
1050 CompileString(handle(target->native_context(), isolate),
1051 Handle<String>::cast(x), NO_PARSE_RESTRICTION));
1052 RETURN_RESULT_OR_FAILURE(
1053 isolate,
1054 Execution::Call(isolate, function, target_global_proxy, 0, nullptr));
1055 }
1056
1057 // ES6 section 24.3.1 JSON.parse.
1058 BUILTIN(JsonParse) {
1059 HandleScope scope(isolate);
1060 Handle<Object> source = args.atOrUndefined(isolate, 1);
1061 Handle<Object> reviver = args.atOrUndefined(isolate, 2);
1062 Handle<String> string;
1063 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, string,
1064 Object::ToString(isolate, source));
1065 string = String::Flatten(string);
1066 RETURN_RESULT_OR_FAILURE(
1067 isolate, string->IsSeqOneByteString()
1068 ? JsonParser<true>::Parse(isolate, string, reviver)
1069 : JsonParser<false>::Parse(isolate, string, reviver));
1070 }
1071
1072 // ES6 section 24.3.2 JSON.stringify.
1073 BUILTIN(JsonStringify) {
1074 HandleScope scope(isolate);
1075 JsonStringifier stringifier(isolate);
1076 Handle<Object> object = args.atOrUndefined(isolate, 1);
1077 Handle<Object> replacer = args.atOrUndefined(isolate, 2);
1078 Handle<Object> indent = args.atOrUndefined(isolate, 3);
1079 RETURN_RESULT_OR_FAILURE(isolate,
1080 stringifier.Stringify(object, replacer, indent));
1081 }
1082
1083 // -----------------------------------------------------------------------------
1084 // ES6 section 20.1 Number Objects
1085
1086 // ES6 section 20.1.3.2 Number.prototype.toExponential ( fractionDigits )
1087 BUILTIN(NumberPrototypeToExponential) {
1088 HandleScope scope(isolate);
1089 Handle<Object> value = args.at<Object>(0);
1090 Handle<Object> fraction_digits = args.atOrUndefined(isolate, 1);
1091
1092 // Unwrap the receiver {value}.
1093 if (value->IsJSValue()) {
1094 value = handle(Handle<JSValue>::cast(value)->value(), isolate);
1095 }
1096 if (!value->IsNumber()) {
1097 THROW_NEW_ERROR_RETURN_FAILURE(
1098 isolate, NewTypeError(MessageTemplate::kNotGeneric,
1099 isolate->factory()->NewStringFromAsciiChecked(
1100 "Number.prototype.toExponential")));
1101 }
1102 double const value_number = value->Number();
1103
1104 // Convert the {fraction_digits} to an integer first.
1105 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1106 isolate, fraction_digits, Object::ToInteger(isolate, fraction_digits));
1107 double const fraction_digits_number = fraction_digits->Number();
1108
1109 if (std::isnan(value_number)) return isolate->heap()->nan_string();
1110 if (std::isinf(value_number)) {
1111 return (value_number < 0.0) ? isolate->heap()->minus_infinity_string()
1112 : isolate->heap()->infinity_string();
1113 }
1114 if (fraction_digits_number < 0.0 || fraction_digits_number > 20.0) {
1115 THROW_NEW_ERROR_RETURN_FAILURE(
1116 isolate, NewRangeError(MessageTemplate::kNumberFormatRange,
1117 isolate->factory()->NewStringFromAsciiChecked(
1118 "toExponential()")));
1119 }
1120 int const f = args.atOrUndefined(isolate, 1)->IsUndefined(isolate)
1121 ? -1
1122 : static_cast<int>(fraction_digits_number);
1123 char* const str = DoubleToExponentialCString(value_number, f);
1124 Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
1125 DeleteArray(str);
1126 return *result;
1127 }
1128
1129 // ES6 section 20.1.3.3 Number.prototype.toFixed ( fractionDigits )
1130 BUILTIN(NumberPrototypeToFixed) {
1131 HandleScope scope(isolate);
1132 Handle<Object> value = args.at<Object>(0);
1133 Handle<Object> fraction_digits = args.atOrUndefined(isolate, 1);
1134
1135 // Unwrap the receiver {value}.
1136 if (value->IsJSValue()) {
1137 value = handle(Handle<JSValue>::cast(value)->value(), isolate);
1138 }
1139 if (!value->IsNumber()) {
1140 THROW_NEW_ERROR_RETURN_FAILURE(
1141 isolate, NewTypeError(MessageTemplate::kNotGeneric,
1142 isolate->factory()->NewStringFromAsciiChecked(
1143 "Number.prototype.toFixed")));
1144 }
1145 double const value_number = value->Number();
1146
1147 // Convert the {fraction_digits} to an integer first.
1148 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1149 isolate, fraction_digits, Object::ToInteger(isolate, fraction_digits));
1150 double const fraction_digits_number = fraction_digits->Number();
1151
1152 // Check if the {fraction_digits} are in the supported range.
1153 if (fraction_digits_number < 0.0 || fraction_digits_number > 20.0) {
1154 THROW_NEW_ERROR_RETURN_FAILURE(
1155 isolate, NewRangeError(MessageTemplate::kNumberFormatRange,
1156 isolate->factory()->NewStringFromAsciiChecked(
1157 "toFixed() digits")));
1158 }
1159
1160 if (std::isnan(value_number)) return isolate->heap()->nan_string();
1161 if (std::isinf(value_number)) {
1162 return (value_number < 0.0) ? isolate->heap()->minus_infinity_string()
1163 : isolate->heap()->infinity_string();
1164 }
1165 char* const str = DoubleToFixedCString(
1166 value_number, static_cast<int>(fraction_digits_number));
1167 Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
1168 DeleteArray(str);
1169 return *result;
1170 }
1171
1172 // ES6 section 20.1.3.4 Number.prototype.toLocaleString ( [ r1 [ , r2 ] ] )
1173 BUILTIN(NumberPrototypeToLocaleString) {
1174 HandleScope scope(isolate);
1175 Handle<Object> value = args.at<Object>(0);
1176
1177 // Unwrap the receiver {value}.
1178 if (value->IsJSValue()) {
1179 value = handle(Handle<JSValue>::cast(value)->value(), isolate);
1180 }
1181 if (!value->IsNumber()) {
1182 THROW_NEW_ERROR_RETURN_FAILURE(
1183 isolate, NewTypeError(MessageTemplate::kNotGeneric,
1184 isolate->factory()->NewStringFromAsciiChecked(
1185 "Number.prototype.toLocaleString")));
1186 }
1187
1188 // Turn the {value} into a String.
1189 return *isolate->factory()->NumberToString(value);
1190 }
1191
1192 // ES6 section 20.1.3.5 Number.prototype.toPrecision ( precision )
1193 BUILTIN(NumberPrototypeToPrecision) {
1194 HandleScope scope(isolate);
1195 Handle<Object> value = args.at<Object>(0);
1196 Handle<Object> precision = args.atOrUndefined(isolate, 1);
1197
1198 // Unwrap the receiver {value}.
1199 if (value->IsJSValue()) {
1200 value = handle(Handle<JSValue>::cast(value)->value(), isolate);
1201 }
1202 if (!value->IsNumber()) {
1203 THROW_NEW_ERROR_RETURN_FAILURE(
1204 isolate, NewTypeError(MessageTemplate::kNotGeneric,
1205 isolate->factory()->NewStringFromAsciiChecked(
1206 "Number.prototype.toPrecision")));
1207 }
1208 double const value_number = value->Number();
1209
1210 // If no {precision} was specified, just return ToString of {value}.
1211 if (precision->IsUndefined(isolate)) {
1212 return *isolate->factory()->NumberToString(value);
1213 }
1214
1215 // Convert the {precision} to an integer first.
1216 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, precision,
1217 Object::ToInteger(isolate, precision));
1218 double const precision_number = precision->Number();
1219
1220 if (std::isnan(value_number)) return isolate->heap()->nan_string();
1221 if (std::isinf(value_number)) {
1222 return (value_number < 0.0) ? isolate->heap()->minus_infinity_string()
1223 : isolate->heap()->infinity_string();
1224 }
1225 if (precision_number < 1.0 || precision_number > 21.0) {
1226 THROW_NEW_ERROR_RETURN_FAILURE(
1227 isolate, NewRangeError(MessageTemplate::kToPrecisionFormatRange));
1228 }
1229 char* const str = DoubleToPrecisionCString(
1230 value_number, static_cast<int>(precision_number));
1231 Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
1232 DeleteArray(str);
1233 return *result;
1234 }
1235
1236 // ES6 section 20.1.3.6 Number.prototype.toString ( [ radix ] )
1237 BUILTIN(NumberPrototypeToString) {
1238 HandleScope scope(isolate);
1239 Handle<Object> value = args.at<Object>(0);
1240 Handle<Object> radix = args.atOrUndefined(isolate, 1);
1241
1242 // Unwrap the receiver {value}.
1243 if (value->IsJSValue()) {
1244 value = handle(Handle<JSValue>::cast(value)->value(), isolate);
1245 }
1246 if (!value->IsNumber()) {
1247 THROW_NEW_ERROR_RETURN_FAILURE(
1248 isolate, NewTypeError(MessageTemplate::kNotGeneric,
1249 isolate->factory()->NewStringFromAsciiChecked(
1250 "Number.prototype.toString")));
1251 }
1252 double const value_number = value->Number();
1253
1254 // If no {radix} was specified, just return ToString of {value}.
1255 if (radix->IsUndefined(isolate)) {
1256 return *isolate->factory()->NumberToString(value);
1257 }
1258
1259 // Convert the {radix} to an integer first.
1260 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, radix,
1261 Object::ToInteger(isolate, radix));
1262 double const radix_number = radix->Number();
1263
1264 // If {radix} is 10, just return ToString of {value}.
1265 if (radix_number == 10.0) return *isolate->factory()->NumberToString(value);
1266
1267 // Make sure the {radix} is within the valid range.
1268 if (radix_number < 2.0 || radix_number > 36.0) {
1269 THROW_NEW_ERROR_RETURN_FAILURE(
1270 isolate, NewRangeError(MessageTemplate::kToRadixFormatRange));
1271 }
1272
1273 // Fast case where the result is a one character string.
1274 if (IsUint32Double(value_number) && value_number < radix_number) {
1275 // Character array used for conversion.
1276 static const char kCharTable[] = "0123456789abcdefghijklmnopqrstuvwxyz";
1277 return *isolate->factory()->LookupSingleCharacterStringFromCode(
1278 kCharTable[static_cast<uint32_t>(value_number)]);
1279 }
1280
1281 // Slow case.
1282 if (std::isnan(value_number)) return isolate->heap()->nan_string();
1283 if (std::isinf(value_number)) {
1284 return (value_number < 0.0) ? isolate->heap()->minus_infinity_string()
1285 : isolate->heap()->infinity_string();
1286 }
1287 char* const str =
1288 DoubleToRadixCString(value_number, static_cast<int>(radix_number));
1289 Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
1290 DeleteArray(str);
1291 return *result;
1292 }
1293
1294 // ES6 section 20.1.3.7 Number.prototype.valueOf ( )
1295 void Builtins::Generate_NumberPrototypeValueOf(CodeStubAssembler* assembler) {
1296 typedef compiler::Node Node;
1297
1298 Node* receiver = assembler->Parameter(0);
1299 Node* context = assembler->Parameter(3);
1300
1301 Node* result = assembler->ToThisValue(
1302 context, receiver, PrimitiveType::kNumber, "Number.prototype.valueOf");
1303 assembler->Return(result);
1304 }
1305
1306 // -----------------------------------------------------------------------------
1307 // ES6 section 20.2.2 Function Properties of the Math Object
1308
1309 // ES6 section - 20.2.2.1 Math.abs ( x )
1310 void Builtins::Generate_MathAbs(CodeStubAssembler* assembler) {
1311 using compiler::Node;
1312 Node* x = assembler->Parameter(1);
1313 Node* context = assembler->Parameter(4);
1314 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
1315 Node* value = assembler->Float64Abs(x_value);
1316 Node* result = assembler->ChangeFloat64ToTagged(value);
1317 assembler->Return(result);
1318 }
1319
1320 // ES6 section 20.2.2.2 Math.acos ( x )
1321 void Builtins::Generate_MathAcos(CodeStubAssembler* assembler) {
1322 using compiler::Node;
1323
1324 Node* x = assembler->Parameter(1);
1325 Node* context = assembler->Parameter(4);
1326 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
1327 Node* value = assembler->Float64Acos(x_value);
1328 Node* result = assembler->ChangeFloat64ToTagged(value);
1329 assembler->Return(result);
1330 }
1331
1332 // ES6 section 20.2.2.3 Math.acosh ( x )
1333 void Builtins::Generate_MathAcosh(CodeStubAssembler* assembler) {
1334 using compiler::Node;
1335
1336 Node* x = assembler->Parameter(1);
1337 Node* context = assembler->Parameter(4);
1338 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
1339 Node* value = assembler->Float64Acosh(x_value);
1340 Node* result = assembler->ChangeFloat64ToTagged(value);
1341 assembler->Return(result);
1342 }
1343
1344 // ES6 section 20.2.2.4 Math.asin ( x )
1345 void Builtins::Generate_MathAsin(CodeStubAssembler* assembler) {
1346 using compiler::Node;
1347
1348 Node* x = assembler->Parameter(1);
1349 Node* context = assembler->Parameter(4);
1350 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
1351 Node* value = assembler->Float64Asin(x_value);
1352 Node* result = assembler->ChangeFloat64ToTagged(value);
1353 assembler->Return(result);
1354 }
1355
1356 // ES6 section 20.2.2.5 Math.asinh ( x )
1357 void Builtins::Generate_MathAsinh(CodeStubAssembler* assembler) {
1358 using compiler::Node;
1359
1360 Node* x = assembler->Parameter(1);
1361 Node* context = assembler->Parameter(4);
1362 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
1363 Node* value = assembler->Float64Asinh(x_value);
1364 Node* result = assembler->ChangeFloat64ToTagged(value);
1365 assembler->Return(result);
1366 }
1367
1368 // ES6 section 20.2.2.6 Math.atan ( x )
1369 void Builtins::Generate_MathAtan(CodeStubAssembler* assembler) {
1370 using compiler::Node;
1371
1372 Node* x = assembler->Parameter(1);
1373 Node* context = assembler->Parameter(4);
1374 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
1375 Node* value = assembler->Float64Atan(x_value);
1376 Node* result = assembler->ChangeFloat64ToTagged(value);
1377 assembler->Return(result);
1378 }
1379
1380 // ES6 section 20.2.2.7 Math.atanh ( x )
1381 void Builtins::Generate_MathAtanh(CodeStubAssembler* assembler) {
1382 using compiler::Node;
1383
1384 Node* x = assembler->Parameter(1);
1385 Node* context = assembler->Parameter(4);
1386 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
1387 Node* value = assembler->Float64Atanh(x_value);
1388 Node* result = assembler->ChangeFloat64ToTagged(value);
1389 assembler->Return(result);
1390 }
1391
1392 // ES6 section 20.2.2.8 Math.atan2 ( y, x )
1393 void Builtins::Generate_MathAtan2(CodeStubAssembler* assembler) {
1394 using compiler::Node;
1395
1396 Node* y = assembler->Parameter(1);
1397 Node* x = assembler->Parameter(2);
1398 Node* context = assembler->Parameter(5);
1399 Node* y_value = assembler->TruncateTaggedToFloat64(context, y);
1400 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
1401 Node* value = assembler->Float64Atan2(y_value, x_value);
1402 Node* result = assembler->ChangeFloat64ToTagged(value);
1403 assembler->Return(result);
1404 }
1405
1406 namespace {
1407
1408 void Generate_MathRoundingOperation(
1409 CodeStubAssembler* assembler,
1410 compiler::Node* (CodeStubAssembler::*float64op)(compiler::Node*)) {
1411 typedef CodeStubAssembler::Label Label;
1412 typedef compiler::Node Node;
1413 typedef CodeStubAssembler::Variable Variable;
1414
1415 Node* context = assembler->Parameter(4);
1416
1417 // We might need to loop once for ToNumber conversion.
1418 Variable var_x(assembler, MachineRepresentation::kTagged);
1419 Label loop(assembler, &var_x);
1420 var_x.Bind(assembler->Parameter(1));
1421 assembler->Goto(&loop);
1422 assembler->Bind(&loop);
1423 {
1424 // Load the current {x} value.
1425 Node* x = var_x.value();
1426
1427 // Check if {x} is a Smi or a HeapObject.
1428 Label if_xissmi(assembler), if_xisnotsmi(assembler);
1429 assembler->Branch(assembler->WordIsSmi(x), &if_xissmi, &if_xisnotsmi);
1430
1431 assembler->Bind(&if_xissmi);
1432 {
1433 // Nothing to do when {x} is a Smi.
1434 assembler->Return(x);
1435 }
1436
1437 assembler->Bind(&if_xisnotsmi);
1438 {
1439 // Check if {x} is a HeapNumber.
1440 Label if_xisheapnumber(assembler),
1441 if_xisnotheapnumber(assembler, Label::kDeferred);
1442 assembler->Branch(
1443 assembler->WordEqual(assembler->LoadMap(x),
1444 assembler->HeapNumberMapConstant()),
1445 &if_xisheapnumber, &if_xisnotheapnumber);
1446
1447 assembler->Bind(&if_xisheapnumber);
1448 {
1449 Node* x_value = assembler->LoadHeapNumberValue(x);
1450 Node* value = (assembler->*float64op)(x_value);
1451 Node* result = assembler->ChangeFloat64ToTagged(value);
1452 assembler->Return(result);
1453 }
1454
1455 assembler->Bind(&if_xisnotheapnumber);
1456 {
1457 // Need to convert {x} to a Number first.
1458 Callable callable =
1459 CodeFactory::NonNumberToNumber(assembler->isolate());
1460 var_x.Bind(assembler->CallStub(callable, context, x));
1461 assembler->Goto(&loop);
1462 }
1463 }
1464 }
1465 }
1466
1467 } // namespace
1468
1469 // ES6 section 20.2.2.10 Math.ceil ( x )
1470 void Builtins::Generate_MathCeil(CodeStubAssembler* assembler) {
1471 Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Ceil);
1472 }
1473
1474 // ES6 section 20.2.2.9 Math.cbrt ( x )
1475 void Builtins::Generate_MathCbrt(CodeStubAssembler* assembler) {
1476 using compiler::Node;
1477
1478 Node* x = assembler->Parameter(1);
1479 Node* context = assembler->Parameter(4);
1480 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
1481 Node* value = assembler->Float64Cbrt(x_value);
1482 Node* result = assembler->ChangeFloat64ToTagged(value);
1483 assembler->Return(result);
1484 }
1485
1486 // ES6 section 20.2.2.11 Math.clz32 ( x )
1487 void Builtins::Generate_MathClz32(CodeStubAssembler* assembler) {
1488 typedef CodeStubAssembler::Label Label;
1489 typedef compiler::Node Node;
1490 typedef CodeStubAssembler::Variable Variable;
1491
1492 Node* context = assembler->Parameter(4);
1493
1494 // Shared entry point for the clz32 operation.
1495 Variable var_clz32_x(assembler, MachineRepresentation::kWord32);
1496 Label do_clz32(assembler);
1497
1498 // We might need to loop once for ToNumber conversion.
1499 Variable var_x(assembler, MachineRepresentation::kTagged);
1500 Label loop(assembler, &var_x);
1501 var_x.Bind(assembler->Parameter(1));
1502 assembler->Goto(&loop);
1503 assembler->Bind(&loop);
1504 {
1505 // Load the current {x} value.
1506 Node* x = var_x.value();
1507
1508 // Check if {x} is a Smi or a HeapObject.
1509 Label if_xissmi(assembler), if_xisnotsmi(assembler);
1510 assembler->Branch(assembler->WordIsSmi(x), &if_xissmi, &if_xisnotsmi);
1511
1512 assembler->Bind(&if_xissmi);
1513 {
1514 var_clz32_x.Bind(assembler->SmiToWord32(x));
1515 assembler->Goto(&do_clz32);
1516 }
1517
1518 assembler->Bind(&if_xisnotsmi);
1519 {
1520 // Check if {x} is a HeapNumber.
1521 Label if_xisheapnumber(assembler),
1522 if_xisnotheapnumber(assembler, Label::kDeferred);
1523 assembler->Branch(
1524 assembler->WordEqual(assembler->LoadMap(x),
1525 assembler->HeapNumberMapConstant()),
1526 &if_xisheapnumber, &if_xisnotheapnumber);
1527
1528 assembler->Bind(&if_xisheapnumber);
1529 {
1530 var_clz32_x.Bind(assembler->TruncateHeapNumberValueToWord32(x));
1531 assembler->Goto(&do_clz32);
1532 }
1533
1534 assembler->Bind(&if_xisnotheapnumber);
1535 {
1536 // Need to convert {x} to a Number first.
1537 Callable callable =
1538 CodeFactory::NonNumberToNumber(assembler->isolate());
1539 var_x.Bind(assembler->CallStub(callable, context, x));
1540 assembler->Goto(&loop);
1541 }
1542 }
1543 }
1544
1545 assembler->Bind(&do_clz32);
1546 {
1547 Node* x_value = var_clz32_x.value();
1548 Node* value = assembler->Word32Clz(x_value);
1549 Node* result = assembler->ChangeInt32ToTagged(value);
1550 assembler->Return(result);
1551 }
1552 }
1553
1554 // ES6 section 20.2.2.12 Math.cos ( x )
1555 void Builtins::Generate_MathCos(CodeStubAssembler* assembler) {
1556 using compiler::Node;
1557
1558 Node* x = assembler->Parameter(1);
1559 Node* context = assembler->Parameter(4);
1560 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
1561 Node* value = assembler->Float64Cos(x_value);
1562 Node* result = assembler->ChangeFloat64ToTagged(value);
1563 assembler->Return(result);
1564 }
1565
1566 // ES6 section 20.2.2.13 Math.cosh ( x )
1567 void Builtins::Generate_MathCosh(CodeStubAssembler* assembler) {
1568 using compiler::Node;
1569
1570 Node* x = assembler->Parameter(1);
1571 Node* context = assembler->Parameter(4);
1572 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
1573 Node* value = assembler->Float64Cosh(x_value);
1574 Node* result = assembler->ChangeFloat64ToTagged(value);
1575 assembler->Return(result);
1576 }
1577
1578 // ES6 section 20.2.2.14 Math.exp ( x )
1579 void Builtins::Generate_MathExp(CodeStubAssembler* assembler) {
1580 using compiler::Node;
1581
1582 Node* x = assembler->Parameter(1);
1583 Node* context = assembler->Parameter(4);
1584 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
1585 Node* value = assembler->Float64Exp(x_value);
1586 Node* result = assembler->ChangeFloat64ToTagged(value);
1587 assembler->Return(result);
1588 }
1589
1590 // ES6 section 20.2.2.16 Math.floor ( x )
1591 void Builtins::Generate_MathFloor(CodeStubAssembler* assembler) {
1592 Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Floor);
1593 }
1594
1595 // ES6 section 20.2.2.17 Math.fround ( x )
1596 void Builtins::Generate_MathFround(CodeStubAssembler* assembler) {
1597 using compiler::Node;
1598
1599 Node* x = assembler->Parameter(1);
1600 Node* context = assembler->Parameter(4);
1601 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
1602 Node* value32 = assembler->TruncateFloat64ToFloat32(x_value);
1603 Node* value = assembler->ChangeFloat32ToFloat64(value32);
1604 Node* result = assembler->ChangeFloat64ToTagged(value);
1605 assembler->Return(result);
1606 }
1607
1608 // ES6 section 20.2.2.18 Math.hypot ( value1, value2, ...values )
1609 BUILTIN(MathHypot) {
1610 HandleScope scope(isolate);
1611 int const length = args.length() - 1;
1612 if (length == 0) return Smi::FromInt(0);
1613 DCHECK_LT(0, length);
1614 double max = 0;
1615 bool one_arg_is_nan = false;
1616 List<double> abs_values(length);
1617 for (int i = 0; i < length; i++) {
1618 Handle<Object> x = args.at<Object>(i + 1);
1619 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x, Object::ToNumber(x));
1620 double abs_value = std::abs(x->Number());
1621
1622 if (std::isnan(abs_value)) {
1623 one_arg_is_nan = true;
1624 } else {
1625 abs_values.Add(abs_value);
1626 if (max < abs_value) {
1627 max = abs_value;
1628 }
1629 }
1630 }
1631
1632 if (max == V8_INFINITY) {
1633 return *isolate->factory()->NewNumber(V8_INFINITY);
1634 }
1635
1636 if (one_arg_is_nan) {
1637 return *isolate->factory()->nan_value();
1638 }
1639
1640 if (max == 0) {
1641 return Smi::FromInt(0);
1642 }
1643 DCHECK_GT(max, 0);
1644
1645 // Kahan summation to avoid rounding errors.
1646 // Normalize the numbers to the largest one to avoid overflow.
1647 double sum = 0;
1648 double compensation = 0;
1649 for (int i = 0; i < length; i++) {
1650 double n = abs_values.at(i) / max;
1651 double summand = n * n - compensation;
1652 double preliminary = sum + summand;
1653 compensation = (preliminary - sum) - summand;
1654 sum = preliminary;
1655 }
1656
1657 return *isolate->factory()->NewNumber(std::sqrt(sum) * max);
1658 }
1659
1660 // ES6 section 20.2.2.19 Math.imul ( x, y )
1661 void Builtins::Generate_MathImul(CodeStubAssembler* assembler) {
1662 using compiler::Node;
1663
1664 Node* x = assembler->Parameter(1);
1665 Node* y = assembler->Parameter(2);
1666 Node* context = assembler->Parameter(5);
1667 Node* x_value = assembler->TruncateTaggedToWord32(context, x);
1668 Node* y_value = assembler->TruncateTaggedToWord32(context, y);
1669 Node* value = assembler->Int32Mul(x_value, y_value);
1670 Node* result = assembler->ChangeInt32ToTagged(value);
1671 assembler->Return(result);
1672 }
1673
1674 // ES6 section 20.2.2.20 Math.log ( x )
1675 void Builtins::Generate_MathLog(CodeStubAssembler* assembler) {
1676 using compiler::Node;
1677
1678 Node* x = assembler->Parameter(1);
1679 Node* context = assembler->Parameter(4);
1680 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
1681 Node* value = assembler->Float64Log(x_value);
1682 Node* result = assembler->ChangeFloat64ToTagged(value);
1683 assembler->Return(result);
1684 }
1685
1686 // ES6 section 20.2.2.21 Math.log1p ( x )
1687 void Builtins::Generate_MathLog1p(CodeStubAssembler* assembler) {
1688 using compiler::Node;
1689
1690 Node* x = assembler->Parameter(1);
1691 Node* context = assembler->Parameter(4);
1692 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
1693 Node* value = assembler->Float64Log1p(x_value);
1694 Node* result = assembler->ChangeFloat64ToTagged(value);
1695 assembler->Return(result);
1696 }
1697
1698 // ES6 section 20.2.2.22 Math.log10 ( x )
1699 void Builtins::Generate_MathLog10(CodeStubAssembler* assembler) {
1700 using compiler::Node;
1701
1702 Node* x = assembler->Parameter(1);
1703 Node* context = assembler->Parameter(4);
1704 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
1705 Node* value = assembler->Float64Log10(x_value);
1706 Node* result = assembler->ChangeFloat64ToTagged(value);
1707 assembler->Return(result);
1708 }
1709
1710 // ES6 section 20.2.2.23 Math.log2 ( x )
1711 void Builtins::Generate_MathLog2(CodeStubAssembler* assembler) {
1712 using compiler::Node;
1713
1714 Node* x = assembler->Parameter(1);
1715 Node* context = assembler->Parameter(4);
1716 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
1717 Node* value = assembler->Float64Log2(x_value);
1718 Node* result = assembler->ChangeFloat64ToTagged(value);
1719 assembler->Return(result);
1720 }
1721
1722 // ES6 section 20.2.2.15 Math.expm1 ( x )
1723 void Builtins::Generate_MathExpm1(CodeStubAssembler* assembler) {
1724 using compiler::Node;
1725
1726 Node* x = assembler->Parameter(1);
1727 Node* context = assembler->Parameter(4);
1728 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
1729 Node* value = assembler->Float64Expm1(x_value);
1730 Node* result = assembler->ChangeFloat64ToTagged(value);
1731 assembler->Return(result);
1732 }
1733
1734 // ES6 section 20.2.2.26 Math.pow ( x, y )
1735 void Builtins::Generate_MathPow(CodeStubAssembler* assembler) {
1736 using compiler::Node;
1737
1738 Node* x = assembler->Parameter(1);
1739 Node* y = assembler->Parameter(2);
1740 Node* context = assembler->Parameter(5);
1741 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
1742 Node* y_value = assembler->TruncateTaggedToFloat64(context, y);
1743 Node* value = assembler->Float64Pow(x_value, y_value);
1744 Node* result = assembler->ChangeFloat64ToTagged(value);
1745 assembler->Return(result);
1746 }
1747
1748 // ES6 section 20.2.2.28 Math.round ( x )
1749 void Builtins::Generate_MathRound(CodeStubAssembler* assembler) {
1750 Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Round);
1751 }
1752
1753 // ES6 section 20.2.2.29 Math.sign ( x )
1754 void Builtins::Generate_MathSign(CodeStubAssembler* assembler) {
1755 typedef CodeStubAssembler::Label Label;
1756 using compiler::Node;
1757
1758 // Convert the {x} value to a Number.
1759 Node* x = assembler->Parameter(1);
1760 Node* context = assembler->Parameter(4);
1761 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
1762
1763 // Return -1 if {x} is negative, 1 if {x} is positive, or {x} itself.
1764 Label if_xisnegative(assembler), if_xispositive(assembler);
1765 assembler->GotoIf(
1766 assembler->Float64LessThan(x_value, assembler->Float64Constant(0.0)),
1767 &if_xisnegative);
1768 assembler->GotoIf(
1769 assembler->Float64LessThan(assembler->Float64Constant(0.0), x_value),
1770 &if_xispositive);
1771 assembler->Return(assembler->ChangeFloat64ToTagged(x_value));
1772
1773 assembler->Bind(&if_xisnegative);
1774 assembler->Return(assembler->SmiConstant(Smi::FromInt(-1)));
1775
1776 assembler->Bind(&if_xispositive);
1777 assembler->Return(assembler->SmiConstant(Smi::FromInt(1)));
1778 }
1779
1780 // ES6 section 20.2.2.30 Math.sin ( x )
1781 void Builtins::Generate_MathSin(CodeStubAssembler* assembler) {
1782 using compiler::Node;
1783
1784 Node* x = assembler->Parameter(1);
1785 Node* context = assembler->Parameter(4);
1786 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
1787 Node* value = assembler->Float64Sin(x_value);
1788 Node* result = assembler->ChangeFloat64ToTagged(value);
1789 assembler->Return(result);
1790 }
1791
1792 // ES6 section 20.2.2.31 Math.sinh ( x )
1793 void Builtins::Generate_MathSinh(CodeStubAssembler* assembler) {
1794 using compiler::Node;
1795
1796 Node* x = assembler->Parameter(1);
1797 Node* context = assembler->Parameter(4);
1798 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
1799 Node* value = assembler->Float64Sinh(x_value);
1800 Node* result = assembler->ChangeFloat64ToTagged(value);
1801 assembler->Return(result);
1802 }
1803
1804 // ES6 section 20.2.2.32 Math.sqrt ( x )
1805 void Builtins::Generate_MathSqrt(CodeStubAssembler* assembler) {
1806 using compiler::Node;
1807
1808 Node* x = assembler->Parameter(1);
1809 Node* context = assembler->Parameter(4);
1810 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
1811 Node* value = assembler->Float64Sqrt(x_value);
1812 Node* result = assembler->ChangeFloat64ToTagged(value);
1813 assembler->Return(result);
1814 }
1815
1816 // ES6 section 20.2.2.33 Math.tan ( x )
1817 void Builtins::Generate_MathTan(CodeStubAssembler* assembler) {
1818 using compiler::Node;
1819
1820 Node* x = assembler->Parameter(1);
1821 Node* context = assembler->Parameter(4);
1822 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
1823 Node* value = assembler->Float64Tan(x_value);
1824 Node* result = assembler->ChangeFloat64ToTagged(value);
1825 assembler->Return(result);
1826 }
1827
1828 // ES6 section 20.2.2.34 Math.tanh ( x )
1829 void Builtins::Generate_MathTanh(CodeStubAssembler* assembler) {
1830 using compiler::Node;
1831
1832 Node* x = assembler->Parameter(1);
1833 Node* context = assembler->Parameter(4);
1834 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
1835 Node* value = assembler->Float64Tanh(x_value);
1836 Node* result = assembler->ChangeFloat64ToTagged(value);
1837 assembler->Return(result);
1838 }
1839
1840 // ES6 section 20.2.2.35 Math.trunc ( x )
1841 void Builtins::Generate_MathTrunc(CodeStubAssembler* assembler) {
1842 Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Trunc);
1843 }
1844
1845 // ----------------------------------------------------------------------------- 24 // -----------------------------------------------------------------------------
1846 // ES6 section 19.2 Function Objects 25 // ES6 section 19.2 Function Objects
1847 26
1848 // ES6 section 19.2.3.6 Function.prototype [ @@hasInstance ] ( V ) 27 // ES6 section 19.2.3.6 Function.prototype [ @@hasInstance ] ( V )
1849 void Builtins::Generate_FunctionPrototypeHasInstance( 28 void Builtins::Generate_FunctionPrototypeHasInstance(
1850 CodeStubAssembler* assembler) { 29 CodeStubAssembler* assembler) {
1851 using compiler::Node; 30 using compiler::Node;
1852 31
1853 Node* f = assembler->Parameter(0); 32 Node* f = assembler->Parameter(0);
1854 Node* v = assembler->Parameter(1); 33 Node* v = assembler->Parameter(1);
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
1956 "[Generator].prototype.return"); 135 "[Generator].prototype.return");
1957 } 136 }
1958 137
1959 // ES6 section 25.3.1.4 Generator.prototype.throw ( exception ) 138 // ES6 section 25.3.1.4 Generator.prototype.throw ( exception )
1960 void Builtins::Generate_GeneratorPrototypeThrow(CodeStubAssembler* assembler) { 139 void Builtins::Generate_GeneratorPrototypeThrow(CodeStubAssembler* assembler) {
1961 Generate_GeneratorPrototypeResume(assembler, JSGeneratorObject::kThrow, 140 Generate_GeneratorPrototypeResume(assembler, JSGeneratorObject::kThrow,
1962 "[Generator].prototype.throw"); 141 "[Generator].prototype.throw");
1963 } 142 }
1964 143
1965 // ----------------------------------------------------------------------------- 144 // -----------------------------------------------------------------------------
1966 // ES6 section 26.1 The Reflect Object
1967
1968 // ES6 section 26.1.3 Reflect.defineProperty
1969 BUILTIN(ReflectDefineProperty) {
1970 HandleScope scope(isolate);
1971 DCHECK_EQ(4, args.length());
1972 Handle<Object> target = args.at<Object>(1);
1973 Handle<Object> key = args.at<Object>(2);
1974 Handle<Object> attributes = args.at<Object>(3);
1975
1976 if (!target->IsJSReceiver()) {
1977 THROW_NEW_ERROR_RETURN_FAILURE(
1978 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
1979 isolate->factory()->NewStringFromAsciiChecked(
1980 "Reflect.defineProperty")));
1981 }
1982
1983 Handle<Name> name;
1984 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
1985 Object::ToName(isolate, key));
1986
1987 PropertyDescriptor desc;
1988 if (!PropertyDescriptor::ToPropertyDescriptor(isolate, attributes, &desc)) {
1989 return isolate->heap()->exception();
1990 }
1991
1992 Maybe<bool> result =
1993 JSReceiver::DefineOwnProperty(isolate, Handle<JSReceiver>::cast(target),
1994 name, &desc, Object::DONT_THROW);
1995 MAYBE_RETURN(result, isolate->heap()->exception());
1996 return *isolate->factory()->ToBoolean(result.FromJust());
1997 }
1998
1999 // ES6 section 26.1.4 Reflect.deleteProperty
2000 BUILTIN(ReflectDeleteProperty) {
2001 HandleScope scope(isolate);
2002 DCHECK_EQ(3, args.length());
2003 Handle<Object> target = args.at<Object>(1);
2004 Handle<Object> key = args.at<Object>(2);
2005
2006 if (!target->IsJSReceiver()) {
2007 THROW_NEW_ERROR_RETURN_FAILURE(
2008 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2009 isolate->factory()->NewStringFromAsciiChecked(
2010 "Reflect.deleteProperty")));
2011 }
2012
2013 Handle<Name> name;
2014 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
2015 Object::ToName(isolate, key));
2016
2017 Maybe<bool> result = JSReceiver::DeletePropertyOrElement(
2018 Handle<JSReceiver>::cast(target), name, SLOPPY);
2019 MAYBE_RETURN(result, isolate->heap()->exception());
2020 return *isolate->factory()->ToBoolean(result.FromJust());
2021 }
2022
2023 // ES6 section 26.1.6 Reflect.get
2024 BUILTIN(ReflectGet) {
2025 HandleScope scope(isolate);
2026 Handle<Object> target = args.atOrUndefined(isolate, 1);
2027 Handle<Object> key = args.atOrUndefined(isolate, 2);
2028 Handle<Object> receiver = args.length() > 3 ? args.at<Object>(3) : target;
2029
2030 if (!target->IsJSReceiver()) {
2031 THROW_NEW_ERROR_RETURN_FAILURE(
2032 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2033 isolate->factory()->NewStringFromAsciiChecked(
2034 "Reflect.get")));
2035 }
2036
2037 Handle<Name> name;
2038 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
2039 Object::ToName(isolate, key));
2040
2041 RETURN_RESULT_OR_FAILURE(
2042 isolate, Object::GetPropertyOrElement(receiver, name,
2043 Handle<JSReceiver>::cast(target)));
2044 }
2045
2046 // ES6 section 26.1.7 Reflect.getOwnPropertyDescriptor
2047 BUILTIN(ReflectGetOwnPropertyDescriptor) {
2048 HandleScope scope(isolate);
2049 DCHECK_EQ(3, args.length());
2050 Handle<Object> target = args.at<Object>(1);
2051 Handle<Object> key = args.at<Object>(2);
2052
2053 if (!target->IsJSReceiver()) {
2054 THROW_NEW_ERROR_RETURN_FAILURE(
2055 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2056 isolate->factory()->NewStringFromAsciiChecked(
2057 "Reflect.getOwnPropertyDescriptor")));
2058 }
2059
2060 Handle<Name> name;
2061 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
2062 Object::ToName(isolate, key));
2063
2064 PropertyDescriptor desc;
2065 Maybe<bool> found = JSReceiver::GetOwnPropertyDescriptor(
2066 isolate, Handle<JSReceiver>::cast(target), name, &desc);
2067 MAYBE_RETURN(found, isolate->heap()->exception());
2068 if (!found.FromJust()) return isolate->heap()->undefined_value();
2069 return *desc.ToObject(isolate);
2070 }
2071
2072 // ES6 section 26.1.8 Reflect.getPrototypeOf
2073 BUILTIN(ReflectGetPrototypeOf) {
2074 HandleScope scope(isolate);
2075 DCHECK_EQ(2, args.length());
2076 Handle<Object> target = args.at<Object>(1);
2077
2078 if (!target->IsJSReceiver()) {
2079 THROW_NEW_ERROR_RETURN_FAILURE(
2080 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2081 isolate->factory()->NewStringFromAsciiChecked(
2082 "Reflect.getPrototypeOf")));
2083 }
2084 Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(target);
2085 RETURN_RESULT_OR_FAILURE(isolate,
2086 JSReceiver::GetPrototype(isolate, receiver));
2087 }
2088
2089 // ES6 section 26.1.9 Reflect.has
2090 BUILTIN(ReflectHas) {
2091 HandleScope scope(isolate);
2092 DCHECK_EQ(3, args.length());
2093 Handle<Object> target = args.at<Object>(1);
2094 Handle<Object> key = args.at<Object>(2);
2095
2096 if (!target->IsJSReceiver()) {
2097 THROW_NEW_ERROR_RETURN_FAILURE(
2098 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2099 isolate->factory()->NewStringFromAsciiChecked(
2100 "Reflect.has")));
2101 }
2102
2103 Handle<Name> name;
2104 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
2105 Object::ToName(isolate, key));
2106
2107 Maybe<bool> result =
2108 JSReceiver::HasProperty(Handle<JSReceiver>::cast(target), name);
2109 return result.IsJust() ? *isolate->factory()->ToBoolean(result.FromJust())
2110 : isolate->heap()->exception();
2111 }
2112
2113 // ES6 section 26.1.10 Reflect.isExtensible
2114 BUILTIN(ReflectIsExtensible) {
2115 HandleScope scope(isolate);
2116 DCHECK_EQ(2, args.length());
2117 Handle<Object> target = args.at<Object>(1);
2118
2119 if (!target->IsJSReceiver()) {
2120 THROW_NEW_ERROR_RETURN_FAILURE(
2121 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2122 isolate->factory()->NewStringFromAsciiChecked(
2123 "Reflect.isExtensible")));
2124 }
2125
2126 Maybe<bool> result =
2127 JSReceiver::IsExtensible(Handle<JSReceiver>::cast(target));
2128 MAYBE_RETURN(result, isolate->heap()->exception());
2129 return *isolate->factory()->ToBoolean(result.FromJust());
2130 }
2131
2132 // ES6 section 26.1.11 Reflect.ownKeys
2133 BUILTIN(ReflectOwnKeys) {
2134 HandleScope scope(isolate);
2135 DCHECK_EQ(2, args.length());
2136 Handle<Object> target = args.at<Object>(1);
2137
2138 if (!target->IsJSReceiver()) {
2139 THROW_NEW_ERROR_RETURN_FAILURE(
2140 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2141 isolate->factory()->NewStringFromAsciiChecked(
2142 "Reflect.ownKeys")));
2143 }
2144
2145 Handle<FixedArray> keys;
2146 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2147 isolate, keys,
2148 KeyAccumulator::GetKeys(Handle<JSReceiver>::cast(target),
2149 KeyCollectionMode::kOwnOnly, ALL_PROPERTIES,
2150 GetKeysConversion::kConvertToString));
2151 return *isolate->factory()->NewJSArrayWithElements(keys);
2152 }
2153
2154 // ES6 section 26.1.12 Reflect.preventExtensions
2155 BUILTIN(ReflectPreventExtensions) {
2156 HandleScope scope(isolate);
2157 DCHECK_EQ(2, args.length());
2158 Handle<Object> target = args.at<Object>(1);
2159
2160 if (!target->IsJSReceiver()) {
2161 THROW_NEW_ERROR_RETURN_FAILURE(
2162 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2163 isolate->factory()->NewStringFromAsciiChecked(
2164 "Reflect.preventExtensions")));
2165 }
2166
2167 Maybe<bool> result = JSReceiver::PreventExtensions(
2168 Handle<JSReceiver>::cast(target), Object::DONT_THROW);
2169 MAYBE_RETURN(result, isolate->heap()->exception());
2170 return *isolate->factory()->ToBoolean(result.FromJust());
2171 }
2172
2173 // ES6 section 26.1.13 Reflect.set
2174 BUILTIN(ReflectSet) {
2175 HandleScope scope(isolate);
2176 Handle<Object> target = args.atOrUndefined(isolate, 1);
2177 Handle<Object> key = args.atOrUndefined(isolate, 2);
2178 Handle<Object> value = args.atOrUndefined(isolate, 3);
2179 Handle<Object> receiver = args.length() > 4 ? args.at<Object>(4) : target;
2180
2181 if (!target->IsJSReceiver()) {
2182 THROW_NEW_ERROR_RETURN_FAILURE(
2183 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2184 isolate->factory()->NewStringFromAsciiChecked(
2185 "Reflect.set")));
2186 }
2187
2188 Handle<Name> name;
2189 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
2190 Object::ToName(isolate, key));
2191
2192 LookupIterator it = LookupIterator::PropertyOrElement(
2193 isolate, receiver, name, Handle<JSReceiver>::cast(target));
2194 Maybe<bool> result = Object::SetSuperProperty(
2195 &it, value, SLOPPY, Object::MAY_BE_STORE_FROM_KEYED);
2196 MAYBE_RETURN(result, isolate->heap()->exception());
2197 return *isolate->factory()->ToBoolean(result.FromJust());
2198 }
2199
2200 // ES6 section 26.1.14 Reflect.setPrototypeOf
2201 BUILTIN(ReflectSetPrototypeOf) {
2202 HandleScope scope(isolate);
2203 DCHECK_EQ(3, args.length());
2204 Handle<Object> target = args.at<Object>(1);
2205 Handle<Object> proto = args.at<Object>(2);
2206
2207 if (!target->IsJSReceiver()) {
2208 THROW_NEW_ERROR_RETURN_FAILURE(
2209 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2210 isolate->factory()->NewStringFromAsciiChecked(
2211 "Reflect.setPrototypeOf")));
2212 }
2213
2214 if (!proto->IsJSReceiver() && !proto->IsNull(isolate)) {
2215 THROW_NEW_ERROR_RETURN_FAILURE(
2216 isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, proto));
2217 }
2218
2219 Maybe<bool> result = JSReceiver::SetPrototype(
2220 Handle<JSReceiver>::cast(target), proto, true, Object::DONT_THROW);
2221 MAYBE_RETURN(result, isolate->heap()->exception());
2222 return *isolate->factory()->ToBoolean(result.FromJust());
2223 }
2224
2225 // -----------------------------------------------------------------------------
2226 // ES6 section 19.3 Boolean Objects
2227
2228 // ES6 section 19.3.1.1 Boolean ( value ) for the [[Call]] case.
2229 BUILTIN(BooleanConstructor) {
2230 HandleScope scope(isolate);
2231 Handle<Object> value = args.atOrUndefined(isolate, 1);
2232 return isolate->heap()->ToBoolean(value->BooleanValue());
2233 }
2234
2235 // ES6 section 19.3.1.1 Boolean ( value ) for the [[Construct]] case.
2236 BUILTIN(BooleanConstructor_ConstructStub) {
2237 HandleScope scope(isolate);
2238 Handle<Object> value = args.atOrUndefined(isolate, 1);
2239 Handle<JSFunction> target = args.target<JSFunction>();
2240 Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
2241 DCHECK(*target == target->native_context()->boolean_function());
2242 Handle<JSObject> result;
2243 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
2244 JSObject::New(target, new_target));
2245 Handle<JSValue>::cast(result)->set_value(
2246 isolate->heap()->ToBoolean(value->BooleanValue()));
2247 return *result;
2248 }
2249
2250 // ES6 section 19.3.3.2 Boolean.prototype.toString ( )
2251 void Builtins::Generate_BooleanPrototypeToString(CodeStubAssembler* assembler) {
2252 typedef compiler::Node Node;
2253
2254 Node* receiver = assembler->Parameter(0);
2255 Node* context = assembler->Parameter(3);
2256
2257 Node* value = assembler->ToThisValue(
2258 context, receiver, PrimitiveType::kBoolean, "Boolean.prototype.toString");
2259 Node* result = assembler->LoadObjectField(value, Oddball::kToStringOffset);
2260 assembler->Return(result);
2261 }
2262
2263 // ES6 section 19.3.3.3 Boolean.prototype.valueOf ( )
2264 void Builtins::Generate_BooleanPrototypeValueOf(CodeStubAssembler* assembler) {
2265 typedef compiler::Node Node;
2266
2267 Node* receiver = assembler->Parameter(0);
2268 Node* context = assembler->Parameter(3);
2269
2270 Node* result = assembler->ToThisValue(
2271 context, receiver, PrimitiveType::kBoolean, "Boolean.prototype.valueOf");
2272 assembler->Return(result);
2273 }
2274
2275 // -----------------------------------------------------------------------------
2276 // ES6 section 24.2 DataView Objects
2277
2278 // ES6 section 24.2.2 The DataView Constructor for the [[Call]] case.
2279 BUILTIN(DataViewConstructor) {
2280 HandleScope scope(isolate);
2281 THROW_NEW_ERROR_RETURN_FAILURE(
2282 isolate,
2283 NewTypeError(MessageTemplate::kConstructorNotFunction,
2284 isolate->factory()->NewStringFromAsciiChecked("DataView")));
2285 }
2286
2287 // ES6 section 24.2.2 The DataView Constructor for the [[Construct]] case.
2288 BUILTIN(DataViewConstructor_ConstructStub) {
2289 HandleScope scope(isolate);
2290 Handle<JSFunction> target = args.target<JSFunction>();
2291 Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
2292 Handle<Object> buffer = args.atOrUndefined(isolate, 1);
2293 Handle<Object> byte_offset = args.atOrUndefined(isolate, 2);
2294 Handle<Object> byte_length = args.atOrUndefined(isolate, 3);
2295
2296 // 2. If Type(buffer) is not Object, throw a TypeError exception.
2297 // 3. If buffer does not have an [[ArrayBufferData]] internal slot, throw a
2298 // TypeError exception.
2299 if (!buffer->IsJSArrayBuffer()) {
2300 THROW_NEW_ERROR_RETURN_FAILURE(
2301 isolate, NewTypeError(MessageTemplate::kDataViewNotArrayBuffer));
2302 }
2303 Handle<JSArrayBuffer> array_buffer = Handle<JSArrayBuffer>::cast(buffer);
2304
2305 // 4. Let numberOffset be ? ToNumber(byteOffset).
2306 Handle<Object> number_offset;
2307 if (byte_offset->IsUndefined(isolate)) {
2308 // We intentionally violate the specification at this point to allow
2309 // for new DataView(buffer) invocations to be equivalent to the full
2310 // new DataView(buffer, 0) invocation.
2311 number_offset = handle(Smi::FromInt(0), isolate);
2312 } else {
2313 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, number_offset,
2314 Object::ToNumber(byte_offset));
2315 }
2316
2317 // 5. Let offset be ToInteger(numberOffset).
2318 Handle<Object> offset;
2319 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, offset,
2320 Object::ToInteger(isolate, number_offset));
2321
2322 // 6. If numberOffset ≠ offset or offset < 0, throw a RangeError exception.
2323 if (number_offset->Number() != offset->Number() || offset->Number() < 0.0) {
2324 THROW_NEW_ERROR_RETURN_FAILURE(
2325 isolate, NewRangeError(MessageTemplate::kInvalidDataViewOffset));
2326 }
2327
2328 // 7. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
2329 // We currently violate the specification at this point.
2330
2331 // 8. Let bufferByteLength be the value of buffer's [[ArrayBufferByteLength]]
2332 // internal slot.
2333 double const buffer_byte_length = array_buffer->byte_length()->Number();
2334
2335 // 9. If offset > bufferByteLength, throw a RangeError exception
2336 if (offset->Number() > buffer_byte_length) {
2337 THROW_NEW_ERROR_RETURN_FAILURE(
2338 isolate, NewRangeError(MessageTemplate::kInvalidDataViewOffset));
2339 }
2340
2341 Handle<Object> view_byte_length;
2342 if (byte_length->IsUndefined(isolate)) {
2343 // 10. If byteLength is undefined, then
2344 // a. Let viewByteLength be bufferByteLength - offset.
2345 view_byte_length =
2346 isolate->factory()->NewNumber(buffer_byte_length - offset->Number());
2347 } else {
2348 // 11. Else,
2349 // a. Let viewByteLength be ? ToLength(byteLength).
2350 // b. If offset+viewByteLength > bufferByteLength, throw a RangeError
2351 // exception
2352 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, view_byte_length,
2353 Object::ToLength(isolate, byte_length));
2354 if (offset->Number() + view_byte_length->Number() > buffer_byte_length) {
2355 THROW_NEW_ERROR_RETURN_FAILURE(
2356 isolate, NewRangeError(MessageTemplate::kInvalidDataViewLength));
2357 }
2358 }
2359
2360 // 12. Let O be ? OrdinaryCreateFromConstructor(NewTarget,
2361 // "%DataViewPrototype%", «[[DataView]], [[ViewedArrayBuffer]],
2362 // [[ByteLength]], [[ByteOffset]]»).
2363 // 13. Set O's [[DataView]] internal slot to true.
2364 Handle<JSObject> result;
2365 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
2366 JSObject::New(target, new_target));
2367 for (int i = 0; i < ArrayBufferView::kInternalFieldCount; ++i) {
2368 Handle<JSDataView>::cast(result)->SetInternalField(i, Smi::FromInt(0));
2369 }
2370
2371 // 14. Set O's [[ViewedArrayBuffer]] internal slot to buffer.
2372 Handle<JSDataView>::cast(result)->set_buffer(*array_buffer);
2373
2374 // 15. Set O's [[ByteLength]] internal slot to viewByteLength.
2375 Handle<JSDataView>::cast(result)->set_byte_length(*view_byte_length);
2376
2377 // 16. Set O's [[ByteOffset]] internal slot to offset.
2378 Handle<JSDataView>::cast(result)->set_byte_offset(*offset);
2379
2380 // 17. Return O.
2381 return *result;
2382 }
2383
2384 // ES6 section 24.2.4.1 get DataView.prototype.buffer
2385 BUILTIN(DataViewPrototypeGetBuffer) {
2386 HandleScope scope(isolate);
2387 CHECK_RECEIVER(JSDataView, data_view, "get DataView.prototype.buffer");
2388 return data_view->buffer();
2389 }
2390
2391 // ES6 section 24.2.4.2 get DataView.prototype.byteLength
2392 BUILTIN(DataViewPrototypeGetByteLength) {
2393 HandleScope scope(isolate);
2394 CHECK_RECEIVER(JSDataView, data_view, "get DataView.prototype.byteLength");
2395 // TODO(bmeurer): According to the ES6 spec, we should throw a TypeError
2396 // here if the JSArrayBuffer of the {data_view} was neutered.
2397 return data_view->byte_length();
2398 }
2399
2400 // ES6 section 24.2.4.3 get DataView.prototype.byteOffset
2401 BUILTIN(DataViewPrototypeGetByteOffset) {
2402 HandleScope scope(isolate);
2403 CHECK_RECEIVER(JSDataView, data_view, "get DataView.prototype.byteOffset");
2404 // TODO(bmeurer): According to the ES6 spec, we should throw a TypeError
2405 // here if the JSArrayBuffer of the {data_view} was neutered.
2406 return data_view->byte_offset();
2407 }
2408
2409 // -----------------------------------------------------------------------------
2410 // ES6 section 22.2 TypedArray Objects
2411
2412 // ES6 section 22.2.3.1 get %TypedArray%.prototype.buffer
2413 BUILTIN(TypedArrayPrototypeBuffer) {
2414 HandleScope scope(isolate);
2415 CHECK_RECEIVER(JSTypedArray, typed_array, "get TypedArray.prototype.buffer");
2416 return *typed_array->GetBuffer();
2417 }
2418
2419 namespace {
2420
2421 void Generate_TypedArrayProtoypeGetter(CodeStubAssembler* assembler,
2422 const char* method_name,
2423 int object_offset) {
2424 typedef CodeStubAssembler::Label Label;
2425 typedef compiler::Node Node;
2426
2427 Node* receiver = assembler->Parameter(0);
2428 Node* context = assembler->Parameter(3);
2429
2430 // Check if the {receiver} is actually a JSTypedArray.
2431 Label if_receiverisincompatible(assembler, Label::kDeferred);
2432 assembler->GotoIf(assembler->WordIsSmi(receiver), &if_receiverisincompatible);
2433 Node* receiver_instance_type = assembler->LoadInstanceType(receiver);
2434 assembler->GotoUnless(
2435 assembler->Word32Equal(receiver_instance_type,
2436 assembler->Int32Constant(JS_TYPED_ARRAY_TYPE)),
2437 &if_receiverisincompatible);
2438
2439 // Check if the {receiver}'s JSArrayBuffer was neutered.
2440 Node* receiver_buffer =
2441 assembler->LoadObjectField(receiver, JSTypedArray::kBufferOffset);
2442 Node* receiver_buffer_bit_field = assembler->LoadObjectField(
2443 receiver_buffer, JSArrayBuffer::kBitFieldOffset, MachineType::Uint32());
2444 Label if_receiverisneutered(assembler, Label::kDeferred);
2445 assembler->GotoUnless(
2446 assembler->Word32Equal(
2447 assembler->Word32And(
2448 receiver_buffer_bit_field,
2449 assembler->Int32Constant(JSArrayBuffer::WasNeutered::kMask)),
2450 assembler->Int32Constant(0)),
2451 &if_receiverisneutered);
2452 assembler->Return(assembler->LoadObjectField(receiver, object_offset));
2453
2454 assembler->Bind(&if_receiverisneutered);
2455 {
2456 // The {receiver}s buffer was neutered, default to zero.
2457 assembler->Return(assembler->SmiConstant(0));
2458 }
2459
2460 assembler->Bind(&if_receiverisincompatible);
2461 {
2462 // The {receiver} is not a valid JSGeneratorObject.
2463 Node* result = assembler->CallRuntime(
2464 Runtime::kThrowIncompatibleMethodReceiver, context,
2465 assembler->HeapConstant(assembler->factory()->NewStringFromAsciiChecked(
2466 method_name, TENURED)),
2467 receiver);
2468 assembler->Return(result); // Never reached.
2469 }
2470 }
2471
2472 } // namespace
2473
2474 // ES6 section 22.2.3.2 get %TypedArray%.prototype.byteLength
2475 void Builtins::Generate_TypedArrayPrototypeByteLength(
2476 CodeStubAssembler* assembler) {
2477 Generate_TypedArrayProtoypeGetter(assembler,
2478 "get TypedArray.prototype.byteLength",
2479 JSTypedArray::kByteLengthOffset);
2480 }
2481
2482 // ES6 section 22.2.3.3 get %TypedArray%.prototype.byteOffset
2483 void Builtins::Generate_TypedArrayPrototypeByteOffset(
2484 CodeStubAssembler* assembler) {
2485 Generate_TypedArrayProtoypeGetter(assembler,
2486 "get TypedArray.prototype.byteOffset",
2487 JSTypedArray::kByteOffsetOffset);
2488 }
2489
2490 // ES6 section 22.2.3.18 get %TypedArray%.prototype.length
2491 void Builtins::Generate_TypedArrayPrototypeLength(
2492 CodeStubAssembler* assembler) {
2493 Generate_TypedArrayProtoypeGetter(assembler,
2494 "get TypedArray.prototype.length",
2495 JSTypedArray::kLengthOffset);
2496 }
2497
2498 // -----------------------------------------------------------------------------
2499 // ES6 section 20.3 Date Objects
2500
2501 namespace {
2502
2503 // ES6 section 20.3.1.1 Time Values and Time Range
2504 const double kMinYear = -1000000.0;
2505 const double kMaxYear = -kMinYear;
2506 const double kMinMonth = -10000000.0;
2507 const double kMaxMonth = -kMinMonth;
2508
2509 // 20.3.1.2 Day Number and Time within Day
2510 const double kMsPerDay = 86400000.0;
2511
2512 // ES6 section 20.3.1.11 Hours, Minutes, Second, and Milliseconds
2513 const double kMsPerSecond = 1000.0;
2514 const double kMsPerMinute = 60000.0;
2515 const double kMsPerHour = 3600000.0;
2516
2517 // ES6 section 20.3.1.14 MakeDate (day, time)
2518 double MakeDate(double day, double time) {
2519 if (std::isfinite(day) && std::isfinite(time)) {
2520 return time + day * kMsPerDay;
2521 }
2522 return std::numeric_limits<double>::quiet_NaN();
2523 }
2524
2525 // ES6 section 20.3.1.13 MakeDay (year, month, date)
2526 double MakeDay(double year, double month, double date) {
2527 if ((kMinYear <= year && year <= kMaxYear) &&
2528 (kMinMonth <= month && month <= kMaxMonth) && std::isfinite(date)) {
2529 int y = FastD2I(year);
2530 int m = FastD2I(month);
2531 y += m / 12;
2532 m %= 12;
2533 if (m < 0) {
2534 m += 12;
2535 y -= 1;
2536 }
2537 DCHECK_LE(0, m);
2538 DCHECK_LT(m, 12);
2539
2540 // kYearDelta is an arbitrary number such that:
2541 // a) kYearDelta = -1 (mod 400)
2542 // b) year + kYearDelta > 0 for years in the range defined by
2543 // ECMA 262 - 15.9.1.1, i.e. upto 100,000,000 days on either side of
2544 // Jan 1 1970. This is required so that we don't run into integer
2545 // division of negative numbers.
2546 // c) there shouldn't be an overflow for 32-bit integers in the following
2547 // operations.
2548 static const int kYearDelta = 399999;
2549 static const int kBaseDay =
2550 365 * (1970 + kYearDelta) + (1970 + kYearDelta) / 4 -
2551 (1970 + kYearDelta) / 100 + (1970 + kYearDelta) / 400;
2552 int day_from_year = 365 * (y + kYearDelta) + (y + kYearDelta) / 4 -
2553 (y + kYearDelta) / 100 + (y + kYearDelta) / 400 -
2554 kBaseDay;
2555 if ((y % 4 != 0) || (y % 100 == 0 && y % 400 != 0)) {
2556 static const int kDayFromMonth[] = {0, 31, 59, 90, 120, 151,
2557 181, 212, 243, 273, 304, 334};
2558 day_from_year += kDayFromMonth[m];
2559 } else {
2560 static const int kDayFromMonth[] = {0, 31, 60, 91, 121, 152,
2561 182, 213, 244, 274, 305, 335};
2562 day_from_year += kDayFromMonth[m];
2563 }
2564 return static_cast<double>(day_from_year - 1) + date;
2565 }
2566 return std::numeric_limits<double>::quiet_NaN();
2567 }
2568
2569 // ES6 section 20.3.1.12 MakeTime (hour, min, sec, ms)
2570 double MakeTime(double hour, double min, double sec, double ms) {
2571 if (std::isfinite(hour) && std::isfinite(min) && std::isfinite(sec) &&
2572 std::isfinite(ms)) {
2573 double const h = DoubleToInteger(hour);
2574 double const m = DoubleToInteger(min);
2575 double const s = DoubleToInteger(sec);
2576 double const milli = DoubleToInteger(ms);
2577 return h * kMsPerHour + m * kMsPerMinute + s * kMsPerSecond + milli;
2578 }
2579 return std::numeric_limits<double>::quiet_NaN();
2580 }
2581
2582 // ES6 section 20.3.1.15 TimeClip (time)
2583 double TimeClip(double time) {
2584 if (-DateCache::kMaxTimeInMs <= time && time <= DateCache::kMaxTimeInMs) {
2585 return DoubleToInteger(time) + 0.0;
2586 }
2587 return std::numeric_limits<double>::quiet_NaN();
2588 }
2589
2590 const char* kShortWeekDays[] = {"Sun", "Mon", "Tue", "Wed",
2591 "Thu", "Fri", "Sat"};
2592 const char* kShortMonths[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
2593 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
2594
2595 // ES6 section 20.3.1.16 Date Time String Format
2596 double ParseDateTimeString(Handle<String> str) {
2597 Isolate* const isolate = str->GetIsolate();
2598 str = String::Flatten(str);
2599 // TODO(bmeurer): Change DateParser to not use the FixedArray.
2600 Handle<FixedArray> tmp =
2601 isolate->factory()->NewFixedArray(DateParser::OUTPUT_SIZE);
2602 DisallowHeapAllocation no_gc;
2603 String::FlatContent str_content = str->GetFlatContent();
2604 bool result;
2605 if (str_content.IsOneByte()) {
2606 result = DateParser::Parse(isolate, str_content.ToOneByteVector(), *tmp);
2607 } else {
2608 result = DateParser::Parse(isolate, str_content.ToUC16Vector(), *tmp);
2609 }
2610 if (!result) return std::numeric_limits<double>::quiet_NaN();
2611 double const day = MakeDay(tmp->get(0)->Number(), tmp->get(1)->Number(),
2612 tmp->get(2)->Number());
2613 double const time = MakeTime(tmp->get(3)->Number(), tmp->get(4)->Number(),
2614 tmp->get(5)->Number(), tmp->get(6)->Number());
2615 double date = MakeDate(day, time);
2616 if (tmp->get(7)->IsNull(isolate)) {
2617 if (!std::isnan(date)) {
2618 date = isolate->date_cache()->ToUTC(static_cast<int64_t>(date));
2619 }
2620 } else {
2621 date -= tmp->get(7)->Number() * 1000.0;
2622 }
2623 return date;
2624 }
2625
2626 enum ToDateStringMode { kDateOnly, kTimeOnly, kDateAndTime };
2627
2628 // ES6 section 20.3.4.41.1 ToDateString(tv)
2629 void ToDateString(double time_val, Vector<char> str, DateCache* date_cache,
2630 ToDateStringMode mode = kDateAndTime) {
2631 if (std::isnan(time_val)) {
2632 SNPrintF(str, "Invalid Date");
2633 return;
2634 }
2635 int64_t time_ms = static_cast<int64_t>(time_val);
2636 int64_t local_time_ms = date_cache->ToLocal(time_ms);
2637 int year, month, day, weekday, hour, min, sec, ms;
2638 date_cache->BreakDownTime(local_time_ms, &year, &month, &day, &weekday, &hour,
2639 &min, &sec, &ms);
2640 int timezone_offset = -date_cache->TimezoneOffset(time_ms);
2641 int timezone_hour = std::abs(timezone_offset) / 60;
2642 int timezone_min = std::abs(timezone_offset) % 60;
2643 const char* local_timezone = date_cache->LocalTimezone(time_ms);
2644 switch (mode) {
2645 case kDateOnly:
2646 SNPrintF(str, "%s %s %02d %4d", kShortWeekDays[weekday],
2647 kShortMonths[month], day, year);
2648 return;
2649 case kTimeOnly:
2650 SNPrintF(str, "%02d:%02d:%02d GMT%c%02d%02d (%s)", hour, min, sec,
2651 (timezone_offset < 0) ? '-' : '+', timezone_hour, timezone_min,
2652 local_timezone);
2653 return;
2654 case kDateAndTime:
2655 SNPrintF(str, "%s %s %02d %4d %02d:%02d:%02d GMT%c%02d%02d (%s)",
2656 kShortWeekDays[weekday], kShortMonths[month], day, year, hour,
2657 min, sec, (timezone_offset < 0) ? '-' : '+', timezone_hour,
2658 timezone_min, local_timezone);
2659 return;
2660 }
2661 UNREACHABLE();
2662 }
2663
2664 Object* SetLocalDateValue(Handle<JSDate> date, double time_val) {
2665 if (time_val >= -DateCache::kMaxTimeBeforeUTCInMs &&
2666 time_val <= DateCache::kMaxTimeBeforeUTCInMs) {
2667 Isolate* const isolate = date->GetIsolate();
2668 time_val = isolate->date_cache()->ToUTC(static_cast<int64_t>(time_val));
2669 } else {
2670 time_val = std::numeric_limits<double>::quiet_NaN();
2671 }
2672 return *JSDate::SetValue(date, TimeClip(time_val));
2673 }
2674
2675 } // namespace
2676
2677 // ES6 section 20.3.2 The Date Constructor for the [[Call]] case.
2678 BUILTIN(DateConstructor) {
2679 HandleScope scope(isolate);
2680 double const time_val = JSDate::CurrentTimeValue(isolate);
2681 char buffer[128];
2682 ToDateString(time_val, ArrayVector(buffer), isolate->date_cache());
2683 RETURN_RESULT_OR_FAILURE(
2684 isolate, isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
2685 }
2686
2687 // ES6 section 20.3.2 The Date Constructor for the [[Construct]] case.
2688 BUILTIN(DateConstructor_ConstructStub) {
2689 HandleScope scope(isolate);
2690 int const argc = args.length() - 1;
2691 Handle<JSFunction> target = args.target<JSFunction>();
2692 Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
2693 double time_val;
2694 if (argc == 0) {
2695 time_val = JSDate::CurrentTimeValue(isolate);
2696 } else if (argc == 1) {
2697 Handle<Object> value = args.at<Object>(1);
2698 if (value->IsJSDate()) {
2699 time_val = Handle<JSDate>::cast(value)->value()->Number();
2700 } else {
2701 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
2702 Object::ToPrimitive(value));
2703 if (value->IsString()) {
2704 time_val = ParseDateTimeString(Handle<String>::cast(value));
2705 } else {
2706 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
2707 Object::ToNumber(value));
2708 time_val = value->Number();
2709 }
2710 }
2711 } else {
2712 Handle<Object> year_object;
2713 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year_object,
2714 Object::ToNumber(args.at<Object>(1)));
2715 Handle<Object> month_object;
2716 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month_object,
2717 Object::ToNumber(args.at<Object>(2)));
2718 double year = year_object->Number();
2719 double month = month_object->Number();
2720 double date = 1.0, hours = 0.0, minutes = 0.0, seconds = 0.0, ms = 0.0;
2721 if (argc >= 3) {
2722 Handle<Object> date_object;
2723 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date_object,
2724 Object::ToNumber(args.at<Object>(3)));
2725 date = date_object->Number();
2726 if (argc >= 4) {
2727 Handle<Object> hours_object;
2728 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2729 isolate, hours_object, Object::ToNumber(args.at<Object>(4)));
2730 hours = hours_object->Number();
2731 if (argc >= 5) {
2732 Handle<Object> minutes_object;
2733 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2734 isolate, minutes_object, Object::ToNumber(args.at<Object>(5)));
2735 minutes = minutes_object->Number();
2736 if (argc >= 6) {
2737 Handle<Object> seconds_object;
2738 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2739 isolate, seconds_object, Object::ToNumber(args.at<Object>(6)));
2740 seconds = seconds_object->Number();
2741 if (argc >= 7) {
2742 Handle<Object> ms_object;
2743 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2744 isolate, ms_object, Object::ToNumber(args.at<Object>(7)));
2745 ms = ms_object->Number();
2746 }
2747 }
2748 }
2749 }
2750 }
2751 if (!std::isnan(year)) {
2752 double const y = DoubleToInteger(year);
2753 if (0.0 <= y && y <= 99) year = 1900 + y;
2754 }
2755 double const day = MakeDay(year, month, date);
2756 double const time = MakeTime(hours, minutes, seconds, ms);
2757 time_val = MakeDate(day, time);
2758 if (time_val >= -DateCache::kMaxTimeBeforeUTCInMs &&
2759 time_val <= DateCache::kMaxTimeBeforeUTCInMs) {
2760 time_val = isolate->date_cache()->ToUTC(static_cast<int64_t>(time_val));
2761 } else {
2762 time_val = std::numeric_limits<double>::quiet_NaN();
2763 }
2764 }
2765 RETURN_RESULT_OR_FAILURE(isolate, JSDate::New(target, new_target, time_val));
2766 }
2767
2768 // ES6 section 20.3.3.1 Date.now ( )
2769 BUILTIN(DateNow) {
2770 HandleScope scope(isolate);
2771 return *isolate->factory()->NewNumber(JSDate::CurrentTimeValue(isolate));
2772 }
2773
2774 // ES6 section 20.3.3.2 Date.parse ( string )
2775 BUILTIN(DateParse) {
2776 HandleScope scope(isolate);
2777 Handle<String> string;
2778 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2779 isolate, string,
2780 Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
2781 return *isolate->factory()->NewNumber(ParseDateTimeString(string));
2782 }
2783
2784 // ES6 section 20.3.3.4 Date.UTC (year,month,date,hours,minutes,seconds,ms)
2785 BUILTIN(DateUTC) {
2786 HandleScope scope(isolate);
2787 int const argc = args.length() - 1;
2788 double year = std::numeric_limits<double>::quiet_NaN();
2789 double month = std::numeric_limits<double>::quiet_NaN();
2790 double date = 1.0, hours = 0.0, minutes = 0.0, seconds = 0.0, ms = 0.0;
2791 if (argc >= 1) {
2792 Handle<Object> year_object;
2793 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year_object,
2794 Object::ToNumber(args.at<Object>(1)));
2795 year = year_object->Number();
2796 if (argc >= 2) {
2797 Handle<Object> month_object;
2798 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month_object,
2799 Object::ToNumber(args.at<Object>(2)));
2800 month = month_object->Number();
2801 if (argc >= 3) {
2802 Handle<Object> date_object;
2803 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2804 isolate, date_object, Object::ToNumber(args.at<Object>(3)));
2805 date = date_object->Number();
2806 if (argc >= 4) {
2807 Handle<Object> hours_object;
2808 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2809 isolate, hours_object, Object::ToNumber(args.at<Object>(4)));
2810 hours = hours_object->Number();
2811 if (argc >= 5) {
2812 Handle<Object> minutes_object;
2813 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2814 isolate, minutes_object, Object::ToNumber(args.at<Object>(5)));
2815 minutes = minutes_object->Number();
2816 if (argc >= 6) {
2817 Handle<Object> seconds_object;
2818 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2819 isolate, seconds_object,
2820 Object::ToNumber(args.at<Object>(6)));
2821 seconds = seconds_object->Number();
2822 if (argc >= 7) {
2823 Handle<Object> ms_object;
2824 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2825 isolate, ms_object, Object::ToNumber(args.at<Object>(7)));
2826 ms = ms_object->Number();
2827 }
2828 }
2829 }
2830 }
2831 }
2832 }
2833 }
2834 if (!std::isnan(year)) {
2835 double const y = DoubleToInteger(year);
2836 if (0.0 <= y && y <= 99) year = 1900 + y;
2837 }
2838 double const day = MakeDay(year, month, date);
2839 double const time = MakeTime(hours, minutes, seconds, ms);
2840 return *isolate->factory()->NewNumber(TimeClip(MakeDate(day, time)));
2841 }
2842
2843 // ES6 section 20.3.4.20 Date.prototype.setDate ( date )
2844 BUILTIN(DatePrototypeSetDate) {
2845 HandleScope scope(isolate);
2846 CHECK_RECEIVER(JSDate, date, "Date.prototype.setDate");
2847 Handle<Object> value = args.atOrUndefined(isolate, 1);
2848 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(value));
2849 double time_val = date->value()->Number();
2850 if (!std::isnan(time_val)) {
2851 int64_t const time_ms = static_cast<int64_t>(time_val);
2852 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
2853 int const days = isolate->date_cache()->DaysFromTime(local_time_ms);
2854 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days);
2855 int year, month, day;
2856 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
2857 time_val = MakeDate(MakeDay(year, month, value->Number()), time_within_day);
2858 }
2859 return SetLocalDateValue(date, time_val);
2860 }
2861
2862 // ES6 section 20.3.4.21 Date.prototype.setFullYear (year, month, date)
2863 BUILTIN(DatePrototypeSetFullYear) {
2864 HandleScope scope(isolate);
2865 CHECK_RECEIVER(JSDate, date, "Date.prototype.setFullYear");
2866 int const argc = args.length() - 1;
2867 Handle<Object> year = args.atOrUndefined(isolate, 1);
2868 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, Object::ToNumber(year));
2869 double y = year->Number(), m = 0.0, dt = 1.0;
2870 int time_within_day = 0;
2871 if (!std::isnan(date->value()->Number())) {
2872 int64_t const time_ms = static_cast<int64_t>(date->value()->Number());
2873 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
2874 int const days = isolate->date_cache()->DaysFromTime(local_time_ms);
2875 time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days);
2876 int year, month, day;
2877 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
2878 m = month;
2879 dt = day;
2880 }
2881 if (argc >= 2) {
2882 Handle<Object> month = args.at<Object>(2);
2883 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month));
2884 m = month->Number();
2885 if (argc >= 3) {
2886 Handle<Object> date = args.at<Object>(3);
2887 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date));
2888 dt = date->Number();
2889 }
2890 }
2891 double time_val = MakeDate(MakeDay(y, m, dt), time_within_day);
2892 return SetLocalDateValue(date, time_val);
2893 }
2894
2895 // ES6 section 20.3.4.22 Date.prototype.setHours(hour, min, sec, ms)
2896 BUILTIN(DatePrototypeSetHours) {
2897 HandleScope scope(isolate);
2898 CHECK_RECEIVER(JSDate, date, "Date.prototype.setHours");
2899 int const argc = args.length() - 1;
2900 Handle<Object> hour = args.atOrUndefined(isolate, 1);
2901 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, hour, Object::ToNumber(hour));
2902 double h = hour->Number();
2903 double time_val = date->value()->Number();
2904 if (!std::isnan(time_val)) {
2905 int64_t const time_ms = static_cast<int64_t>(time_val);
2906 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
2907 int day = isolate->date_cache()->DaysFromTime(local_time_ms);
2908 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day);
2909 double m = (time_within_day / (60 * 1000)) % 60;
2910 double s = (time_within_day / 1000) % 60;
2911 double milli = time_within_day % 1000;
2912 if (argc >= 2) {
2913 Handle<Object> min = args.at<Object>(2);
2914 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min));
2915 m = min->Number();
2916 if (argc >= 3) {
2917 Handle<Object> sec = args.at<Object>(3);
2918 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
2919 s = sec->Number();
2920 if (argc >= 4) {
2921 Handle<Object> ms = args.at<Object>(4);
2922 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
2923 milli = ms->Number();
2924 }
2925 }
2926 }
2927 time_val = MakeDate(day, MakeTime(h, m, s, milli));
2928 }
2929 return SetLocalDateValue(date, time_val);
2930 }
2931
2932 // ES6 section 20.3.4.23 Date.prototype.setMilliseconds(ms)
2933 BUILTIN(DatePrototypeSetMilliseconds) {
2934 HandleScope scope(isolate);
2935 CHECK_RECEIVER(JSDate, date, "Date.prototype.setMilliseconds");
2936 Handle<Object> ms = args.atOrUndefined(isolate, 1);
2937 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
2938 double time_val = date->value()->Number();
2939 if (!std::isnan(time_val)) {
2940 int64_t const time_ms = static_cast<int64_t>(time_val);
2941 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
2942 int day = isolate->date_cache()->DaysFromTime(local_time_ms);
2943 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day);
2944 int h = time_within_day / (60 * 60 * 1000);
2945 int m = (time_within_day / (60 * 1000)) % 60;
2946 int s = (time_within_day / 1000) % 60;
2947 time_val = MakeDate(day, MakeTime(h, m, s, ms->Number()));
2948 }
2949 return SetLocalDateValue(date, time_val);
2950 }
2951
2952 // ES6 section 20.3.4.24 Date.prototype.setMinutes ( min, sec, ms )
2953 BUILTIN(DatePrototypeSetMinutes) {
2954 HandleScope scope(isolate);
2955 CHECK_RECEIVER(JSDate, date, "Date.prototype.setMinutes");
2956 int const argc = args.length() - 1;
2957 Handle<Object> min = args.atOrUndefined(isolate, 1);
2958 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min));
2959 double time_val = date->value()->Number();
2960 if (!std::isnan(time_val)) {
2961 int64_t const time_ms = static_cast<int64_t>(time_val);
2962 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
2963 int day = isolate->date_cache()->DaysFromTime(local_time_ms);
2964 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day);
2965 int h = time_within_day / (60 * 60 * 1000);
2966 double m = min->Number();
2967 double s = (time_within_day / 1000) % 60;
2968 double milli = time_within_day % 1000;
2969 if (argc >= 2) {
2970 Handle<Object> sec = args.at<Object>(2);
2971 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
2972 s = sec->Number();
2973 if (argc >= 3) {
2974 Handle<Object> ms = args.at<Object>(3);
2975 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
2976 milli = ms->Number();
2977 }
2978 }
2979 time_val = MakeDate(day, MakeTime(h, m, s, milli));
2980 }
2981 return SetLocalDateValue(date, time_val);
2982 }
2983
2984 // ES6 section 20.3.4.25 Date.prototype.setMonth ( month, date )
2985 BUILTIN(DatePrototypeSetMonth) {
2986 HandleScope scope(isolate);
2987 CHECK_RECEIVER(JSDate, date, "Date.prototype.setMonth");
2988 int const argc = args.length() - 1;
2989 Handle<Object> month = args.atOrUndefined(isolate, 1);
2990 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month));
2991 double time_val = date->value()->Number();
2992 if (!std::isnan(time_val)) {
2993 int64_t const time_ms = static_cast<int64_t>(time_val);
2994 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
2995 int days = isolate->date_cache()->DaysFromTime(local_time_ms);
2996 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days);
2997 int year, unused, day;
2998 isolate->date_cache()->YearMonthDayFromDays(days, &year, &unused, &day);
2999 double m = month->Number();
3000 double dt = day;
3001 if (argc >= 2) {
3002 Handle<Object> date = args.at<Object>(2);
3003 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date));
3004 dt = date->Number();
3005 }
3006 time_val = MakeDate(MakeDay(year, m, dt), time_within_day);
3007 }
3008 return SetLocalDateValue(date, time_val);
3009 }
3010
3011 // ES6 section 20.3.4.26 Date.prototype.setSeconds ( sec, ms )
3012 BUILTIN(DatePrototypeSetSeconds) {
3013 HandleScope scope(isolate);
3014 CHECK_RECEIVER(JSDate, date, "Date.prototype.setSeconds");
3015 int const argc = args.length() - 1;
3016 Handle<Object> sec = args.atOrUndefined(isolate, 1);
3017 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
3018 double time_val = date->value()->Number();
3019 if (!std::isnan(time_val)) {
3020 int64_t const time_ms = static_cast<int64_t>(time_val);
3021 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
3022 int day = isolate->date_cache()->DaysFromTime(local_time_ms);
3023 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day);
3024 int h = time_within_day / (60 * 60 * 1000);
3025 double m = (time_within_day / (60 * 1000)) % 60;
3026 double s = sec->Number();
3027 double milli = time_within_day % 1000;
3028 if (argc >= 2) {
3029 Handle<Object> ms = args.at<Object>(2);
3030 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3031 milli = ms->Number();
3032 }
3033 time_val = MakeDate(day, MakeTime(h, m, s, milli));
3034 }
3035 return SetLocalDateValue(date, time_val);
3036 }
3037
3038 // ES6 section 20.3.4.27 Date.prototype.setTime ( time )
3039 BUILTIN(DatePrototypeSetTime) {
3040 HandleScope scope(isolate);
3041 CHECK_RECEIVER(JSDate, date, "Date.prototype.setTime");
3042 Handle<Object> value = args.atOrUndefined(isolate, 1);
3043 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(value));
3044 return *JSDate::SetValue(date, TimeClip(value->Number()));
3045 }
3046
3047 // ES6 section 20.3.4.28 Date.prototype.setUTCDate ( date )
3048 BUILTIN(DatePrototypeSetUTCDate) {
3049 HandleScope scope(isolate);
3050 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCDate");
3051 Handle<Object> value = args.atOrUndefined(isolate, 1);
3052 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(value));
3053 if (std::isnan(date->value()->Number())) return date->value();
3054 int64_t const time_ms = static_cast<int64_t>(date->value()->Number());
3055 int const days = isolate->date_cache()->DaysFromTime(time_ms);
3056 int const time_within_day = isolate->date_cache()->TimeInDay(time_ms, days);
3057 int year, month, day;
3058 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
3059 double const time_val =
3060 MakeDate(MakeDay(year, month, value->Number()), time_within_day);
3061 return *JSDate::SetValue(date, TimeClip(time_val));
3062 }
3063
3064 // ES6 section 20.3.4.29 Date.prototype.setUTCFullYear (year, month, date)
3065 BUILTIN(DatePrototypeSetUTCFullYear) {
3066 HandleScope scope(isolate);
3067 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCFullYear");
3068 int const argc = args.length() - 1;
3069 Handle<Object> year = args.atOrUndefined(isolate, 1);
3070 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, Object::ToNumber(year));
3071 double y = year->Number(), m = 0.0, dt = 1.0;
3072 int time_within_day = 0;
3073 if (!std::isnan(date->value()->Number())) {
3074 int64_t const time_ms = static_cast<int64_t>(date->value()->Number());
3075 int const days = isolate->date_cache()->DaysFromTime(time_ms);
3076 time_within_day = isolate->date_cache()->TimeInDay(time_ms, days);
3077 int year, month, day;
3078 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
3079 m = month;
3080 dt = day;
3081 }
3082 if (argc >= 2) {
3083 Handle<Object> month = args.at<Object>(2);
3084 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month));
3085 m = month->Number();
3086 if (argc >= 3) {
3087 Handle<Object> date = args.at<Object>(3);
3088 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date));
3089 dt = date->Number();
3090 }
3091 }
3092 double const time_val = MakeDate(MakeDay(y, m, dt), time_within_day);
3093 return *JSDate::SetValue(date, TimeClip(time_val));
3094 }
3095
3096 // ES6 section 20.3.4.30 Date.prototype.setUTCHours(hour, min, sec, ms)
3097 BUILTIN(DatePrototypeSetUTCHours) {
3098 HandleScope scope(isolate);
3099 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCHours");
3100 int const argc = args.length() - 1;
3101 Handle<Object> hour = args.atOrUndefined(isolate, 1);
3102 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, hour, Object::ToNumber(hour));
3103 double h = hour->Number();
3104 double time_val = date->value()->Number();
3105 if (!std::isnan(time_val)) {
3106 int64_t const time_ms = static_cast<int64_t>(time_val);
3107 int day = isolate->date_cache()->DaysFromTime(time_ms);
3108 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day);
3109 double m = (time_within_day / (60 * 1000)) % 60;
3110 double s = (time_within_day / 1000) % 60;
3111 double milli = time_within_day % 1000;
3112 if (argc >= 2) {
3113 Handle<Object> min = args.at<Object>(2);
3114 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min));
3115 m = min->Number();
3116 if (argc >= 3) {
3117 Handle<Object> sec = args.at<Object>(3);
3118 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
3119 s = sec->Number();
3120 if (argc >= 4) {
3121 Handle<Object> ms = args.at<Object>(4);
3122 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3123 milli = ms->Number();
3124 }
3125 }
3126 }
3127 time_val = MakeDate(day, MakeTime(h, m, s, milli));
3128 }
3129 return *JSDate::SetValue(date, TimeClip(time_val));
3130 }
3131
3132 // ES6 section 20.3.4.31 Date.prototype.setUTCMilliseconds(ms)
3133 BUILTIN(DatePrototypeSetUTCMilliseconds) {
3134 HandleScope scope(isolate);
3135 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMilliseconds");
3136 Handle<Object> ms = args.atOrUndefined(isolate, 1);
3137 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3138 double time_val = date->value()->Number();
3139 if (!std::isnan(time_val)) {
3140 int64_t const time_ms = static_cast<int64_t>(time_val);
3141 int day = isolate->date_cache()->DaysFromTime(time_ms);
3142 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day);
3143 int h = time_within_day / (60 * 60 * 1000);
3144 int m = (time_within_day / (60 * 1000)) % 60;
3145 int s = (time_within_day / 1000) % 60;
3146 time_val = MakeDate(day, MakeTime(h, m, s, ms->Number()));
3147 }
3148 return *JSDate::SetValue(date, TimeClip(time_val));
3149 }
3150
3151 // ES6 section 20.3.4.32 Date.prototype.setUTCMinutes ( min, sec, ms )
3152 BUILTIN(DatePrototypeSetUTCMinutes) {
3153 HandleScope scope(isolate);
3154 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMinutes");
3155 int const argc = args.length() - 1;
3156 Handle<Object> min = args.atOrUndefined(isolate, 1);
3157 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min));
3158 double time_val = date->value()->Number();
3159 if (!std::isnan(time_val)) {
3160 int64_t const time_ms = static_cast<int64_t>(time_val);
3161 int day = isolate->date_cache()->DaysFromTime(time_ms);
3162 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day);
3163 int h = time_within_day / (60 * 60 * 1000);
3164 double m = min->Number();
3165 double s = (time_within_day / 1000) % 60;
3166 double milli = time_within_day % 1000;
3167 if (argc >= 2) {
3168 Handle<Object> sec = args.at<Object>(2);
3169 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
3170 s = sec->Number();
3171 if (argc >= 3) {
3172 Handle<Object> ms = args.at<Object>(3);
3173 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3174 milli = ms->Number();
3175 }
3176 }
3177 time_val = MakeDate(day, MakeTime(h, m, s, milli));
3178 }
3179 return *JSDate::SetValue(date, TimeClip(time_val));
3180 }
3181
3182 // ES6 section 20.3.4.31 Date.prototype.setUTCMonth ( month, date )
3183 BUILTIN(DatePrototypeSetUTCMonth) {
3184 HandleScope scope(isolate);
3185 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMonth");
3186 int const argc = args.length() - 1;
3187 Handle<Object> month = args.atOrUndefined(isolate, 1);
3188 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month));
3189 double time_val = date->value()->Number();
3190 if (!std::isnan(time_val)) {
3191 int64_t const time_ms = static_cast<int64_t>(time_val);
3192 int days = isolate->date_cache()->DaysFromTime(time_ms);
3193 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, days);
3194 int year, unused, day;
3195 isolate->date_cache()->YearMonthDayFromDays(days, &year, &unused, &day);
3196 double m = month->Number();
3197 double dt = day;
3198 if (argc >= 2) {
3199 Handle<Object> date = args.at<Object>(2);
3200 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date));
3201 dt = date->Number();
3202 }
3203 time_val = MakeDate(MakeDay(year, m, dt), time_within_day);
3204 }
3205 return *JSDate::SetValue(date, TimeClip(time_val));
3206 }
3207
3208 // ES6 section 20.3.4.34 Date.prototype.setUTCSeconds ( sec, ms )
3209 BUILTIN(DatePrototypeSetUTCSeconds) {
3210 HandleScope scope(isolate);
3211 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCSeconds");
3212 int const argc = args.length() - 1;
3213 Handle<Object> sec = args.atOrUndefined(isolate, 1);
3214 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
3215 double time_val = date->value()->Number();
3216 if (!std::isnan(time_val)) {
3217 int64_t const time_ms = static_cast<int64_t>(time_val);
3218 int day = isolate->date_cache()->DaysFromTime(time_ms);
3219 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day);
3220 int h = time_within_day / (60 * 60 * 1000);
3221 double m = (time_within_day / (60 * 1000)) % 60;
3222 double s = sec->Number();
3223 double milli = time_within_day % 1000;
3224 if (argc >= 2) {
3225 Handle<Object> ms = args.at<Object>(2);
3226 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3227 milli = ms->Number();
3228 }
3229 time_val = MakeDate(day, MakeTime(h, m, s, milli));
3230 }
3231 return *JSDate::SetValue(date, TimeClip(time_val));
3232 }
3233
3234 // ES6 section 20.3.4.35 Date.prototype.toDateString ( )
3235 BUILTIN(DatePrototypeToDateString) {
3236 HandleScope scope(isolate);
3237 CHECK_RECEIVER(JSDate, date, "Date.prototype.toDateString");
3238 char buffer[128];
3239 ToDateString(date->value()->Number(), ArrayVector(buffer),
3240 isolate->date_cache(), kDateOnly);
3241 RETURN_RESULT_OR_FAILURE(
3242 isolate, isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
3243 }
3244
3245 // ES6 section 20.3.4.36 Date.prototype.toISOString ( )
3246 BUILTIN(DatePrototypeToISOString) {
3247 HandleScope scope(isolate);
3248 CHECK_RECEIVER(JSDate, date, "Date.prototype.toISOString");
3249 double const time_val = date->value()->Number();
3250 if (std::isnan(time_val)) {
3251 THROW_NEW_ERROR_RETURN_FAILURE(
3252 isolate, NewRangeError(MessageTemplate::kInvalidTimeValue));
3253 }
3254 int64_t const time_ms = static_cast<int64_t>(time_val);
3255 int year, month, day, weekday, hour, min, sec, ms;
3256 isolate->date_cache()->BreakDownTime(time_ms, &year, &month, &day, &weekday,
3257 &hour, &min, &sec, &ms);
3258 char buffer[128];
3259 if (year >= 0 && year <= 9999) {
3260 SNPrintF(ArrayVector(buffer), "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", year,
3261 month + 1, day, hour, min, sec, ms);
3262 } else if (year < 0) {
3263 SNPrintF(ArrayVector(buffer), "-%06d-%02d-%02dT%02d:%02d:%02d.%03dZ", -year,
3264 month + 1, day, hour, min, sec, ms);
3265 } else {
3266 SNPrintF(ArrayVector(buffer), "+%06d-%02d-%02dT%02d:%02d:%02d.%03dZ", year,
3267 month + 1, day, hour, min, sec, ms);
3268 }
3269 return *isolate->factory()->NewStringFromAsciiChecked(buffer);
3270 }
3271
3272 // ES6 section 20.3.4.41 Date.prototype.toString ( )
3273 BUILTIN(DatePrototypeToString) {
3274 HandleScope scope(isolate);
3275 CHECK_RECEIVER(JSDate, date, "Date.prototype.toString");
3276 char buffer[128];
3277 ToDateString(date->value()->Number(), ArrayVector(buffer),
3278 isolate->date_cache());
3279 RETURN_RESULT_OR_FAILURE(
3280 isolate, isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
3281 }
3282
3283 // ES6 section 20.3.4.42 Date.prototype.toTimeString ( )
3284 BUILTIN(DatePrototypeToTimeString) {
3285 HandleScope scope(isolate);
3286 CHECK_RECEIVER(JSDate, date, "Date.prototype.toTimeString");
3287 char buffer[128];
3288 ToDateString(date->value()->Number(), ArrayVector(buffer),
3289 isolate->date_cache(), kTimeOnly);
3290 RETURN_RESULT_OR_FAILURE(
3291 isolate, isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
3292 }
3293
3294 // ES6 section 20.3.4.43 Date.prototype.toUTCString ( )
3295 BUILTIN(DatePrototypeToUTCString) {
3296 HandleScope scope(isolate);
3297 CHECK_RECEIVER(JSDate, date, "Date.prototype.toUTCString");
3298 double const time_val = date->value()->Number();
3299 if (std::isnan(time_val)) {
3300 return *isolate->factory()->NewStringFromAsciiChecked("Invalid Date");
3301 }
3302 char buffer[128];
3303 int64_t time_ms = static_cast<int64_t>(time_val);
3304 int year, month, day, weekday, hour, min, sec, ms;
3305 isolate->date_cache()->BreakDownTime(time_ms, &year, &month, &day, &weekday,
3306 &hour, &min, &sec, &ms);
3307 SNPrintF(ArrayVector(buffer), "%s, %02d %s %4d %02d:%02d:%02d GMT",
3308 kShortWeekDays[weekday], day, kShortMonths[month], year, hour, min,
3309 sec);
3310 return *isolate->factory()->NewStringFromAsciiChecked(buffer);
3311 }
3312
3313 // ES6 section 20.3.4.44 Date.prototype.valueOf ( )
3314 BUILTIN(DatePrototypeValueOf) {
3315 HandleScope scope(isolate);
3316 CHECK_RECEIVER(JSDate, date, "Date.prototype.valueOf");
3317 return date->value();
3318 }
3319
3320 // ES6 section 20.3.4.45 Date.prototype [ @@toPrimitive ] ( hint )
3321 BUILTIN(DatePrototypeToPrimitive) {
3322 HandleScope scope(isolate);
3323 DCHECK_EQ(2, args.length());
3324 CHECK_RECEIVER(JSReceiver, receiver, "Date.prototype [ @@toPrimitive ]");
3325 Handle<Object> hint = args.at<Object>(1);
3326 RETURN_RESULT_OR_FAILURE(isolate, JSDate::ToPrimitive(receiver, hint));
3327 }
3328
3329 // ES6 section B.2.4.1 Date.prototype.getYear ( )
3330 BUILTIN(DatePrototypeGetYear) {
3331 HandleScope scope(isolate);
3332 CHECK_RECEIVER(JSDate, date, "Date.prototype.getYear");
3333 double time_val = date->value()->Number();
3334 if (std::isnan(time_val)) return date->value();
3335 int64_t time_ms = static_cast<int64_t>(time_val);
3336 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
3337 int days = isolate->date_cache()->DaysFromTime(local_time_ms);
3338 int year, month, day;
3339 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
3340 return Smi::FromInt(year - 1900);
3341 }
3342
3343 // ES6 section B.2.4.2 Date.prototype.setYear ( year )
3344 BUILTIN(DatePrototypeSetYear) {
3345 HandleScope scope(isolate);
3346 CHECK_RECEIVER(JSDate, date, "Date.prototype.setYear");
3347 Handle<Object> year = args.atOrUndefined(isolate, 1);
3348 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, Object::ToNumber(year));
3349 double m = 0.0, dt = 1.0, y = year->Number();
3350 if (0.0 <= y && y <= 99.0) {
3351 y = 1900.0 + DoubleToInteger(y);
3352 }
3353 int time_within_day = 0;
3354 if (!std::isnan(date->value()->Number())) {
3355 int64_t const time_ms = static_cast<int64_t>(date->value()->Number());
3356 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
3357 int const days = isolate->date_cache()->DaysFromTime(local_time_ms);
3358 time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days);
3359 int year, month, day;
3360 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
3361 m = month;
3362 dt = day;
3363 }
3364 double time_val = MakeDate(MakeDay(y, m, dt), time_within_day);
3365 return SetLocalDateValue(date, time_val);
3366 }
3367
3368 // ES6 section 20.3.4.37 Date.prototype.toJSON ( key )
3369 BUILTIN(DatePrototypeToJson) {
3370 HandleScope scope(isolate);
3371 Handle<Object> receiver = args.atOrUndefined(isolate, 0);
3372 Handle<JSReceiver> receiver_obj;
3373 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver_obj,
3374 Object::ToObject(isolate, receiver));
3375 Handle<Object> primitive;
3376 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3377 isolate, primitive,
3378 Object::ToPrimitive(receiver_obj, ToPrimitiveHint::kNumber));
3379 if (primitive->IsNumber() && !std::isfinite(primitive->Number())) {
3380 return isolate->heap()->null_value();
3381 } else {
3382 Handle<String> name =
3383 isolate->factory()->NewStringFromAsciiChecked("toISOString");
3384 Handle<Object> function;
3385 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, function,
3386 Object::GetProperty(receiver_obj, name));
3387 if (!function->IsCallable()) {
3388 THROW_NEW_ERROR_RETURN_FAILURE(
3389 isolate, NewTypeError(MessageTemplate::kCalledNonCallable, name));
3390 }
3391 RETURN_RESULT_OR_FAILURE(
3392 isolate, Execution::Call(isolate, function, receiver_obj, 0, NULL));
3393 }
3394 }
3395
3396 // static
3397 void Builtins::Generate_DatePrototypeGetDate(MacroAssembler* masm) {
3398 Generate_DatePrototype_GetField(masm, JSDate::kDay);
3399 }
3400
3401 // static
3402 void Builtins::Generate_DatePrototypeGetDay(MacroAssembler* masm) {
3403 Generate_DatePrototype_GetField(masm, JSDate::kWeekday);
3404 }
3405
3406 // static
3407 void Builtins::Generate_DatePrototypeGetFullYear(MacroAssembler* masm) {
3408 Generate_DatePrototype_GetField(masm, JSDate::kYear);
3409 }
3410
3411 // static
3412 void Builtins::Generate_DatePrototypeGetHours(MacroAssembler* masm) {
3413 Generate_DatePrototype_GetField(masm, JSDate::kHour);
3414 }
3415
3416 // static
3417 void Builtins::Generate_DatePrototypeGetMilliseconds(MacroAssembler* masm) {
3418 Generate_DatePrototype_GetField(masm, JSDate::kMillisecond);
3419 }
3420
3421 // static
3422 void Builtins::Generate_DatePrototypeGetMinutes(MacroAssembler* masm) {
3423 Generate_DatePrototype_GetField(masm, JSDate::kMinute);
3424 }
3425
3426 // static
3427 void Builtins::Generate_DatePrototypeGetMonth(MacroAssembler* masm) {
3428 Generate_DatePrototype_GetField(masm, JSDate::kMonth);
3429 }
3430
3431 // static
3432 void Builtins::Generate_DatePrototypeGetSeconds(MacroAssembler* masm) {
3433 Generate_DatePrototype_GetField(masm, JSDate::kSecond);
3434 }
3435
3436 // static
3437 void Builtins::Generate_DatePrototypeGetTime(MacroAssembler* masm) {
3438 Generate_DatePrototype_GetField(masm, JSDate::kDateValue);
3439 }
3440
3441 // static
3442 void Builtins::Generate_DatePrototypeGetTimezoneOffset(MacroAssembler* masm) {
3443 Generate_DatePrototype_GetField(masm, JSDate::kTimezoneOffset);
3444 }
3445
3446 // static
3447 void Builtins::Generate_DatePrototypeGetUTCDate(MacroAssembler* masm) {
3448 Generate_DatePrototype_GetField(masm, JSDate::kDayUTC);
3449 }
3450
3451 // static
3452 void Builtins::Generate_DatePrototypeGetUTCDay(MacroAssembler* masm) {
3453 Generate_DatePrototype_GetField(masm, JSDate::kWeekdayUTC);
3454 }
3455
3456 // static
3457 void Builtins::Generate_DatePrototypeGetUTCFullYear(MacroAssembler* masm) {
3458 Generate_DatePrototype_GetField(masm, JSDate::kYearUTC);
3459 }
3460
3461 // static
3462 void Builtins::Generate_DatePrototypeGetUTCHours(MacroAssembler* masm) {
3463 Generate_DatePrototype_GetField(masm, JSDate::kHourUTC);
3464 }
3465
3466 // static
3467 void Builtins::Generate_DatePrototypeGetUTCMilliseconds(MacroAssembler* masm) {
3468 Generate_DatePrototype_GetField(masm, JSDate::kMillisecondUTC);
3469 }
3470
3471 // static
3472 void Builtins::Generate_DatePrototypeGetUTCMinutes(MacroAssembler* masm) {
3473 Generate_DatePrototype_GetField(masm, JSDate::kMinuteUTC);
3474 }
3475
3476 // static
3477 void Builtins::Generate_DatePrototypeGetUTCMonth(MacroAssembler* masm) {
3478 Generate_DatePrototype_GetField(masm, JSDate::kMonthUTC);
3479 }
3480
3481 // static
3482 void Builtins::Generate_DatePrototypeGetUTCSeconds(MacroAssembler* masm) {
3483 Generate_DatePrototype_GetField(masm, JSDate::kSecondUTC);
3484 }
3485
3486 namespace {
3487
3488 bool AllowDynamicFunction(Isolate* isolate, Handle<JSFunction> target,
3489 Handle<JSObject> target_global_proxy) {
3490 if (FLAG_allow_unsafe_function_constructor) return true;
3491 HandleScopeImplementer* impl = isolate->handle_scope_implementer();
3492 Handle<Context> responsible_context = impl->LastEnteredContext();
3493 if (responsible_context.is_null()) {
3494 responsible_context = impl->MicrotaskContext();
3495 // TODO(jochen): Remove this.
3496 if (responsible_context.is_null()) {
3497 return true;
3498 }
3499 }
3500 if (*responsible_context == target->context()) return true;
3501 return isolate->MayAccess(responsible_context, target_global_proxy);
3502 }
3503
3504 // ES6 section 19.2.1.1.1 CreateDynamicFunction
3505 MaybeHandle<Object> CreateDynamicFunction(Isolate* isolate,
3506 BuiltinArguments args,
3507 const char* token) {
3508 // Compute number of arguments, ignoring the receiver.
3509 DCHECK_LE(1, args.length());
3510 int const argc = args.length() - 1;
3511
3512 Handle<JSFunction> target = args.target<JSFunction>();
3513 Handle<JSObject> target_global_proxy(target->global_proxy(), isolate);
3514
3515 if (!AllowDynamicFunction(isolate, target, target_global_proxy)) {
3516 isolate->CountUsage(v8::Isolate::kFunctionConstructorReturnedUndefined);
3517 return isolate->factory()->undefined_value();
3518 }
3519
3520 // Build the source string.
3521 Handle<String> source;
3522 {
3523 IncrementalStringBuilder builder(isolate);
3524 builder.AppendCharacter('(');
3525 builder.AppendCString(token);
3526 builder.AppendCharacter('(');
3527 bool parenthesis_in_arg_string = false;
3528 if (argc > 1) {
3529 for (int i = 1; i < argc; ++i) {
3530 if (i > 1) builder.AppendCharacter(',');
3531 Handle<String> param;
3532 ASSIGN_RETURN_ON_EXCEPTION(
3533 isolate, param, Object::ToString(isolate, args.at<Object>(i)),
3534 Object);
3535 param = String::Flatten(param);
3536 builder.AppendString(param);
3537 // If the formal parameters string include ) - an illegal
3538 // character - it may make the combined function expression
3539 // compile. We avoid this problem by checking for this early on.
3540 DisallowHeapAllocation no_gc; // Ensure vectors stay valid.
3541 String::FlatContent param_content = param->GetFlatContent();
3542 for (int i = 0, length = param->length(); i < length; ++i) {
3543 if (param_content.Get(i) == ')') {
3544 parenthesis_in_arg_string = true;
3545 break;
3546 }
3547 }
3548 }
3549 // If the formal parameters include an unbalanced block comment, the
3550 // function must be rejected. Since JavaScript does not allow nested
3551 // comments we can include a trailing block comment to catch this.
3552 builder.AppendCString("\n/**/");
3553 }
3554 builder.AppendCString(") {\n");
3555 if (argc > 0) {
3556 Handle<String> body;
3557 ASSIGN_RETURN_ON_EXCEPTION(
3558 isolate, body, Object::ToString(isolate, args.at<Object>(argc)),
3559 Object);
3560 builder.AppendString(body);
3561 }
3562 builder.AppendCString("\n})");
3563 ASSIGN_RETURN_ON_EXCEPTION(isolate, source, builder.Finish(), Object);
3564
3565 // The SyntaxError must be thrown after all the (observable) ToString
3566 // conversions are done.
3567 if (parenthesis_in_arg_string) {
3568 THROW_NEW_ERROR(isolate,
3569 NewSyntaxError(MessageTemplate::kParenthesisInArgString),
3570 Object);
3571 }
3572 }
3573
3574 // Compile the string in the constructor and not a helper so that errors to
3575 // come from here.
3576 Handle<JSFunction> function;
3577 {
3578 ASSIGN_RETURN_ON_EXCEPTION(
3579 isolate, function,
3580 CompileString(handle(target->native_context(), isolate), source,
3581 ONLY_SINGLE_FUNCTION_LITERAL),
3582 Object);
3583 Handle<Object> result;
3584 ASSIGN_RETURN_ON_EXCEPTION(
3585 isolate, result,
3586 Execution::Call(isolate, function, target_global_proxy, 0, nullptr),
3587 Object);
3588 function = Handle<JSFunction>::cast(result);
3589 function->shared()->set_name_should_print_as_anonymous(true);
3590 }
3591
3592 // If new.target is equal to target then the function created
3593 // is already correctly setup and nothing else should be done
3594 // here. But if new.target is not equal to target then we are
3595 // have a Function builtin subclassing case and therefore the
3596 // function has wrong initial map. To fix that we create a new
3597 // function object with correct initial map.
3598 Handle<Object> unchecked_new_target = args.new_target();
3599 if (!unchecked_new_target->IsUndefined(isolate) &&
3600 !unchecked_new_target.is_identical_to(target)) {
3601 Handle<JSReceiver> new_target =
3602 Handle<JSReceiver>::cast(unchecked_new_target);
3603 Handle<Map> initial_map;
3604 ASSIGN_RETURN_ON_EXCEPTION(
3605 isolate, initial_map,
3606 JSFunction::GetDerivedMap(isolate, target, new_target), Object);
3607
3608 Handle<SharedFunctionInfo> shared_info(function->shared(), isolate);
3609 Handle<Map> map = Map::AsLanguageMode(
3610 initial_map, shared_info->language_mode(), shared_info->kind());
3611
3612 Handle<Context> context(function->context(), isolate);
3613 function = isolate->factory()->NewFunctionFromSharedFunctionInfo(
3614 map, shared_info, context, NOT_TENURED);
3615 }
3616 return function;
3617 }
3618
3619 } // namespace
3620
3621 // ES6 section 19.2.1.1 Function ( p1, p2, ... , pn, body )
3622 BUILTIN(FunctionConstructor) {
3623 HandleScope scope(isolate);
3624 Handle<Object> result;
3625 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3626 isolate, result, CreateDynamicFunction(isolate, args, "function"));
3627 return *result;
3628 }
3629
3630 namespace {
3631
3632 Object* DoFunctionBind(Isolate* isolate, BuiltinArguments args) {
3633 HandleScope scope(isolate);
3634 DCHECK_LE(1, args.length());
3635 if (!args.receiver()->IsCallable()) {
3636 THROW_NEW_ERROR_RETURN_FAILURE(
3637 isolate, NewTypeError(MessageTemplate::kFunctionBind));
3638 }
3639
3640 // Allocate the bound function with the given {this_arg} and {args}.
3641 Handle<JSReceiver> target = args.at<JSReceiver>(0);
3642 Handle<Object> this_arg = isolate->factory()->undefined_value();
3643 ScopedVector<Handle<Object>> argv(std::max(0, args.length() - 2));
3644 if (args.length() > 1) {
3645 this_arg = args.at<Object>(1);
3646 for (int i = 2; i < args.length(); ++i) {
3647 argv[i - 2] = args.at<Object>(i);
3648 }
3649 }
3650 Handle<JSBoundFunction> function;
3651 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3652 isolate, function,
3653 isolate->factory()->NewJSBoundFunction(target, this_arg, argv));
3654
3655 LookupIterator length_lookup(target, isolate->factory()->length_string(),
3656 target, LookupIterator::OWN);
3657 // Setup the "length" property based on the "length" of the {target}.
3658 // If the targets length is the default JSFunction accessor, we can keep the
3659 // accessor that's installed by default on the JSBoundFunction. It lazily
3660 // computes the value from the underlying internal length.
3661 if (!target->IsJSFunction() ||
3662 length_lookup.state() != LookupIterator::ACCESSOR ||
3663 !length_lookup.GetAccessors()->IsAccessorInfo()) {
3664 Handle<Object> length(Smi::FromInt(0), isolate);
3665 Maybe<PropertyAttributes> attributes =
3666 JSReceiver::GetPropertyAttributes(&length_lookup);
3667 if (!attributes.IsJust()) return isolate->heap()->exception();
3668 if (attributes.FromJust() != ABSENT) {
3669 Handle<Object> target_length;
3670 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, target_length,
3671 Object::GetProperty(&length_lookup));
3672 if (target_length->IsNumber()) {
3673 length = isolate->factory()->NewNumber(std::max(
3674 0.0, DoubleToInteger(target_length->Number()) - argv.length()));
3675 }
3676 }
3677 LookupIterator it(function, isolate->factory()->length_string(), function);
3678 DCHECK_EQ(LookupIterator::ACCESSOR, it.state());
3679 RETURN_FAILURE_ON_EXCEPTION(isolate,
3680 JSObject::DefineOwnPropertyIgnoreAttributes(
3681 &it, length, it.property_attributes()));
3682 }
3683
3684 // Setup the "name" property based on the "name" of the {target}.
3685 // If the targets name is the default JSFunction accessor, we can keep the
3686 // accessor that's installed by default on the JSBoundFunction. It lazily
3687 // computes the value from the underlying internal name.
3688 LookupIterator name_lookup(target, isolate->factory()->name_string(), target,
3689 LookupIterator::OWN);
3690 if (!target->IsJSFunction() ||
3691 name_lookup.state() != LookupIterator::ACCESSOR ||
3692 !name_lookup.GetAccessors()->IsAccessorInfo()) {
3693 Handle<Object> target_name;
3694 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, target_name,
3695 Object::GetProperty(&name_lookup));
3696 Handle<String> name;
3697 if (target_name->IsString()) {
3698 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3699 isolate, name,
3700 Name::ToFunctionName(Handle<String>::cast(target_name)));
3701 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3702 isolate, name, isolate->factory()->NewConsString(
3703 isolate->factory()->bound__string(), name));
3704 } else {
3705 name = isolate->factory()->bound__string();
3706 }
3707 LookupIterator it(function, isolate->factory()->name_string());
3708 DCHECK_EQ(LookupIterator::ACCESSOR, it.state());
3709 RETURN_FAILURE_ON_EXCEPTION(isolate,
3710 JSObject::DefineOwnPropertyIgnoreAttributes(
3711 &it, name, it.property_attributes()));
3712 }
3713 return *function;
3714 }
3715
3716 } // namespace
3717
3718 // ES6 section 19.2.3.2 Function.prototype.bind ( thisArg, ...args )
3719 BUILTIN(FunctionPrototypeBind) { return DoFunctionBind(isolate, args); }
3720
3721 // TODO(verwaest): This is a temporary helper until the FastFunctionBind stub
3722 // can tailcall to the builtin directly.
3723 RUNTIME_FUNCTION(Runtime_FunctionBind) {
3724 DCHECK_EQ(2, args.length());
3725 Arguments* incoming = reinterpret_cast<Arguments*>(args[0]);
3726 // Rewrap the arguments as builtins arguments.
3727 int argc = incoming->length() + BuiltinArguments::kNumExtraArgsWithReceiver;
3728 BuiltinArguments caller_args(argc, incoming->arguments() + 1);
3729 return DoFunctionBind(isolate, caller_args);
3730 }
3731
3732 // ES6 section 19.2.3.5 Function.prototype.toString ( )
3733 BUILTIN(FunctionPrototypeToString) {
3734 HandleScope scope(isolate);
3735 Handle<Object> receiver = args.receiver();
3736 if (receiver->IsJSBoundFunction()) {
3737 return *JSBoundFunction::ToString(Handle<JSBoundFunction>::cast(receiver));
3738 } else if (receiver->IsJSFunction()) {
3739 return *JSFunction::ToString(Handle<JSFunction>::cast(receiver));
3740 }
3741 THROW_NEW_ERROR_RETURN_FAILURE(
3742 isolate, NewTypeError(MessageTemplate::kNotGeneric,
3743 isolate->factory()->NewStringFromAsciiChecked(
3744 "Function.prototype.toString")));
3745 }
3746
3747 // ES6 section 25.2.1.1 GeneratorFunction (p1, p2, ... , pn, body)
3748 BUILTIN(GeneratorFunctionConstructor) {
3749 HandleScope scope(isolate);
3750 RETURN_RESULT_OR_FAILURE(isolate,
3751 CreateDynamicFunction(isolate, args, "function*"));
3752 }
3753
3754 BUILTIN(AsyncFunctionConstructor) {
3755 HandleScope scope(isolate);
3756 Handle<Object> maybe_func;
3757 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3758 isolate, maybe_func,
3759 CreateDynamicFunction(isolate, args, "async function"));
3760 if (!maybe_func->IsJSFunction()) return *maybe_func;
3761
3762 // Do not lazily compute eval position for AsyncFunction, as they may not be
3763 // determined after the function is resumed.
3764 Handle<JSFunction> func = Handle<JSFunction>::cast(maybe_func);
3765 Handle<Script> script = handle(Script::cast(func->shared()->script()));
3766 int position = script->GetEvalPosition();
3767 USE(position);
3768
3769 return *func;
3770 }
3771
3772 // -----------------------------------------------------------------------------
3773 // ES6 section 19.1 Object Objects
3774
3775 // ES6 section 19.1.3.4 Object.prototype.propertyIsEnumerable ( V )
3776 BUILTIN(ObjectPrototypePropertyIsEnumerable) {
3777 HandleScope scope(isolate);
3778 Handle<JSReceiver> object;
3779 Handle<Name> name;
3780 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3781 isolate, name, Object::ToName(isolate, args.atOrUndefined(isolate, 1)));
3782 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3783 isolate, object, JSReceiver::ToObject(isolate, args.receiver()));
3784 Maybe<PropertyAttributes> maybe =
3785 JSReceiver::GetOwnPropertyAttributes(object, name);
3786 if (!maybe.IsJust()) return isolate->heap()->exception();
3787 if (maybe.FromJust() == ABSENT) return isolate->heap()->false_value();
3788 return isolate->heap()->ToBoolean((maybe.FromJust() & DONT_ENUM) == 0);
3789 }
3790
3791 // -----------------------------------------------------------------------------
3792 // ES6 section 19.4 Symbol Objects
3793
3794 // ES6 section 19.4.1.1 Symbol ( [ description ] ) for the [[Call]] case.
3795 BUILTIN(SymbolConstructor) {
3796 HandleScope scope(isolate);
3797 Handle<Symbol> result = isolate->factory()->NewSymbol();
3798 Handle<Object> description = args.atOrUndefined(isolate, 1);
3799 if (!description->IsUndefined(isolate)) {
3800 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, description,
3801 Object::ToString(isolate, description));
3802 result->set_name(*description);
3803 }
3804 return *result;
3805 }
3806
3807 // ES6 section 19.4.1.1 Symbol ( [ description ] ) for the [[Construct]] case.
3808 BUILTIN(SymbolConstructor_ConstructStub) {
3809 HandleScope scope(isolate);
3810 THROW_NEW_ERROR_RETURN_FAILURE(
3811 isolate, NewTypeError(MessageTemplate::kNotConstructor,
3812 isolate->factory()->Symbol_string()));
3813 }
3814
3815 // ES6 section 19.4.3.4 Symbol.prototype [ @@toPrimitive ] ( hint )
3816 void Builtins::Generate_SymbolPrototypeToPrimitive(
3817 CodeStubAssembler* assembler) {
3818 typedef compiler::Node Node;
3819
3820 Node* receiver = assembler->Parameter(0);
3821 Node* context = assembler->Parameter(4);
3822
3823 Node* result =
3824 assembler->ToThisValue(context, receiver, PrimitiveType::kSymbol,
3825 "Symbol.prototype [ @@toPrimitive ]");
3826 assembler->Return(result);
3827 }
3828
3829 // ES6 section 19.4.3.2 Symbol.prototype.toString ( )
3830 void Builtins::Generate_SymbolPrototypeToString(CodeStubAssembler* assembler) {
3831 typedef compiler::Node Node;
3832
3833 Node* receiver = assembler->Parameter(0);
3834 Node* context = assembler->Parameter(3);
3835
3836 Node* value = assembler->ToThisValue(
3837 context, receiver, PrimitiveType::kSymbol, "Symbol.prototype.toString");
3838 Node* result =
3839 assembler->CallRuntime(Runtime::kSymbolDescriptiveString, context, value);
3840 assembler->Return(result);
3841 }
3842
3843 // ES6 section 19.4.3.3 Symbol.prototype.valueOf ( )
3844 void Builtins::Generate_SymbolPrototypeValueOf(CodeStubAssembler* assembler) {
3845 typedef compiler::Node Node;
3846
3847 Node* receiver = assembler->Parameter(0);
3848 Node* context = assembler->Parameter(3);
3849
3850 Node* result = assembler->ToThisValue(
3851 context, receiver, PrimitiveType::kSymbol, "Symbol.prototype.valueOf");
3852 assembler->Return(result);
3853 }
3854
3855 // -----------------------------------------------------------------------------
3856 // ES6 section 21.1 String Objects
3857
3858 // ES6 section 21.1.2.1 String.fromCharCode ( ...codeUnits )
3859 void Builtins::Generate_StringFromCharCode(CodeStubAssembler* assembler) {
3860 typedef CodeStubAssembler::Label Label;
3861 typedef compiler::Node Node;
3862 typedef CodeStubAssembler::Variable Variable;
3863
3864 Node* code = assembler->Parameter(1);
3865 Node* context = assembler->Parameter(4);
3866
3867 // Check if we have exactly one argument (plus the implicit receiver), i.e.
3868 // if the parent frame is not an arguments adaptor frame.
3869 Label if_oneargument(assembler), if_notoneargument(assembler);
3870 Node* parent_frame_pointer = assembler->LoadParentFramePointer();
3871 Node* parent_frame_type =
3872 assembler->Load(MachineType::Pointer(), parent_frame_pointer,
3873 assembler->IntPtrConstant(
3874 CommonFrameConstants::kContextOrFrameTypeOffset));
3875 assembler->Branch(
3876 assembler->WordEqual(
3877 parent_frame_type,
3878 assembler->SmiConstant(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))),
3879 &if_notoneargument, &if_oneargument);
3880
3881 assembler->Bind(&if_oneargument);
3882 {
3883 // Single argument case, perform fast single character string cache lookup
3884 // for one-byte code units, or fall back to creating a single character
3885 // string on the fly otherwise.
3886 Node* code32 = assembler->TruncateTaggedToWord32(context, code);
3887 Node* code16 = assembler->Word32And(
3888 code32, assembler->Int32Constant(String::kMaxUtf16CodeUnit));
3889 Node* result = assembler->StringFromCharCode(code16);
3890 assembler->Return(result);
3891 }
3892
3893 assembler->Bind(&if_notoneargument);
3894 {
3895 // Determine the resulting string length.
3896 Node* parent_frame_length =
3897 assembler->Load(MachineType::Pointer(), parent_frame_pointer,
3898 assembler->IntPtrConstant(
3899 ArgumentsAdaptorFrameConstants::kLengthOffset));
3900 Node* length = assembler->SmiToWord(parent_frame_length);
3901
3902 // Assume that the resulting string contains only one-byte characters.
3903 Node* result = assembler->AllocateSeqOneByteString(context, length);
3904
3905 // Truncate all input parameters and append them to the resulting string.
3906 Variable var_offset(assembler, MachineType::PointerRepresentation());
3907 Label loop(assembler, &var_offset), done_loop(assembler);
3908 var_offset.Bind(assembler->IntPtrConstant(0));
3909 assembler->Goto(&loop);
3910 assembler->Bind(&loop);
3911 {
3912 // Load the current {offset}.
3913 Node* offset = var_offset.value();
3914
3915 // Check if we're done with the string.
3916 assembler->GotoIf(assembler->WordEqual(offset, length), &done_loop);
3917
3918 // Load the next code point and truncate it to a 16-bit value.
3919 Node* code = assembler->Load(
3920 MachineType::AnyTagged(), parent_frame_pointer,
3921 assembler->IntPtrAdd(
3922 assembler->WordShl(assembler->IntPtrSub(length, offset),
3923 assembler->IntPtrConstant(kPointerSizeLog2)),
3924 assembler->IntPtrConstant(
3925 CommonFrameConstants::kFixedFrameSizeAboveFp -
3926 kPointerSize)));
3927 Node* code32 = assembler->TruncateTaggedToWord32(context, code);
3928 Node* code16 = assembler->Word32And(
3929 code32, assembler->Int32Constant(String::kMaxUtf16CodeUnit));
3930
3931 // Check if {code16} fits into a one-byte string.
3932 Label if_codeisonebyte(assembler), if_codeistwobyte(assembler);
3933 assembler->Branch(
3934 assembler->Int32LessThanOrEqual(
3935 code16, assembler->Int32Constant(String::kMaxOneByteCharCode)),
3936 &if_codeisonebyte, &if_codeistwobyte);
3937
3938 assembler->Bind(&if_codeisonebyte);
3939 {
3940 // The {code16} fits into the SeqOneByteString {result}.
3941 assembler->StoreNoWriteBarrier(
3942 MachineRepresentation::kWord8, result,
3943 assembler->IntPtrAdd(
3944 assembler->IntPtrConstant(SeqOneByteString::kHeaderSize -
3945 kHeapObjectTag),
3946 offset),
3947 code16);
3948 var_offset.Bind(
3949 assembler->IntPtrAdd(offset, assembler->IntPtrConstant(1)));
3950 assembler->Goto(&loop);
3951 }
3952
3953 assembler->Bind(&if_codeistwobyte);
3954 {
3955 // Allocate a SeqTwoByteString to hold the resulting string.
3956 Node* cresult = assembler->AllocateSeqTwoByteString(context, length);
3957
3958 // Copy all characters that were previously written to the
3959 // SeqOneByteString in {result} over to the new {cresult}.
3960 Variable var_coffset(assembler, MachineType::PointerRepresentation());
3961 Label cloop(assembler, &var_coffset), done_cloop(assembler);
3962 var_coffset.Bind(assembler->IntPtrConstant(0));
3963 assembler->Goto(&cloop);
3964 assembler->Bind(&cloop);
3965 {
3966 Node* coffset = var_coffset.value();
3967 assembler->GotoIf(assembler->WordEqual(coffset, offset), &done_cloop);
3968 Node* ccode = assembler->Load(
3969 MachineType::Uint8(), result,
3970 assembler->IntPtrAdd(
3971 assembler->IntPtrConstant(SeqOneByteString::kHeaderSize -
3972 kHeapObjectTag),
3973 coffset));
3974 assembler->StoreNoWriteBarrier(
3975 MachineRepresentation::kWord16, cresult,
3976 assembler->IntPtrAdd(
3977 assembler->IntPtrConstant(SeqTwoByteString::kHeaderSize -
3978 kHeapObjectTag),
3979 assembler->WordShl(coffset, 1)),
3980 ccode);
3981 var_coffset.Bind(
3982 assembler->IntPtrAdd(coffset, assembler->IntPtrConstant(1)));
3983 assembler->Goto(&cloop);
3984 }
3985
3986 // Write the pending {code16} to {offset}.
3987 assembler->Bind(&done_cloop);
3988 assembler->StoreNoWriteBarrier(
3989 MachineRepresentation::kWord16, cresult,
3990 assembler->IntPtrAdd(
3991 assembler->IntPtrConstant(SeqTwoByteString::kHeaderSize -
3992 kHeapObjectTag),
3993 assembler->WordShl(offset, 1)),
3994 code16);
3995
3996 // Copy the remaining parameters to the SeqTwoByteString {cresult}.
3997 Label floop(assembler, &var_offset), done_floop(assembler);
3998 assembler->Goto(&floop);
3999 assembler->Bind(&floop);
4000 {
4001 // Compute the next {offset}.
4002 Node* offset = assembler->IntPtrAdd(var_offset.value(),
4003 assembler->IntPtrConstant(1));
4004
4005 // Check if we're done with the string.
4006 assembler->GotoIf(assembler->WordEqual(offset, length), &done_floop);
4007
4008 // Load the next code point and truncate it to a 16-bit value.
4009 Node* code = assembler->Load(
4010 MachineType::AnyTagged(), parent_frame_pointer,
4011 assembler->IntPtrAdd(
4012 assembler->WordShl(
4013 assembler->IntPtrSub(length, offset),
4014 assembler->IntPtrConstant(kPointerSizeLog2)),
4015 assembler->IntPtrConstant(
4016 CommonFrameConstants::kFixedFrameSizeAboveFp -
4017 kPointerSize)));
4018 Node* code32 = assembler->TruncateTaggedToWord32(context, code);
4019 Node* code16 = assembler->Word32And(
4020 code32, assembler->Int32Constant(String::kMaxUtf16CodeUnit));
4021
4022 // Store the truncated {code} point at the next offset.
4023 assembler->StoreNoWriteBarrier(
4024 MachineRepresentation::kWord16, cresult,
4025 assembler->IntPtrAdd(
4026 assembler->IntPtrConstant(SeqTwoByteString::kHeaderSize -
4027 kHeapObjectTag),
4028 assembler->WordShl(offset, 1)),
4029 code16);
4030 var_offset.Bind(offset);
4031 assembler->Goto(&floop);
4032 }
4033
4034 // Return the SeqTwoByteString.
4035 assembler->Bind(&done_floop);
4036 assembler->Return(cresult);
4037 }
4038 }
4039
4040 assembler->Bind(&done_loop);
4041 assembler->Return(result);
4042 }
4043 }
4044
4045 namespace { // for String.fromCodePoint
4046
4047 bool IsValidCodePoint(Isolate* isolate, Handle<Object> value) {
4048 if (!value->IsNumber() && !Object::ToNumber(value).ToHandle(&value)) {
4049 return false;
4050 }
4051
4052 if (Object::ToInteger(isolate, value).ToHandleChecked()->Number() !=
4053 value->Number()) {
4054 return false;
4055 }
4056
4057 if (value->Number() < 0 || value->Number() > 0x10FFFF) {
4058 return false;
4059 }
4060
4061 return true;
4062 }
4063
4064 uc32 NextCodePoint(Isolate* isolate, BuiltinArguments args, int index) {
4065 Handle<Object> value = args.at<Object>(1 + index);
4066 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, value, Object::ToNumber(value), -1);
4067 if (!IsValidCodePoint(isolate, value)) {
4068 isolate->Throw(*isolate->factory()->NewRangeError(
4069 MessageTemplate::kInvalidCodePoint, value));
4070 return -1;
4071 }
4072 return DoubleToUint32(value->Number());
4073 }
4074
4075 } // namespace
4076
4077 // ES6 section 21.1.2.2 String.fromCodePoint ( ...codePoints )
4078 BUILTIN(StringFromCodePoint) {
4079 HandleScope scope(isolate);
4080 int const length = args.length() - 1;
4081 if (length == 0) return isolate->heap()->empty_string();
4082 DCHECK_LT(0, length);
4083
4084 // Optimistically assume that the resulting String contains only one byte
4085 // characters.
4086 List<uint8_t> one_byte_buffer(length);
4087 uc32 code = 0;
4088 int index;
4089 for (index = 0; index < length; index++) {
4090 code = NextCodePoint(isolate, args, index);
4091 if (code < 0) {
4092 return isolate->heap()->exception();
4093 }
4094 if (code > String::kMaxOneByteCharCode) {
4095 break;
4096 }
4097 one_byte_buffer.Add(code);
4098 }
4099
4100 if (index == length) {
4101 RETURN_RESULT_OR_FAILURE(isolate, isolate->factory()->NewStringFromOneByte(
4102 one_byte_buffer.ToConstVector()));
4103 }
4104
4105 List<uc16> two_byte_buffer(length - index);
4106
4107 while (true) {
4108 if (code <= unibrow::Utf16::kMaxNonSurrogateCharCode) {
4109 two_byte_buffer.Add(code);
4110 } else {
4111 two_byte_buffer.Add(unibrow::Utf16::LeadSurrogate(code));
4112 two_byte_buffer.Add(unibrow::Utf16::TrailSurrogate(code));
4113 }
4114
4115 if (++index == length) {
4116 break;
4117 }
4118 code = NextCodePoint(isolate, args, index);
4119 if (code < 0) {
4120 return isolate->heap()->exception();
4121 }
4122 }
4123
4124 Handle<SeqTwoByteString> result;
4125 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
4126 isolate, result,
4127 isolate->factory()->NewRawTwoByteString(one_byte_buffer.length() +
4128 two_byte_buffer.length()));
4129
4130 CopyChars(result->GetChars(), one_byte_buffer.ToConstVector().start(),
4131 one_byte_buffer.length());
4132 CopyChars(result->GetChars() + one_byte_buffer.length(),
4133 two_byte_buffer.ToConstVector().start(), two_byte_buffer.length());
4134
4135 return *result;
4136 }
4137
4138 // ES6 section 21.1.3.1 String.prototype.charAt ( pos )
4139 void Builtins::Generate_StringPrototypeCharAt(CodeStubAssembler* assembler) {
4140 typedef CodeStubAssembler::Label Label;
4141 typedef compiler::Node Node;
4142 typedef CodeStubAssembler::Variable Variable;
4143
4144 Node* receiver = assembler->Parameter(0);
4145 Node* position = assembler->Parameter(1);
4146 Node* context = assembler->Parameter(4);
4147
4148 // Check that {receiver} is coercible to Object and convert it to a String.
4149 receiver =
4150 assembler->ToThisString(context, receiver, "String.prototype.charAt");
4151
4152 // Convert the {position} to a Smi and check that it's in bounds of the
4153 // {receiver}.
4154 // TODO(bmeurer): Find an abstraction for this!
4155 {
4156 // Check if the {position} is already a Smi.
4157 Variable var_position(assembler, MachineRepresentation::kTagged);
4158 var_position.Bind(position);
4159 Label if_positionissmi(assembler),
4160 if_positionisnotsmi(assembler, Label::kDeferred);
4161 assembler->Branch(assembler->WordIsSmi(position), &if_positionissmi,
4162 &if_positionisnotsmi);
4163 assembler->Bind(&if_positionisnotsmi);
4164 {
4165 // Convert the {position} to an Integer via the ToIntegerStub.
4166 Callable callable = CodeFactory::ToInteger(assembler->isolate());
4167 Node* index = assembler->CallStub(callable, context, position);
4168
4169 // Check if the resulting {index} is now a Smi.
4170 Label if_indexissmi(assembler, Label::kDeferred),
4171 if_indexisnotsmi(assembler, Label::kDeferred);
4172 assembler->Branch(assembler->WordIsSmi(index), &if_indexissmi,
4173 &if_indexisnotsmi);
4174
4175 assembler->Bind(&if_indexissmi);
4176 {
4177 var_position.Bind(index);
4178 assembler->Goto(&if_positionissmi);
4179 }
4180
4181 assembler->Bind(&if_indexisnotsmi);
4182 {
4183 // The ToIntegerStub canonicalizes everything in Smi range to Smi
4184 // representation, so any HeapNumber returned is not in Smi range.
4185 // The only exception here is -0.0, which we treat as 0.
4186 Node* index_value = assembler->LoadHeapNumberValue(index);
4187 Label if_indexiszero(assembler, Label::kDeferred),
4188 if_indexisnotzero(assembler, Label::kDeferred);
4189 assembler->Branch(assembler->Float64Equal(
4190 index_value, assembler->Float64Constant(0.0)),
4191 &if_indexiszero, &if_indexisnotzero);
4192
4193 assembler->Bind(&if_indexiszero);
4194 {
4195 var_position.Bind(assembler->SmiConstant(Smi::FromInt(0)));
4196 assembler->Goto(&if_positionissmi);
4197 }
4198
4199 assembler->Bind(&if_indexisnotzero);
4200 {
4201 // The {index} is some other integral Number, that is definitely
4202 // neither -0.0 nor in Smi range.
4203 assembler->Return(assembler->EmptyStringConstant());
4204 }
4205 }
4206 }
4207 assembler->Bind(&if_positionissmi);
4208 position = var_position.value();
4209
4210 // Determine the actual length of the {receiver} String.
4211 Node* receiver_length =
4212 assembler->LoadObjectField(receiver, String::kLengthOffset);
4213
4214 // Return "" if the Smi {position} is outside the bounds of the {receiver}.
4215 Label if_positioninbounds(assembler),
4216 if_positionnotinbounds(assembler, Label::kDeferred);
4217 assembler->Branch(assembler->SmiAboveOrEqual(position, receiver_length),
4218 &if_positionnotinbounds, &if_positioninbounds);
4219 assembler->Bind(&if_positionnotinbounds);
4220 assembler->Return(assembler->EmptyStringConstant());
4221 assembler->Bind(&if_positioninbounds);
4222 }
4223
4224 // Load the character code at the {position} from the {receiver}.
4225 Node* code = assembler->StringCharCodeAt(receiver, position);
4226
4227 // And return the single character string with only that {code}.
4228 Node* result = assembler->StringFromCharCode(code);
4229 assembler->Return(result);
4230 }
4231
4232 // ES6 section 21.1.3.2 String.prototype.charCodeAt ( pos )
4233 void Builtins::Generate_StringPrototypeCharCodeAt(
4234 CodeStubAssembler* assembler) {
4235 typedef CodeStubAssembler::Label Label;
4236 typedef compiler::Node Node;
4237 typedef CodeStubAssembler::Variable Variable;
4238
4239 Node* receiver = assembler->Parameter(0);
4240 Node* position = assembler->Parameter(1);
4241 Node* context = assembler->Parameter(4);
4242
4243 // Check that {receiver} is coercible to Object and convert it to a String.
4244 receiver =
4245 assembler->ToThisString(context, receiver, "String.prototype.charCodeAt");
4246
4247 // Convert the {position} to a Smi and check that it's in bounds of the
4248 // {receiver}.
4249 // TODO(bmeurer): Find an abstraction for this!
4250 {
4251 // Check if the {position} is already a Smi.
4252 Variable var_position(assembler, MachineRepresentation::kTagged);
4253 var_position.Bind(position);
4254 Label if_positionissmi(assembler),
4255 if_positionisnotsmi(assembler, Label::kDeferred);
4256 assembler->Branch(assembler->WordIsSmi(position), &if_positionissmi,
4257 &if_positionisnotsmi);
4258 assembler->Bind(&if_positionisnotsmi);
4259 {
4260 // Convert the {position} to an Integer via the ToIntegerStub.
4261 Callable callable = CodeFactory::ToInteger(assembler->isolate());
4262 Node* index = assembler->CallStub(callable, context, position);
4263
4264 // Check if the resulting {index} is now a Smi.
4265 Label if_indexissmi(assembler, Label::kDeferred),
4266 if_indexisnotsmi(assembler, Label::kDeferred);
4267 assembler->Branch(assembler->WordIsSmi(index), &if_indexissmi,
4268 &if_indexisnotsmi);
4269
4270 assembler->Bind(&if_indexissmi);
4271 {
4272 var_position.Bind(index);
4273 assembler->Goto(&if_positionissmi);
4274 }
4275
4276 assembler->Bind(&if_indexisnotsmi);
4277 {
4278 // The ToIntegerStub canonicalizes everything in Smi range to Smi
4279 // representation, so any HeapNumber returned is not in Smi range.
4280 // The only exception here is -0.0, which we treat as 0.
4281 Node* index_value = assembler->LoadHeapNumberValue(index);
4282 Label if_indexiszero(assembler, Label::kDeferred),
4283 if_indexisnotzero(assembler, Label::kDeferred);
4284 assembler->Branch(assembler->Float64Equal(
4285 index_value, assembler->Float64Constant(0.0)),
4286 &if_indexiszero, &if_indexisnotzero);
4287
4288 assembler->Bind(&if_indexiszero);
4289 {
4290 var_position.Bind(assembler->SmiConstant(Smi::FromInt(0)));
4291 assembler->Goto(&if_positionissmi);
4292 }
4293
4294 assembler->Bind(&if_indexisnotzero);
4295 {
4296 // The {index} is some other integral Number, that is definitely
4297 // neither -0.0 nor in Smi range.
4298 assembler->Return(assembler->NaNConstant());
4299 }
4300 }
4301 }
4302 assembler->Bind(&if_positionissmi);
4303 position = var_position.value();
4304
4305 // Determine the actual length of the {receiver} String.
4306 Node* receiver_length =
4307 assembler->LoadObjectField(receiver, String::kLengthOffset);
4308
4309 // Return NaN if the Smi {position} is outside the bounds of the {receiver}.
4310 Label if_positioninbounds(assembler),
4311 if_positionnotinbounds(assembler, Label::kDeferred);
4312 assembler->Branch(assembler->SmiAboveOrEqual(position, receiver_length),
4313 &if_positionnotinbounds, &if_positioninbounds);
4314 assembler->Bind(&if_positionnotinbounds);
4315 assembler->Return(assembler->NaNConstant());
4316 assembler->Bind(&if_positioninbounds);
4317 }
4318
4319 // Load the character at the {position} from the {receiver}.
4320 Node* value = assembler->StringCharCodeAt(receiver, position);
4321 Node* result = assembler->SmiFromWord32(value);
4322 assembler->Return(result);
4323 }
4324
4325 // ES6 section 21.1.3.25 String.prototype.toString ()
4326 void Builtins::Generate_StringPrototypeToString(CodeStubAssembler* assembler) {
4327 typedef compiler::Node Node;
4328
4329 Node* receiver = assembler->Parameter(0);
4330 Node* context = assembler->Parameter(3);
4331
4332 Node* result = assembler->ToThisValue(
4333 context, receiver, PrimitiveType::kString, "String.prototype.toString");
4334 assembler->Return(result);
4335 }
4336
4337 // ES6 section 21.1.3.27 String.prototype.trim ()
4338 BUILTIN(StringPrototypeTrim) {
4339 HandleScope scope(isolate);
4340 TO_THIS_STRING(string, "String.prototype.trim");
4341 return *String::Trim(string, String::kTrim);
4342 }
4343
4344 // Non-standard WebKit extension
4345 BUILTIN(StringPrototypeTrimLeft) {
4346 HandleScope scope(isolate);
4347 TO_THIS_STRING(string, "String.prototype.trimLeft");
4348 return *String::Trim(string, String::kTrimLeft);
4349 }
4350
4351 // Non-standard WebKit extension
4352 BUILTIN(StringPrototypeTrimRight) {
4353 HandleScope scope(isolate);
4354 TO_THIS_STRING(string, "String.prototype.trimRight");
4355 return *String::Trim(string, String::kTrimRight);
4356 }
4357
4358 // ES6 section 21.1.3.28 String.prototype.valueOf ( )
4359 void Builtins::Generate_StringPrototypeValueOf(CodeStubAssembler* assembler) {
4360 typedef compiler::Node Node;
4361
4362 Node* receiver = assembler->Parameter(0);
4363 Node* context = assembler->Parameter(3);
4364
4365 Node* result = assembler->ToThisValue(
4366 context, receiver, PrimitiveType::kString, "String.prototype.valueOf");
4367 assembler->Return(result);
4368 }
4369
4370 // -----------------------------------------------------------------------------
4371 // ES6 section 21.1 ArrayBuffer Objects
4372
4373 // ES6 section 24.1.2.1 ArrayBuffer ( length ) for the [[Call]] case.
4374 BUILTIN(ArrayBufferConstructor) {
4375 HandleScope scope(isolate);
4376 Handle<JSFunction> target = args.target<JSFunction>();
4377 DCHECK(*target == target->native_context()->array_buffer_fun() ||
4378 *target == target->native_context()->shared_array_buffer_fun());
4379 THROW_NEW_ERROR_RETURN_FAILURE(
4380 isolate, NewTypeError(MessageTemplate::kConstructorNotFunction,
4381 handle(target->shared()->name(), isolate)));
4382 }
4383
4384 // ES6 section 24.1.2.1 ArrayBuffer ( length ) for the [[Construct]] case.
4385 BUILTIN(ArrayBufferConstructor_ConstructStub) {
4386 HandleScope scope(isolate);
4387 Handle<JSFunction> target = args.target<JSFunction>();
4388 Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
4389 Handle<Object> length = args.atOrUndefined(isolate, 1);
4390 DCHECK(*target == target->native_context()->array_buffer_fun() ||
4391 *target == target->native_context()->shared_array_buffer_fun());
4392 Handle<Object> number_length;
4393 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, number_length,
4394 Object::ToInteger(isolate, length));
4395 if (number_length->Number() < 0.0) {
4396 THROW_NEW_ERROR_RETURN_FAILURE(
4397 isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferLength));
4398 }
4399 Handle<JSObject> result;
4400 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
4401 JSObject::New(target, new_target));
4402 size_t byte_length;
4403 if (!TryNumberToSize(isolate, *number_length, &byte_length)) {
4404 THROW_NEW_ERROR_RETURN_FAILURE(
4405 isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferLength));
4406 }
4407 SharedFlag shared_flag =
4408 (*target == target->native_context()->array_buffer_fun())
4409 ? SharedFlag::kNotShared
4410 : SharedFlag::kShared;
4411 if (!JSArrayBuffer::SetupAllocatingData(Handle<JSArrayBuffer>::cast(result),
4412 isolate, byte_length, true,
4413 shared_flag)) {
4414 THROW_NEW_ERROR_RETURN_FAILURE(
4415 isolate, NewRangeError(MessageTemplate::kArrayBufferAllocationFailed));
4416 }
4417 return *result;
4418 }
4419
4420 // ES6 section 24.1.4.1 get ArrayBuffer.prototype.byteLength
4421 BUILTIN(ArrayBufferPrototypeGetByteLength) {
4422 HandleScope scope(isolate);
4423 CHECK_RECEIVER(JSArrayBuffer, array_buffer,
4424 "get ArrayBuffer.prototype.byteLength");
4425
4426 if (array_buffer->is_shared()) {
4427 THROW_NEW_ERROR_RETURN_FAILURE(
4428 isolate, NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
4429 isolate->factory()->NewStringFromAsciiChecked(
4430 "get ArrayBuffer.prototype.byteLength"),
4431 args.receiver()));
4432 }
4433 // TODO(franzih): According to the ES6 spec, we should throw a TypeError
4434 // here if the JSArrayBuffer is detached.
4435 return array_buffer->byte_length();
4436 }
4437
4438 // ES6 section 24.1.3.1 ArrayBuffer.isView ( arg )
4439 BUILTIN(ArrayBufferIsView) {
4440 SealHandleScope shs(isolate);
4441 DCHECK_EQ(2, args.length());
4442 Object* arg = args[1];
4443 return isolate->heap()->ToBoolean(arg->IsJSArrayBufferView());
4444 }
4445
4446 // ES7 sharedmem 6.3.4.1 get SharedArrayBuffer.prototype.byteLength
4447 BUILTIN(SharedArrayBufferPrototypeGetByteLength) {
4448 HandleScope scope(isolate);
4449 CHECK_RECEIVER(JSArrayBuffer, array_buffer,
4450 "get SharedArrayBuffer.prototype.byteLength");
4451 if (!array_buffer->is_shared()) {
4452 THROW_NEW_ERROR_RETURN_FAILURE(
4453 isolate, NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
4454 isolate->factory()->NewStringFromAsciiChecked(
4455 "get SharedArrayBuffer.prototype.byteLength"),
4456 args.receiver()));
4457 }
4458 return array_buffer->byte_length();
4459 }
4460
4461 // ES6 section 26.2.1.1 Proxy ( target, handler ) for the [[Call]] case.
4462 BUILTIN(ProxyConstructor) {
4463 HandleScope scope(isolate);
4464 THROW_NEW_ERROR_RETURN_FAILURE(
4465 isolate,
4466 NewTypeError(MessageTemplate::kConstructorNotFunction,
4467 isolate->factory()->NewStringFromAsciiChecked("Proxy")));
4468 }
4469
4470 // ES6 section 26.2.1.1 Proxy ( target, handler ) for the [[Construct]] case.
4471 BUILTIN(ProxyConstructor_ConstructStub) {
4472 HandleScope scope(isolate);
4473 DCHECK(isolate->proxy_function()->IsConstructor());
4474 Handle<Object> target = args.atOrUndefined(isolate, 1);
4475 Handle<Object> handler = args.atOrUndefined(isolate, 2);
4476 RETURN_RESULT_OR_FAILURE(isolate, JSProxy::New(isolate, target, handler));
4477 }
4478
4479 // -----------------------------------------------------------------------------
4480 // Throwers for restricted function properties and strict arguments object
4481 // properties
4482
4483 BUILTIN(RestrictedFunctionPropertiesThrower) {
4484 HandleScope scope(isolate);
4485 THROW_NEW_ERROR_RETURN_FAILURE(
4486 isolate, NewTypeError(MessageTemplate::kRestrictedFunctionProperties));
4487 }
4488
4489 BUILTIN(RestrictedStrictArgumentsPropertiesThrower) {
4490 HandleScope scope(isolate);
4491 THROW_NEW_ERROR_RETURN_FAILURE(
4492 isolate, NewTypeError(MessageTemplate::kStrictPoisonPill));
4493 }
4494
4495 // -----------------------------------------------------------------------------
4496 // 145 //
4497 146
4498 namespace { 147 namespace {
4499 148
4500 // Returns the holder JSObject if the function can legally be called with this 149 // Returns the holder JSObject if the function can legally be called with this
4501 // receiver. Returns nullptr if the call is illegal. 150 // receiver. Returns nullptr if the call is illegal.
4502 // TODO(dcarney): CallOptimization duplicates this logic, merge. 151 // TODO(dcarney): CallOptimization duplicates this logic, merge.
4503 JSObject* GetCompatibleReceiver(Isolate* isolate, FunctionTemplateInfo* info, 152 JSObject* GetCompatibleReceiver(Isolate* isolate, FunctionTemplateInfo* info,
4504 JSObject* receiver) { 153 JSObject* receiver) {
4505 Object* recv_type = info->signature(); 154 Object* recv_type = info->signature();
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
4615 RETURN_RESULT_OR_FAILURE( 264 RETURN_RESULT_OR_FAILURE(
4616 isolate, HandleApiCallHelper<true>(isolate, function, new_target, 265 isolate, HandleApiCallHelper<true>(isolate, function, new_target,
4617 fun_data, receiver, args)); 266 fun_data, receiver, args));
4618 } else { 267 } else {
4619 RETURN_RESULT_OR_FAILURE( 268 RETURN_RESULT_OR_FAILURE(
4620 isolate, HandleApiCallHelper<false>(isolate, function, new_target, 269 isolate, HandleApiCallHelper<false>(isolate, function, new_target,
4621 fun_data, receiver, args)); 270 fun_data, receiver, args));
4622 } 271 }
4623 } 272 }
4624 273
274 namespace {
275
276 bool CodeGenerationFromStringsAllowed(Isolate* isolate,
277 Handle<Context> context) {
278 DCHECK(context->allow_code_gen_from_strings()->IsFalse(isolate));
279 // Check with callback if set.
280 AllowCodeGenerationFromStringsCallback callback =
281 isolate->allow_code_gen_callback();
282 if (callback == NULL) {
283 // No callback set and code generation disallowed.
284 return false;
285 } else {
286 // Callback set. Let it decide if code generation is allowed.
287 VMState<EXTERNAL> state(isolate);
288 return callback(v8::Utils::ToLocal(context));
289 }
290 }
291
292 } // namespace
293
294 MaybeHandle<JSFunction> Builtins::CompileString(Handle<Context> context,
295 Handle<String> source,
296 ParseRestriction restriction) {
297 Isolate* const isolate = context->GetIsolate();
298 Handle<Context> native_context(context->native_context(), isolate);
299
300 // Check if native context allows code generation from
301 // strings. Throw an exception if it doesn't.
302 if (native_context->allow_code_gen_from_strings()->IsFalse(isolate) &&
303 !CodeGenerationFromStringsAllowed(isolate, native_context)) {
304 Handle<Object> error_message =
305 native_context->ErrorMessageForCodeGenerationFromStrings();
306 THROW_NEW_ERROR(isolate, NewEvalError(MessageTemplate::kCodeGenFromStrings,
307 error_message),
308 JSFunction);
309 }
310
311 // Compile source string in the native context.
312 int eval_scope_position = 0;
313 int eval_position = kNoSourcePosition;
314 Handle<SharedFunctionInfo> outer_info(native_context->closure()->shared());
315 return Compiler::GetFunctionFromEval(source, outer_info, native_context,
316 SLOPPY, restriction, eval_scope_position,
317 eval_position);
318 }
319
4625 Handle<Code> Builtins::CallFunction(ConvertReceiverMode mode, 320 Handle<Code> Builtins::CallFunction(ConvertReceiverMode mode,
4626 TailCallMode tail_call_mode) { 321 TailCallMode tail_call_mode) {
4627 switch (tail_call_mode) { 322 switch (tail_call_mode) {
4628 case TailCallMode::kDisallow: 323 case TailCallMode::kDisallow:
4629 switch (mode) { 324 switch (mode) {
4630 case ConvertReceiverMode::kNullOrUndefined: 325 case ConvertReceiverMode::kNullOrUndefined:
4631 return CallFunction_ReceiverIsNullOrUndefined(); 326 return CallFunction_ReceiverIsNullOrUndefined();
4632 case ConvertReceiverMode::kNotNullOrUndefined: 327 case ConvertReceiverMode::kNotNullOrUndefined:
4633 return CallFunction_ReceiverIsNotNullOrUndefined(); 328 return CallFunction_ReceiverIsNotNullOrUndefined();
4634 case ConvertReceiverMode::kAny: 329 case ConvertReceiverMode::kAny:
(...skipping 866 matching lines...) Expand 10 before | Expand all | Expand 10 after
5501 } 1196 }
5502 1197
5503 void Builtins::Generate_InterruptCheck(MacroAssembler* masm) { 1198 void Builtins::Generate_InterruptCheck(MacroAssembler* masm) {
5504 masm->TailCallRuntime(Runtime::kInterrupt); 1199 masm->TailCallRuntime(Runtime::kInterrupt);
5505 } 1200 }
5506 1201
5507 void Builtins::Generate_StackCheck(MacroAssembler* masm) { 1202 void Builtins::Generate_StackCheck(MacroAssembler* masm) {
5508 masm->TailCallRuntime(Runtime::kStackGuard); 1203 masm->TailCallRuntime(Runtime::kStackGuard);
5509 } 1204 }
5510 1205
5511 namespace {
5512
5513 void ValidateSharedTypedArray(CodeStubAssembler* a, compiler::Node* tagged,
5514 compiler::Node* context,
5515 compiler::Node** out_instance_type,
5516 compiler::Node** out_backing_store) {
5517 using namespace compiler;
5518 CodeStubAssembler::Label is_smi(a), not_smi(a), is_typed_array(a),
5519 not_typed_array(a), is_shared(a), not_shared(a), is_float_or_clamped(a),
5520 not_float_or_clamped(a), invalid(a);
5521
5522 // Fail if it is not a heap object.
5523 a->Branch(a->WordIsSmi(tagged), &is_smi, &not_smi);
5524 a->Bind(&is_smi);
5525 a->Goto(&invalid);
5526
5527 // Fail if the array's instance type is not JSTypedArray.
5528 a->Bind(&not_smi);
5529 a->Branch(a->WordEqual(a->LoadInstanceType(tagged),
5530 a->Int32Constant(JS_TYPED_ARRAY_TYPE)),
5531 &is_typed_array, &not_typed_array);
5532 a->Bind(&not_typed_array);
5533 a->Goto(&invalid);
5534
5535 // Fail if the array's JSArrayBuffer is not shared.
5536 a->Bind(&is_typed_array);
5537 Node* array_buffer = a->LoadObjectField(tagged, JSTypedArray::kBufferOffset);
5538 Node* is_buffer_shared = a->BitFieldDecode<JSArrayBuffer::IsShared>(
5539 a->LoadObjectField(array_buffer, JSArrayBuffer::kBitFieldSlot));
5540 a->Branch(is_buffer_shared, &is_shared, &not_shared);
5541 a->Bind(&not_shared);
5542 a->Goto(&invalid);
5543
5544 // Fail if the array's element type is float32, float64 or clamped.
5545 a->Bind(&is_shared);
5546 Node* elements_instance_type = a->LoadInstanceType(
5547 a->LoadObjectField(tagged, JSObject::kElementsOffset));
5548 STATIC_ASSERT(FIXED_INT8_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE);
5549 STATIC_ASSERT(FIXED_INT16_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE);
5550 STATIC_ASSERT(FIXED_INT32_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE);
5551 STATIC_ASSERT(FIXED_UINT8_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE);
5552 STATIC_ASSERT(FIXED_UINT16_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE);
5553 STATIC_ASSERT(FIXED_UINT32_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE);
5554 a->Branch(a->Int32LessThan(elements_instance_type,
5555 a->Int32Constant(FIXED_FLOAT32_ARRAY_TYPE)),
5556 &not_float_or_clamped, &is_float_or_clamped);
5557 a->Bind(&is_float_or_clamped);
5558 a->Goto(&invalid);
5559
5560 a->Bind(&invalid);
5561 a->CallRuntime(Runtime::kThrowNotIntegerSharedTypedArrayError, context,
5562 tagged);
5563 a->Return(a->UndefinedConstant());
5564
5565 a->Bind(&not_float_or_clamped);
5566 *out_instance_type = elements_instance_type;
5567
5568 Node* backing_store =
5569 a->LoadObjectField(array_buffer, JSArrayBuffer::kBackingStoreOffset);
5570 Node* byte_offset = a->ChangeUint32ToWord(a->TruncateTaggedToWord32(
5571 context,
5572 a->LoadObjectField(tagged, JSArrayBufferView::kByteOffsetOffset)));
5573 *out_backing_store = a->IntPtrAdd(backing_store, byte_offset);
5574 }
5575
5576 // https://tc39.github.io/ecmascript_sharedmem/shmem.html#Atomics.ValidateAtomic Access
5577 compiler::Node* ConvertTaggedAtomicIndexToWord32(CodeStubAssembler* a,
5578 compiler::Node* tagged,
5579 compiler::Node* context) {
5580 using namespace compiler;
5581 CodeStubAssembler::Variable var_result(a, MachineRepresentation::kWord32);
5582
5583 Callable to_number = CodeFactory::ToNumber(a->isolate());
5584 Node* number_index = a->CallStub(to_number, context, tagged);
5585 CodeStubAssembler::Label done(a, &var_result);
5586
5587 CodeStubAssembler::Label if_numberissmi(a), if_numberisnotsmi(a);
5588 a->Branch(a->WordIsSmi(number_index), &if_numberissmi, &if_numberisnotsmi);
5589
5590 a->Bind(&if_numberissmi);
5591 {
5592 var_result.Bind(a->SmiToWord32(number_index));
5593 a->Goto(&done);
5594 }
5595
5596 a->Bind(&if_numberisnotsmi);
5597 {
5598 Node* number_index_value = a->LoadHeapNumberValue(number_index);
5599 Node* access_index = a->TruncateFloat64ToWord32(number_index_value);
5600 Node* test_index = a->ChangeInt32ToFloat64(access_index);
5601
5602 CodeStubAssembler::Label if_indexesareequal(a), if_indexesarenotequal(a);
5603 a->Branch(a->Float64Equal(number_index_value, test_index),
5604 &if_indexesareequal, &if_indexesarenotequal);
5605
5606 a->Bind(&if_indexesareequal);
5607 {
5608 var_result.Bind(access_index);
5609 a->Goto(&done);
5610 }
5611
5612 a->Bind(&if_indexesarenotequal);
5613 a->Return(
5614 a->CallRuntime(Runtime::kThrowInvalidAtomicAccessIndexError, context));
5615 }
5616
5617 a->Bind(&done);
5618 return var_result.value();
5619 }
5620
5621 void ValidateAtomicIndex(CodeStubAssembler* a, compiler::Node* index_word,
5622 compiler::Node* array_length_word,
5623 compiler::Node* context) {
5624 using namespace compiler;
5625 // Check if the index is in bounds. If not, throw RangeError.
5626 CodeStubAssembler::Label if_inbounds(a), if_notinbounds(a);
5627 a->Branch(
5628 a->WordOr(a->Int32LessThan(index_word, a->Int32Constant(0)),
5629 a->Int32GreaterThanOrEqual(index_word, array_length_word)),
5630 &if_notinbounds, &if_inbounds);
5631 a->Bind(&if_notinbounds);
5632 a->Return(
5633 a->CallRuntime(Runtime::kThrowInvalidAtomicAccessIndexError, context));
5634 a->Bind(&if_inbounds);
5635 }
5636
5637 } // anonymous namespace
5638
5639 void Builtins::Generate_AtomicsLoad(CodeStubAssembler* a) {
5640 using namespace compiler;
5641 Node* array = a->Parameter(1);
5642 Node* index = a->Parameter(2);
5643 Node* context = a->Parameter(3 + 2);
5644
5645 Node* instance_type;
5646 Node* backing_store;
5647 ValidateSharedTypedArray(a, array, context, &instance_type, &backing_store);
5648
5649 Node* index_word32 = ConvertTaggedAtomicIndexToWord32(a, index, context);
5650 Node* array_length_word32 = a->TruncateTaggedToWord32(
5651 context, a->LoadObjectField(array, JSTypedArray::kLengthOffset));
5652 ValidateAtomicIndex(a, index_word32, array_length_word32, context);
5653 Node* index_word = a->ChangeUint32ToWord(index_word32);
5654
5655 CodeStubAssembler::Label i8(a), u8(a), i16(a), u16(a), i32(a), u32(a),
5656 other(a);
5657 int32_t case_values[] = {
5658 FIXED_INT8_ARRAY_TYPE, FIXED_UINT8_ARRAY_TYPE, FIXED_INT16_ARRAY_TYPE,
5659 FIXED_UINT16_ARRAY_TYPE, FIXED_INT32_ARRAY_TYPE, FIXED_UINT32_ARRAY_TYPE,
5660 };
5661 CodeStubAssembler::Label* case_labels[] = {
5662 &i8, &u8, &i16, &u16, &i32, &u32,
5663 };
5664 a->Switch(instance_type, &other, case_values, case_labels,
5665 arraysize(case_labels));
5666
5667 a->Bind(&i8);
5668 a->Return(
5669 a->SmiTag(a->AtomicLoad(MachineType::Int8(), backing_store, index_word)));
5670
5671 a->Bind(&u8);
5672 a->Return(a->SmiTag(
5673 a->AtomicLoad(MachineType::Uint8(), backing_store, index_word)));
5674
5675 a->Bind(&i16);
5676 a->Return(a->SmiTag(a->AtomicLoad(MachineType::Int16(), backing_store,
5677 a->WordShl(index_word, 1))));
5678
5679 a->Bind(&u16);
5680 a->Return(a->SmiTag(a->AtomicLoad(MachineType::Uint16(), backing_store,
5681 a->WordShl(index_word, 1))));
5682
5683 a->Bind(&i32);
5684 a->Return(a->ChangeInt32ToTagged(a->AtomicLoad(
5685 MachineType::Int32(), backing_store, a->WordShl(index_word, 2))));
5686
5687 a->Bind(&u32);
5688 a->Return(a->ChangeUint32ToTagged(a->AtomicLoad(
5689 MachineType::Uint32(), backing_store, a->WordShl(index_word, 2))));
5690
5691 // This shouldn't happen, we've already validated the type.
5692 a->Bind(&other);
5693 a->Return(a->Int32Constant(0));
5694 }
5695
5696 void Builtins::Generate_AtomicsStore(CodeStubAssembler* a) {
5697 using namespace compiler;
5698 Node* array = a->Parameter(1);
5699 Node* index = a->Parameter(2);
5700 Node* value = a->Parameter(3);
5701 Node* context = a->Parameter(4 + 2);
5702
5703 Node* instance_type;
5704 Node* backing_store;
5705 ValidateSharedTypedArray(a, array, context, &instance_type, &backing_store);
5706
5707 Node* index_word32 = ConvertTaggedAtomicIndexToWord32(a, index, context);
5708 Node* array_length_word32 = a->TruncateTaggedToWord32(
5709 context, a->LoadObjectField(array, JSTypedArray::kLengthOffset));
5710 ValidateAtomicIndex(a, index_word32, array_length_word32, context);
5711 Node* index_word = a->ChangeUint32ToWord(index_word32);
5712
5713 Callable to_integer = CodeFactory::ToInteger(a->isolate());
5714 Node* value_integer = a->CallStub(to_integer, context, value);
5715 Node* value_word32 = a->TruncateTaggedToWord32(context, value_integer);
5716
5717 CodeStubAssembler::Label u8(a), u16(a), u32(a), other(a);
5718 int32_t case_values[] = {
5719 FIXED_INT8_ARRAY_TYPE, FIXED_UINT8_ARRAY_TYPE, FIXED_INT16_ARRAY_TYPE,
5720 FIXED_UINT16_ARRAY_TYPE, FIXED_INT32_ARRAY_TYPE, FIXED_UINT32_ARRAY_TYPE,
5721 };
5722 CodeStubAssembler::Label* case_labels[] = {
5723 &u8, &u8, &u16, &u16, &u32, &u32,
5724 };
5725 a->Switch(instance_type, &other, case_values, case_labels,
5726 arraysize(case_labels));
5727
5728 a->Bind(&u8);
5729 a->AtomicStore(MachineRepresentation::kWord8, backing_store, index_word,
5730 value_word32);
5731 a->Return(value_integer);
5732
5733 a->Bind(&u16);
5734 a->SmiTag(a->AtomicStore(MachineRepresentation::kWord16, backing_store,
5735 a->WordShl(index_word, 1), value_word32));
5736 a->Return(value_integer);
5737
5738 a->Bind(&u32);
5739 a->AtomicStore(MachineRepresentation::kWord32, backing_store,
5740 a->WordShl(index_word, 2), value_word32);
5741 a->Return(value_integer);
5742
5743 // This shouldn't happen, we've already validated the type.
5744 a->Bind(&other);
5745 a->Return(a->Int32Constant(0));
5746 }
5747
5748 void Builtins::Generate_CallFunction_ReceiverIsNullOrUndefined( 1206 void Builtins::Generate_CallFunction_ReceiverIsNullOrUndefined(
5749 MacroAssembler* masm) { 1207 MacroAssembler* masm) {
5750 Generate_CallFunction(masm, ConvertReceiverMode::kNullOrUndefined, 1208 Generate_CallFunction(masm, ConvertReceiverMode::kNullOrUndefined,
5751 TailCallMode::kDisallow); 1209 TailCallMode::kDisallow);
5752 } 1210 }
5753 1211
5754 void Builtins::Generate_CallFunction_ReceiverIsNotNullOrUndefined( 1212 void Builtins::Generate_CallFunction_ReceiverIsNotNullOrUndefined(
5755 MacroAssembler* masm) { 1213 MacroAssembler* masm) {
5756 Generate_CallFunction(masm, ConvertReceiverMode::kNotNullOrUndefined, 1214 Generate_CallFunction(masm, ConvertReceiverMode::kNotNullOrUndefined,
5757 TailCallMode::kDisallow); 1215 TailCallMode::kDisallow);
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
5831 return Generate_InterpreterPushArgsAndCallImpl(masm, TailCallMode::kDisallow, 1289 return Generate_InterpreterPushArgsAndCallImpl(masm, TailCallMode::kDisallow,
5832 CallableType::kJSFunction); 1290 CallableType::kJSFunction);
5833 } 1291 }
5834 1292
5835 void Builtins::Generate_InterpreterPushArgsAndTailCallFunction( 1293 void Builtins::Generate_InterpreterPushArgsAndTailCallFunction(
5836 MacroAssembler* masm) { 1294 MacroAssembler* masm) {
5837 return Generate_InterpreterPushArgsAndCallImpl(masm, TailCallMode::kAllow, 1295 return Generate_InterpreterPushArgsAndCallImpl(masm, TailCallMode::kAllow,
5838 CallableType::kJSFunction); 1296 CallableType::kJSFunction);
5839 } 1297 }
5840 1298
5841 void Builtins::Generate_MathMax(MacroAssembler* masm) {
5842 Generate_MathMaxMin(masm, MathMaxMinKind::kMax);
5843 }
5844
5845 void Builtins::Generate_MathMin(MacroAssembler* masm) {
5846 Generate_MathMaxMin(masm, MathMaxMinKind::kMin);
5847 }
5848
5849 #define DEFINE_BUILTIN_ACCESSOR(Name, ...) \ 1299 #define DEFINE_BUILTIN_ACCESSOR(Name, ...) \
5850 Handle<Code> Builtins::Name() { \ 1300 Handle<Code> Builtins::Name() { \
5851 Code** code_address = reinterpret_cast<Code**>(builtin_address(k##Name)); \ 1301 Code** code_address = reinterpret_cast<Code**>(builtin_address(k##Name)); \
5852 return Handle<Code>(code_address); \ 1302 return Handle<Code>(code_address); \
5853 } 1303 }
5854 BUILTIN_LIST_ALL(DEFINE_BUILTIN_ACCESSOR) 1304 BUILTIN_LIST_ALL(DEFINE_BUILTIN_ACCESSOR)
5855 #undef DEFINE_BUILTIN_ACCESSOR 1305 #undef DEFINE_BUILTIN_ACCESSOR
5856 1306
5857 } // namespace internal 1307 } // namespace internal
5858 } // namespace v8 1308 } // namespace v8
OLDNEW
« no previous file with comments | « src/builtins/builtins.h ('k') | src/builtins/builtins-arraybuffer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698