1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/builtins/builtins.h"
6 #include "src/builtins/builtins-utils.h"
7
8 #include "src/code-factory.h"
9 #include "src/property-descriptor.h"
10
11 namespace v8 {
12 namespace internal {
13
14 // -----------------------------------------------------------------------------
15 // ES6 section 19.1 Object Objects
16
Generate_ObjectHasOwnProperty(CodeStubAssembler * assembler)17 void Builtins::Generate_ObjectHasOwnProperty(CodeStubAssembler* assembler) {
18 typedef compiler::Node Node;
19 typedef CodeStubAssembler::Label Label;
20 typedef CodeStubAssembler::Variable Variable;
21
22 Node* object = assembler->Parameter(0);
23 Node* key = assembler->Parameter(1);
24 Node* context = assembler->Parameter(4);
25
26 Label call_runtime(assembler), return_true(assembler),
27 return_false(assembler);
28
29 // Smi receivers do not have own properties.
30 Label if_objectisnotsmi(assembler);
31 assembler->Branch(assembler->TaggedIsSmi(object), &return_false,
32 &if_objectisnotsmi);
33 assembler->Bind(&if_objectisnotsmi);
34
35 Node* map = assembler->LoadMap(object);
36 Node* instance_type = assembler->LoadMapInstanceType(map);
37
38 Variable var_index(assembler, MachineType::PointerRepresentation());
39
40 Label keyisindex(assembler), if_iskeyunique(assembler);
41 assembler->TryToName(key, &keyisindex, &var_index, &if_iskeyunique,
42 &call_runtime);
43
44 assembler->Bind(&if_iskeyunique);
45 assembler->TryHasOwnProperty(object, map, instance_type, key, &return_true,
46 &return_false, &call_runtime);
47
48 assembler->Bind(&keyisindex);
49 // Handle negative keys in the runtime.
50 assembler->GotoIf(assembler->IntPtrLessThan(var_index.value(),
51 assembler->IntPtrConstant(0)),
52 &call_runtime);
53 assembler->TryLookupElement(object, map, instance_type, var_index.value(),
54 &return_true, &return_false, &call_runtime);
55
56 assembler->Bind(&return_true);
57 assembler->Return(assembler->BooleanConstant(true));
58
59 assembler->Bind(&return_false);
60 assembler->Return(assembler->BooleanConstant(false));
61
62 assembler->Bind(&call_runtime);
63 assembler->Return(assembler->CallRuntime(Runtime::kObjectHasOwnProperty,
64 context, object, key));
65 }
66
67 namespace {
68
FastAssign(Handle<JSReceiver> to,Handle<Object> next_source)69 MUST_USE_RESULT Maybe<bool> FastAssign(Handle<JSReceiver> to,
70 Handle<Object> next_source) {
71 // Non-empty strings are the only non-JSReceivers that need to be handled
72 // explicitly by Object.assign.
73 if (!next_source->IsJSReceiver()) {
74 return Just(!next_source->IsString() ||
75 String::cast(*next_source)->length() == 0);
76 }
77
78 // If the target is deprecated, the object will be updated on first store. If
79 // the source for that store equals the target, this will invalidate the
80 // cached representation of the source. Preventively upgrade the target.
81 // Do this on each iteration since any property load could cause deprecation.
82 if (to->map()->is_deprecated()) {
83 JSObject::MigrateInstance(Handle<JSObject>::cast(to));
84 }
85
86 Isolate* isolate = to->GetIsolate();
87 Handle<Map> map(JSReceiver::cast(*next_source)->map(), isolate);
88
89 if (!map->IsJSObjectMap()) return Just(false);
90 if (!map->OnlyHasSimpleProperties()) return Just(false);
91
92 Handle<JSObject> from = Handle<JSObject>::cast(next_source);
93 if (from->elements() != isolate->heap()->empty_fixed_array()) {
94 return Just(false);
95 }
96
97 Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
98 int length = map->NumberOfOwnDescriptors();
99
100 bool stable = true;
101
102 for (int i = 0; i < length; i++) {
103 Handle<Name> next_key(descriptors->GetKey(i), isolate);
104 Handle<Object> prop_value;
105 // Directly decode from the descriptor array if |from| did not change shape.
106 if (stable) {
107 PropertyDetails details = descriptors->GetDetails(i);
108 if (!details.IsEnumerable()) continue;
109 if (details.kind() == kData) {
110 if (details.location() == kDescriptor) {
111 prop_value = handle(descriptors->GetValue(i), isolate);
112 } else {
113 Representation representation = details.representation();
114 FieldIndex index = FieldIndex::ForDescriptor(*map, i);
115 prop_value = JSObject::FastPropertyAt(from, representation, index);
116 }
117 } else {
118 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
119 isolate, prop_value, JSReceiver::GetProperty(from, next_key),
120 Nothing<bool>());
121 stable = from->map() == *map;
122 }
123 } else {
124 // If the map did change, do a slower lookup. We are still guaranteed that
125 // the object has a simple shape, and that the key is a name.
126 LookupIterator it(from, next_key, from,
127 LookupIterator::OWN_SKIP_INTERCEPTOR);
128 if (!it.IsFound()) continue;
129 DCHECK(it.state() == LookupIterator::DATA ||
130 it.state() == LookupIterator::ACCESSOR);
131 if (!it.IsEnumerable()) continue;
132 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
133 isolate, prop_value, Object::GetProperty(&it), Nothing<bool>());
134 }
135 LookupIterator it(to, next_key, to);
136 bool call_to_js = it.IsFound() && it.state() != LookupIterator::DATA;
137 Maybe<bool> result = Object::SetProperty(
138 &it, prop_value, STRICT, Object::CERTAINLY_NOT_STORE_FROM_KEYED);
139 if (result.IsNothing()) return result;
140 if (stable && call_to_js) stable = from->map() == *map;
141 }
142
143 return Just(true);
144 }
145
146 } // namespace
147
148 // ES6 19.1.2.1 Object.assign
BUILTIN(ObjectAssign)149 BUILTIN(ObjectAssign) {
150 HandleScope scope(isolate);
151 Handle<Object> target = args.atOrUndefined(isolate, 1);
152
153 // 1. Let to be ? ToObject(target).
154 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, target,
155 Object::ToObject(isolate, target));
156 Handle<JSReceiver> to = Handle<JSReceiver>::cast(target);
157 // 2. If only one argument was passed, return to.
158 if (args.length() == 2) return *to;
159 // 3. Let sources be the List of argument values starting with the
160 // second argument.
161 // 4. For each element nextSource of sources, in ascending index order,
162 for (int i = 2; i < args.length(); ++i) {
163 Handle<Object> next_source = args.at<Object>(i);
164 Maybe<bool> fast_assign = FastAssign(to, next_source);
165 if (fast_assign.IsNothing()) return isolate->heap()->exception();
166 if (fast_assign.FromJust()) continue;
167 // 4a. If nextSource is undefined or null, let keys be an empty List.
168 // 4b. Else,
169 // 4b i. Let from be ToObject(nextSource).
170 // Only non-empty strings and JSReceivers have enumerable properties.
171 Handle<JSReceiver> from =
172 Object::ToObject(isolate, next_source).ToHandleChecked();
173 // 4b ii. Let keys be ? from.[[OwnPropertyKeys]]().
174 Handle<FixedArray> keys;
175 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
176 isolate, keys, KeyAccumulator::GetKeys(
177 from, KeyCollectionMode::kOwnOnly, ALL_PROPERTIES,
178 GetKeysConversion::kKeepNumbers));
179 // 4c. Repeat for each element nextKey of keys in List order,
180 for (int j = 0; j < keys->length(); ++j) {
181 Handle<Object> next_key(keys->get(j), isolate);
182 // 4c i. Let desc be ? from.[[GetOwnProperty]](nextKey).
183 PropertyDescriptor desc;
184 Maybe<bool> found =
185 JSReceiver::GetOwnPropertyDescriptor(isolate, from, next_key, &desc);
186 if (found.IsNothing()) return isolate->heap()->exception();
187 // 4c ii. If desc is not undefined and desc.[[Enumerable]] is true, then
188 if (found.FromJust() && desc.enumerable()) {
189 // 4c ii 1. Let propValue be ? Get(from, nextKey).
190 Handle<Object> prop_value;
191 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
192 isolate, prop_value,
193 Runtime::GetObjectProperty(isolate, from, next_key));
194 // 4c ii 2. Let status be ? Set(to, nextKey, propValue, true).
195 Handle<Object> status;
196 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
197 isolate, status, Runtime::SetObjectProperty(isolate, to, next_key,
198 prop_value, STRICT));
199 }
200 }
201 }
202 // 5. Return to.
203 return *to;
204 }
205
206 // ES6 section 19.1.3.4 Object.prototype.propertyIsEnumerable ( V )
BUILTIN(ObjectPrototypePropertyIsEnumerable)207 BUILTIN(ObjectPrototypePropertyIsEnumerable) {
208 HandleScope scope(isolate);
209 Handle<JSReceiver> object;
210 Handle<Name> name;
211 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
212 isolate, name, Object::ToName(isolate, args.atOrUndefined(isolate, 1)));
213 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
214 isolate, object, JSReceiver::ToObject(isolate, args.receiver()));
215 Maybe<PropertyAttributes> maybe =
216 JSReceiver::GetOwnPropertyAttributes(object, name);
217 if (!maybe.IsJust()) return isolate->heap()->exception();
218 if (maybe.FromJust() == ABSENT) return isolate->heap()->false_value();
219 return isolate->heap()->ToBoolean((maybe.FromJust() & DONT_ENUM) == 0);
220 }
221
222 namespace { // anonymous namespace for ObjectProtoToString()
223
IsString(CodeStubAssembler * assembler,compiler::Node * object,CodeStubAssembler::Label * if_string,CodeStubAssembler::Label * if_notstring)224 void IsString(CodeStubAssembler* assembler, compiler::Node* object,
225 CodeStubAssembler::Label* if_string,
226 CodeStubAssembler::Label* if_notstring) {
227 typedef compiler::Node Node;
228 typedef CodeStubAssembler::Label Label;
229
230 Label if_notsmi(assembler);
231 assembler->Branch(assembler->TaggedIsSmi(object), if_notstring, &if_notsmi);
232
233 assembler->Bind(&if_notsmi);
234 {
235 Node* instance_type = assembler->LoadInstanceType(object);
236
237 assembler->Branch(assembler->IsStringInstanceType(instance_type), if_string,
238 if_notstring);
239 }
240 }
241
ReturnToStringFormat(CodeStubAssembler * assembler,compiler::Node * context,compiler::Node * string)242 void ReturnToStringFormat(CodeStubAssembler* assembler, compiler::Node* context,
243 compiler::Node* string) {
244 typedef compiler::Node Node;
245
246 Node* lhs = assembler->HeapConstant(
247 assembler->factory()->NewStringFromStaticChars("[object "));
248 Node* rhs = assembler->HeapConstant(
249 assembler->factory()->NewStringFromStaticChars("]"));
250
251 Callable callable = CodeFactory::StringAdd(
252 assembler->isolate(), STRING_ADD_CHECK_NONE, NOT_TENURED);
253
254 assembler->Return(assembler->CallStub(
255 callable, context, assembler->CallStub(callable, context, lhs, string),
256 rhs));
257 }
258
ReturnIfPrimitive(CodeStubAssembler * assembler,compiler::Node * instance_type,CodeStubAssembler::Label * return_string,CodeStubAssembler::Label * return_boolean,CodeStubAssembler::Label * return_number)259 void ReturnIfPrimitive(CodeStubAssembler* assembler,
260 compiler::Node* instance_type,
261 CodeStubAssembler::Label* return_string,
262 CodeStubAssembler::Label* return_boolean,
263 CodeStubAssembler::Label* return_number) {
264 assembler->GotoIf(assembler->IsStringInstanceType(instance_type),
265 return_string);
266
267 assembler->GotoIf(assembler->Word32Equal(
268 instance_type, assembler->Int32Constant(ODDBALL_TYPE)),
269 return_boolean);
270
271 assembler->GotoIf(
272 assembler->Word32Equal(instance_type,
273 assembler->Int32Constant(HEAP_NUMBER_TYPE)),
274 return_number);
275 }
276
277 } // namespace
278
279 // ES6 section 19.1.3.6 Object.prototype.toString
Generate_ObjectProtoToString(CodeStubAssembler * assembler)280 void Builtins::Generate_ObjectProtoToString(CodeStubAssembler* assembler) {
281 typedef compiler::Node Node;
282 typedef CodeStubAssembler::Label Label;
283 typedef CodeStubAssembler::Variable Variable;
284
285 Label return_undefined(assembler, Label::kDeferred),
286 return_null(assembler, Label::kDeferred),
287 return_arguments(assembler, Label::kDeferred), return_array(assembler),
288 return_api(assembler, Label::kDeferred), return_object(assembler),
289 return_regexp(assembler), return_function(assembler),
290 return_error(assembler), return_date(assembler), return_string(assembler),
291 return_boolean(assembler), return_jsvalue(assembler),
292 return_jsproxy(assembler, Label::kDeferred), return_number(assembler);
293
294 Label if_isproxy(assembler, Label::kDeferred);
295
296 Label checkstringtag(assembler);
297 Label if_tostringtag(assembler), if_notostringtag(assembler);
298
299 Node* receiver = assembler->Parameter(0);
300 Node* context = assembler->Parameter(3);
301
302 assembler->GotoIf(
303 assembler->WordEqual(receiver, assembler->UndefinedConstant()),
304 &return_undefined);
305
306 assembler->GotoIf(assembler->WordEqual(receiver, assembler->NullConstant()),
307 &return_null);
308
309 assembler->GotoIf(assembler->TaggedIsSmi(receiver), &return_number);
310
311 Node* receiver_instance_type = assembler->LoadInstanceType(receiver);
312 ReturnIfPrimitive(assembler, receiver_instance_type, &return_string,
313 &return_boolean, &return_number);
314
315 // for proxies, check IsArray before getting @@toStringTag
316 Variable var_proxy_is_array(assembler, MachineRepresentation::kTagged);
317 var_proxy_is_array.Bind(assembler->BooleanConstant(false));
318
319 assembler->Branch(
320 assembler->Word32Equal(receiver_instance_type,
321 assembler->Int32Constant(JS_PROXY_TYPE)),
322 &if_isproxy, &checkstringtag);
323
324 assembler->Bind(&if_isproxy);
325 {
326 // This can throw
327 var_proxy_is_array.Bind(
328 assembler->CallRuntime(Runtime::kArrayIsArray, context, receiver));
329 assembler->Goto(&checkstringtag);
330 }
331
332 assembler->Bind(&checkstringtag);
333 {
334 Node* to_string_tag_symbol = assembler->HeapConstant(
335 assembler->isolate()->factory()->to_string_tag_symbol());
336
337 GetPropertyStub stub(assembler->isolate());
338 Callable get_property =
339 Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
340 Node* to_string_tag_value = assembler->CallStub(
341 get_property, context, receiver, to_string_tag_symbol);
342
343 IsString(assembler, to_string_tag_value, &if_tostringtag,
344 &if_notostringtag);
345
346 assembler->Bind(&if_tostringtag);
347 ReturnToStringFormat(assembler, context, to_string_tag_value);
348 }
349 assembler->Bind(&if_notostringtag);
350 {
351 size_t const kNumCases = 11;
352 Label* case_labels[kNumCases];
353 int32_t case_values[kNumCases];
354 case_labels[0] = &return_api;
355 case_values[0] = JS_API_OBJECT_TYPE;
356 case_labels[1] = &return_api;
357 case_values[1] = JS_SPECIAL_API_OBJECT_TYPE;
358 case_labels[2] = &return_arguments;
359 case_values[2] = JS_ARGUMENTS_TYPE;
360 case_labels[3] = &return_array;
361 case_values[3] = JS_ARRAY_TYPE;
362 case_labels[4] = &return_function;
363 case_values[4] = JS_BOUND_FUNCTION_TYPE;
364 case_labels[5] = &return_function;
365 case_values[5] = JS_FUNCTION_TYPE;
366 case_labels[6] = &return_error;
367 case_values[6] = JS_ERROR_TYPE;
368 case_labels[7] = &return_date;
369 case_values[7] = JS_DATE_TYPE;
370 case_labels[8] = &return_regexp;
371 case_values[8] = JS_REGEXP_TYPE;
372 case_labels[9] = &return_jsvalue;
373 case_values[9] = JS_VALUE_TYPE;
374 case_labels[10] = &return_jsproxy;
375 case_values[10] = JS_PROXY_TYPE;
376
377 assembler->Switch(receiver_instance_type, &return_object, case_values,
378 case_labels, arraysize(case_values));
379
380 assembler->Bind(&return_undefined);
381 assembler->Return(assembler->HeapConstant(
382 assembler->isolate()->factory()->undefined_to_string()));
383
384 assembler->Bind(&return_null);
385 assembler->Return(assembler->HeapConstant(
386 assembler->isolate()->factory()->null_to_string()));
387
388 assembler->Bind(&return_number);
389 assembler->Return(assembler->HeapConstant(
390 assembler->isolate()->factory()->number_to_string()));
391
392 assembler->Bind(&return_string);
393 assembler->Return(assembler->HeapConstant(
394 assembler->isolate()->factory()->string_to_string()));
395
396 assembler->Bind(&return_boolean);
397 assembler->Return(assembler->HeapConstant(
398 assembler->isolate()->factory()->boolean_to_string()));
399
400 assembler->Bind(&return_arguments);
401 assembler->Return(assembler->HeapConstant(
402 assembler->isolate()->factory()->arguments_to_string()));
403
404 assembler->Bind(&return_array);
405 assembler->Return(assembler->HeapConstant(
406 assembler->isolate()->factory()->array_to_string()));
407
408 assembler->Bind(&return_function);
409 assembler->Return(assembler->HeapConstant(
410 assembler->isolate()->factory()->function_to_string()));
411
412 assembler->Bind(&return_error);
413 assembler->Return(assembler->HeapConstant(
414 assembler->isolate()->factory()->error_to_string()));
415
416 assembler->Bind(&return_date);
417 assembler->Return(assembler->HeapConstant(
418 assembler->isolate()->factory()->date_to_string()));
419
420 assembler->Bind(&return_regexp);
421 assembler->Return(assembler->HeapConstant(
422 assembler->isolate()->factory()->regexp_to_string()));
423
424 assembler->Bind(&return_api);
425 {
426 Node* class_name =
427 assembler->CallRuntime(Runtime::kClassOf, context, receiver);
428 ReturnToStringFormat(assembler, context, class_name);
429 }
430
431 assembler->Bind(&return_jsvalue);
432 {
433 Node* value = assembler->LoadJSValueValue(receiver);
434 assembler->GotoIf(assembler->TaggedIsSmi(value), &return_number);
435
436 ReturnIfPrimitive(assembler, assembler->LoadInstanceType(value),
437 &return_string, &return_boolean, &return_number);
438 assembler->Goto(&return_object);
439 }
440
441 assembler->Bind(&return_jsproxy);
442 {
443 assembler->GotoIf(assembler->WordEqual(var_proxy_is_array.value(),
444 assembler->BooleanConstant(true)),
445 &return_array);
446
447 Node* map = assembler->LoadMap(receiver);
448
449 // Return object if the proxy {receiver} is not callable.
450 assembler->Branch(assembler->IsCallableMap(map), &return_function,
451 &return_object);
452 }
453
454 // Default
455 assembler->Bind(&return_object);
456 assembler->Return(assembler->HeapConstant(
457 assembler->isolate()->factory()->object_to_string()));
458 }
459 }
460
Generate_ObjectCreate(CodeStubAssembler * a)461 void Builtins::Generate_ObjectCreate(CodeStubAssembler* a) {
462 typedef compiler::Node Node;
463 typedef CodeStubAssembler::Label Label;
464 typedef CodeStubAssembler::Variable Variable;
465
466 Node* prototype = a->Parameter(1);
467 Node* properties = a->Parameter(2);
468 Node* context = a->Parameter(3 + 2);
469
470 Label call_runtime(a, Label::kDeferred), prototype_valid(a), no_properties(a);
471 {
472 a->Comment("Argument 1 check: prototype");
473 a->GotoIf(a->WordEqual(prototype, a->NullConstant()), &prototype_valid);
474 a->BranchIfJSReceiver(prototype, &prototype_valid, &call_runtime);
475 }
476
477 a->Bind(&prototype_valid);
478 {
479 a->Comment("Argument 2 check: properties");
480 // Check that we have a simple object
481 a->GotoIf(a->TaggedIsSmi(properties), &call_runtime);
482 // Undefined implies no properties.
483 a->GotoIf(a->WordEqual(properties, a->UndefinedConstant()), &no_properties);
484 Node* properties_map = a->LoadMap(properties);
485 a->GotoIf(a->IsSpecialReceiverMap(properties_map), &call_runtime);
486 // Stay on the fast path only if there are no elements.
487 a->GotoUnless(a->WordEqual(a->LoadElements(properties),
488 a->LoadRoot(Heap::kEmptyFixedArrayRootIndex)),
489 &call_runtime);
490 // Handle dictionary objects or fast objects with properties in runtime.
491 Node* bit_field3 = a->LoadMapBitField3(properties_map);
492 a->GotoIf(a->IsSetWord32<Map::DictionaryMap>(bit_field3), &call_runtime);
493 a->Branch(a->IsSetWord32<Map::NumberOfOwnDescriptorsBits>(bit_field3),
494 &call_runtime, &no_properties);
495 }
496
497 // Create a new object with the given prototype.
498 a->Bind(&no_properties);
499 {
500 Variable map(a, MachineRepresentation::kTagged);
501 Variable properties(a, MachineRepresentation::kTagged);
502 Label non_null_proto(a), instantiate_map(a), good(a);
503
504 a->Branch(a->WordEqual(prototype, a->NullConstant()), &good,
505 &non_null_proto);
506
507 a->Bind(&good);
508 {
509 map.Bind(a->LoadContextElement(
510 context, Context::SLOW_OBJECT_WITH_NULL_PROTOTYPE_MAP));
511 properties.Bind(
512 a->AllocateNameDictionary(NameDictionary::kInitialCapacity));
513 a->Goto(&instantiate_map);
514 }
515
516 a->Bind(&non_null_proto);
517 {
518 properties.Bind(a->EmptyFixedArrayConstant());
519 Node* object_function =
520 a->LoadContextElement(context, Context::OBJECT_FUNCTION_INDEX);
521 Node* object_function_map = a->LoadObjectField(
522 object_function, JSFunction::kPrototypeOrInitialMapOffset);
523 map.Bind(object_function_map);
524 a->GotoIf(a->WordEqual(prototype, a->LoadMapPrototype(map.value())),
525 &instantiate_map);
526 // Try loading the prototype info.
527 Node* prototype_info =
528 a->LoadMapPrototypeInfo(a->LoadMap(prototype), &call_runtime);
529 a->Comment("Load ObjectCreateMap from PrototypeInfo");
530 Node* weak_cell =
531 a->LoadObjectField(prototype_info, PrototypeInfo::kObjectCreateMap);
532 a->GotoIf(a->WordEqual(weak_cell, a->UndefinedConstant()), &call_runtime);
533 map.Bind(a->LoadWeakCellValue(weak_cell, &call_runtime));
534 a->Goto(&instantiate_map);
535 }
536
537 a->Bind(&instantiate_map);
538 {
539 Node* instance =
540 a->AllocateJSObjectFromMap(map.value(), properties.value());
541 a->Return(instance);
542 }
543 }
544
545 a->Bind(&call_runtime);
546 {
547 a->Return(
548 a->CallRuntime(Runtime::kObjectCreate, context, prototype, properties));
549 }
550 }
551
552 // ES6 section 19.1.2.3 Object.defineProperties
BUILTIN(ObjectDefineProperties)553 BUILTIN(ObjectDefineProperties) {
554 HandleScope scope(isolate);
555 DCHECK_EQ(3, args.length());
556 Handle<Object> target = args.at<Object>(1);
557 Handle<Object> properties = args.at<Object>(2);
558
559 RETURN_RESULT_OR_FAILURE(
560 isolate, JSReceiver::DefineProperties(isolate, target, properties));
561 }
562
563 // ES6 section 19.1.2.4 Object.defineProperty
BUILTIN(ObjectDefineProperty)564 BUILTIN(ObjectDefineProperty) {
565 HandleScope scope(isolate);
566 DCHECK_EQ(4, args.length());
567 Handle<Object> target = args.at<Object>(1);
568 Handle<Object> key = args.at<Object>(2);
569 Handle<Object> attributes = args.at<Object>(3);
570
571 return JSReceiver::DefineProperty(isolate, target, key, attributes);
572 }
573
574 namespace {
575
576 template <AccessorComponent which_accessor>
ObjectDefineAccessor(Isolate * isolate,Handle<Object> object,Handle<Object> name,Handle<Object> accessor)577 Object* ObjectDefineAccessor(Isolate* isolate, Handle<Object> object,
578 Handle<Object> name, Handle<Object> accessor) {
579 // 1. Let O be ? ToObject(this value).
580 Handle<JSReceiver> receiver;
581 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
582 Object::ConvertReceiver(isolate, object));
583 // 2. If IsCallable(getter) is false, throw a TypeError exception.
584 if (!accessor->IsCallable()) {
585 MessageTemplate::Template message =
586 which_accessor == ACCESSOR_GETTER
587 ? MessageTemplate::kObjectGetterExpectingFunction
588 : MessageTemplate::kObjectSetterExpectingFunction;
589 THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(message));
590 }
591 // 3. Let desc be PropertyDescriptor{[[Get]]: getter, [[Enumerable]]: true,
592 // [[Configurable]]: true}.
593 PropertyDescriptor desc;
594 if (which_accessor == ACCESSOR_GETTER) {
595 desc.set_get(accessor);
596 } else {
597 DCHECK(which_accessor == ACCESSOR_SETTER);
598 desc.set_set(accessor);
599 }
600 desc.set_enumerable(true);
601 desc.set_configurable(true);
602 // 4. Let key be ? ToPropertyKey(P).
603 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
604 Object::ToPropertyKey(isolate, name));
605 // 5. Perform ? DefinePropertyOrThrow(O, key, desc).
606 // To preserve legacy behavior, we ignore errors silently rather than
607 // throwing an exception.
608 Maybe<bool> success = JSReceiver::DefineOwnProperty(
609 isolate, receiver, name, &desc, Object::DONT_THROW);
610 MAYBE_RETURN(success, isolate->heap()->exception());
611 if (!success.FromJust()) {
612 isolate->CountUsage(v8::Isolate::kDefineGetterOrSetterWouldThrow);
613 }
614 // 6. Return undefined.
615 return isolate->heap()->undefined_value();
616 }
617
ObjectLookupAccessor(Isolate * isolate,Handle<Object> object,Handle<Object> key,AccessorComponent component)618 Object* ObjectLookupAccessor(Isolate* isolate, Handle<Object> object,
619 Handle<Object> key, AccessorComponent component) {
620 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, object,
621 Object::ConvertReceiver(isolate, object));
622 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key,
623 Object::ToPropertyKey(isolate, key));
624 bool success = false;
625 LookupIterator it = LookupIterator::PropertyOrElement(
626 isolate, object, key, &success,
627 LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
628 DCHECK(success);
629
630 for (; it.IsFound(); it.Next()) {
631 switch (it.state()) {
632 case LookupIterator::INTERCEPTOR:
633 case LookupIterator::NOT_FOUND:
634 case LookupIterator::TRANSITION:
635 UNREACHABLE();
636
637 case LookupIterator::ACCESS_CHECK:
638 if (it.HasAccess()) continue;
639 isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>());
640 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
641 return isolate->heap()->undefined_value();
642
643 case LookupIterator::JSPROXY:
644 return isolate->heap()->undefined_value();
645
646 case LookupIterator::INTEGER_INDEXED_EXOTIC:
647 return isolate->heap()->undefined_value();
648 case LookupIterator::DATA:
649 continue;
650 case LookupIterator::ACCESSOR: {
651 Handle<Object> maybe_pair = it.GetAccessors();
652 if (maybe_pair->IsAccessorPair()) {
653 return *AccessorPair::GetComponent(
654 Handle<AccessorPair>::cast(maybe_pair), component);
655 }
656 }
657 }
658 }
659
660 return isolate->heap()->undefined_value();
661 }
662
663 } // namespace
664
665 // ES6 B.2.2.2 a.k.a.
666 // https://tc39.github.io/ecma262/#sec-object.prototype.__defineGetter__
BUILTIN(ObjectDefineGetter)667 BUILTIN(ObjectDefineGetter) {
668 HandleScope scope(isolate);
669 Handle<Object> object = args.at<Object>(0); // Receiver.
670 Handle<Object> name = args.at<Object>(1);
671 Handle<Object> getter = args.at<Object>(2);
672 return ObjectDefineAccessor<ACCESSOR_GETTER>(isolate, object, name, getter);
673 }
674
675 // ES6 B.2.2.3 a.k.a.
676 // https://tc39.github.io/ecma262/#sec-object.prototype.__defineSetter__
BUILTIN(ObjectDefineSetter)677 BUILTIN(ObjectDefineSetter) {
678 HandleScope scope(isolate);
679 Handle<Object> object = args.at<Object>(0); // Receiver.
680 Handle<Object> name = args.at<Object>(1);
681 Handle<Object> setter = args.at<Object>(2);
682 return ObjectDefineAccessor<ACCESSOR_SETTER>(isolate, object, name, setter);
683 }
684
685 // ES6 B.2.2.4 a.k.a.
686 // https://tc39.github.io/ecma262/#sec-object.prototype.__lookupGetter__
BUILTIN(ObjectLookupGetter)687 BUILTIN(ObjectLookupGetter) {
688 HandleScope scope(isolate);
689 Handle<Object> object = args.at<Object>(0);
690 Handle<Object> name = args.at<Object>(1);
691 return ObjectLookupAccessor(isolate, object, name, ACCESSOR_GETTER);
692 }
693
694 // ES6 B.2.2.5 a.k.a.
695 // https://tc39.github.io/ecma262/#sec-object.prototype.__lookupSetter__
BUILTIN(ObjectLookupSetter)696 BUILTIN(ObjectLookupSetter) {
697 HandleScope scope(isolate);
698 Handle<Object> object = args.at<Object>(0);
699 Handle<Object> name = args.at<Object>(1);
700 return ObjectLookupAccessor(isolate, object, name, ACCESSOR_SETTER);
701 }
702
703 // ES6 section 19.1.2.5 Object.freeze ( O )
BUILTIN(ObjectFreeze)704 BUILTIN(ObjectFreeze) {
705 HandleScope scope(isolate);
706 Handle<Object> object = args.atOrUndefined(isolate, 1);
707 if (object->IsJSReceiver()) {
708 MAYBE_RETURN(JSReceiver::SetIntegrityLevel(Handle<JSReceiver>::cast(object),
709 FROZEN, Object::THROW_ON_ERROR),
710 isolate->heap()->exception());
711 }
712 return *object;
713 }
714
715 // ES section 19.1.2.9 Object.getPrototypeOf ( O )
BUILTIN(ObjectGetPrototypeOf)716 BUILTIN(ObjectGetPrototypeOf) {
717 HandleScope scope(isolate);
718 Handle<Object> object = args.atOrUndefined(isolate, 1);
719
720 Handle<JSReceiver> receiver;
721 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
722 Object::ToObject(isolate, object));
723
724 RETURN_RESULT_OR_FAILURE(isolate,
725 JSReceiver::GetPrototype(isolate, receiver));
726 }
727
728 // ES6 section 19.1.2.21 Object.setPrototypeOf ( O, proto )
BUILTIN(ObjectSetPrototypeOf)729 BUILTIN(ObjectSetPrototypeOf) {
730 HandleScope scope(isolate);
731
732 // 1. Let O be ? RequireObjectCoercible(O).
733 Handle<Object> object = args.atOrUndefined(isolate, 1);
734 if (object->IsNull(isolate) || object->IsUndefined(isolate)) {
735 THROW_NEW_ERROR_RETURN_FAILURE(
736 isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined,
737 isolate->factory()->NewStringFromAsciiChecked(
738 "Object.setPrototypeOf")));
739 }
740
741 // 2. If Type(proto) is neither Object nor Null, throw a TypeError exception.
742 Handle<Object> proto = args.atOrUndefined(isolate, 2);
743 if (!proto->IsNull(isolate) && !proto->IsJSReceiver()) {
744 THROW_NEW_ERROR_RETURN_FAILURE(
745 isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, proto));
746 }
747
748 // 3. If Type(O) is not Object, return O.
749 if (!object->IsJSReceiver()) return *object;
750 Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
751
752 // 4. Let status be ? O.[[SetPrototypeOf]](proto).
753 // 5. If status is false, throw a TypeError exception.
754 MAYBE_RETURN(
755 JSReceiver::SetPrototype(receiver, proto, true, Object::THROW_ON_ERROR),
756 isolate->heap()->exception());
757
758 // 6. Return O.
759 return *receiver;
760 }
761
762 // ES6 section B.2.2.1.1 get Object.prototype.__proto__
BUILTIN(ObjectPrototypeGetProto)763 BUILTIN(ObjectPrototypeGetProto) {
764 HandleScope scope(isolate);
765 // 1. Let O be ? ToObject(this value).
766 Handle<JSReceiver> receiver;
767 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
768 isolate, receiver, Object::ToObject(isolate, args.receiver()));
769
770 // 2. Return ? O.[[GetPrototypeOf]]().
771 RETURN_RESULT_OR_FAILURE(isolate,
772 JSReceiver::GetPrototype(isolate, receiver));
773 }
774
775 // ES6 section B.2.2.1.2 set Object.prototype.__proto__
BUILTIN(ObjectPrototypeSetProto)776 BUILTIN(ObjectPrototypeSetProto) {
777 HandleScope scope(isolate);
778 // 1. Let O be ? RequireObjectCoercible(this value).
779 Handle<Object> object = args.receiver();
780 if (object->IsNull(isolate) || object->IsUndefined(isolate)) {
781 THROW_NEW_ERROR_RETURN_FAILURE(
782 isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined,
783 isolate->factory()->NewStringFromAsciiChecked(
784 "set Object.prototype.__proto__")));
785 }
786
787 // 2. If Type(proto) is neither Object nor Null, return undefined.
788 Handle<Object> proto = args.at<Object>(1);
789 if (!proto->IsNull(isolate) && !proto->IsJSReceiver()) {
790 return isolate->heap()->undefined_value();
791 }
792
793 // 3. If Type(O) is not Object, return undefined.
794 if (!object->IsJSReceiver()) return isolate->heap()->undefined_value();
795 Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
796
797 // 4. Let status be ? O.[[SetPrototypeOf]](proto).
798 // 5. If status is false, throw a TypeError exception.
799 MAYBE_RETURN(
800 JSReceiver::SetPrototype(receiver, proto, true, Object::THROW_ON_ERROR),
801 isolate->heap()->exception());
802
803 // Return undefined.
804 return isolate->heap()->undefined_value();
805 }
806
807 // ES6 section 19.1.2.6 Object.getOwnPropertyDescriptor ( O, P )
BUILTIN(ObjectGetOwnPropertyDescriptor)808 BUILTIN(ObjectGetOwnPropertyDescriptor) {
809 HandleScope scope(isolate);
810 // 1. Let obj be ? ToObject(O).
811 Handle<Object> object = args.atOrUndefined(isolate, 1);
812 Handle<JSReceiver> receiver;
813 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
814 Object::ToObject(isolate, object));
815 // 2. Let key be ? ToPropertyKey(P).
816 Handle<Object> property = args.atOrUndefined(isolate, 2);
817 Handle<Name> key;
818 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key,
819 Object::ToName(isolate, property));
820 // 3. Let desc be ? obj.[[GetOwnProperty]](key).
821 PropertyDescriptor desc;
822 Maybe<bool> found =
823 JSReceiver::GetOwnPropertyDescriptor(isolate, receiver, key, &desc);
824 MAYBE_RETURN(found, isolate->heap()->exception());
825 // 4. Return FromPropertyDescriptor(desc).
826 if (!found.FromJust()) return isolate->heap()->undefined_value();
827 return *desc.ToObject(isolate);
828 }
829
830 namespace {
831
GetOwnPropertyKeys(Isolate * isolate,BuiltinArguments args,PropertyFilter filter)832 Object* GetOwnPropertyKeys(Isolate* isolate, BuiltinArguments args,
833 PropertyFilter filter) {
834 HandleScope scope(isolate);
835 Handle<Object> object = args.atOrUndefined(isolate, 1);
836 Handle<JSReceiver> receiver;
837 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
838 Object::ToObject(isolate, object));
839 Handle<FixedArray> keys;
840 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
841 isolate, keys,
842 KeyAccumulator::GetKeys(receiver, KeyCollectionMode::kOwnOnly, filter,
843 GetKeysConversion::kConvertToString));
844 return *isolate->factory()->NewJSArrayWithElements(keys);
845 }
846
847 } // namespace
848
849 // ES6 section 19.1.2.7 Object.getOwnPropertyNames ( O )
BUILTIN(ObjectGetOwnPropertyNames)850 BUILTIN(ObjectGetOwnPropertyNames) {
851 return GetOwnPropertyKeys(isolate, args, SKIP_SYMBOLS);
852 }
853
854 // ES6 section 19.1.2.8 Object.getOwnPropertySymbols ( O )
BUILTIN(ObjectGetOwnPropertySymbols)855 BUILTIN(ObjectGetOwnPropertySymbols) {
856 return GetOwnPropertyKeys(isolate, args, SKIP_STRINGS);
857 }
858
859 // ES#sec-object.is Object.is ( value1, value2 )
BUILTIN(ObjectIs)860 BUILTIN(ObjectIs) {
861 SealHandleScope shs(isolate);
862 DCHECK_EQ(3, args.length());
863 Handle<Object> value1 = args.at<Object>(1);
864 Handle<Object> value2 = args.at<Object>(2);
865 return isolate->heap()->ToBoolean(value1->SameValue(*value2));
866 }
867
868 // ES6 section 19.1.2.11 Object.isExtensible ( O )
BUILTIN(ObjectIsExtensible)869 BUILTIN(ObjectIsExtensible) {
870 HandleScope scope(isolate);
871 Handle<Object> object = args.atOrUndefined(isolate, 1);
872 Maybe<bool> result =
873 object->IsJSReceiver()
874 ? JSReceiver::IsExtensible(Handle<JSReceiver>::cast(object))
875 : Just(false);
876 MAYBE_RETURN(result, isolate->heap()->exception());
877 return isolate->heap()->ToBoolean(result.FromJust());
878 }
879
880 // ES6 section 19.1.2.12 Object.isFrozen ( O )
BUILTIN(ObjectIsFrozen)881 BUILTIN(ObjectIsFrozen) {
882 HandleScope scope(isolate);
883 Handle<Object> object = args.atOrUndefined(isolate, 1);
884 Maybe<bool> result = object->IsJSReceiver()
885 ? JSReceiver::TestIntegrityLevel(
886 Handle<JSReceiver>::cast(object), FROZEN)
887 : Just(true);
888 MAYBE_RETURN(result, isolate->heap()->exception());
889 return isolate->heap()->ToBoolean(result.FromJust());
890 }
891
892 // ES6 section 19.1.2.13 Object.isSealed ( O )
BUILTIN(ObjectIsSealed)893 BUILTIN(ObjectIsSealed) {
894 HandleScope scope(isolate);
895 Handle<Object> object = args.atOrUndefined(isolate, 1);
896 Maybe<bool> result = object->IsJSReceiver()
897 ? JSReceiver::TestIntegrityLevel(
898 Handle<JSReceiver>::cast(object), SEALED)
899 : Just(true);
900 MAYBE_RETURN(result, isolate->heap()->exception());
901 return isolate->heap()->ToBoolean(result.FromJust());
902 }
903
904 // ES6 section 19.1.2.14 Object.keys ( O )
BUILTIN(ObjectKeys)905 BUILTIN(ObjectKeys) {
906 HandleScope scope(isolate);
907 Handle<Object> object = args.atOrUndefined(isolate, 1);
908 Handle<JSReceiver> receiver;
909 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
910 Object::ToObject(isolate, object));
911
912 Handle<FixedArray> keys;
913 int enum_length = receiver->map()->EnumLength();
914 if (enum_length != kInvalidEnumCacheSentinel &&
915 JSObject::cast(*receiver)->elements() ==
916 isolate->heap()->empty_fixed_array()) {
917 DCHECK(receiver->IsJSObject());
918 DCHECK(!JSObject::cast(*receiver)->HasNamedInterceptor());
919 DCHECK(!JSObject::cast(*receiver)->IsAccessCheckNeeded());
920 DCHECK(!receiver->map()->has_hidden_prototype());
921 DCHECK(JSObject::cast(*receiver)->HasFastProperties());
922 if (enum_length == 0) {
923 keys = isolate->factory()->empty_fixed_array();
924 } else {
925 Handle<FixedArray> cache(
926 receiver->map()->instance_descriptors()->GetEnumCache());
927 keys = isolate->factory()->CopyFixedArrayUpTo(cache, enum_length);
928 }
929 } else {
930 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
931 isolate, keys,
932 KeyAccumulator::GetKeys(receiver, KeyCollectionMode::kOwnOnly,
933 ENUMERABLE_STRINGS,
934 GetKeysConversion::kConvertToString));
935 }
936 return *isolate->factory()->NewJSArrayWithElements(keys, FAST_ELEMENTS);
937 }
938
BUILTIN(ObjectValues)939 BUILTIN(ObjectValues) {
940 HandleScope scope(isolate);
941 Handle<Object> object = args.atOrUndefined(isolate, 1);
942 Handle<JSReceiver> receiver;
943 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
944 Object::ToObject(isolate, object));
945 Handle<FixedArray> values;
946 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
947 isolate, values, JSReceiver::GetOwnValues(receiver, ENUMERABLE_STRINGS));
948 return *isolate->factory()->NewJSArrayWithElements(values);
949 }
950
BUILTIN(ObjectEntries)951 BUILTIN(ObjectEntries) {
952 HandleScope scope(isolate);
953 Handle<Object> object = args.atOrUndefined(isolate, 1);
954 Handle<JSReceiver> receiver;
955 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
956 Object::ToObject(isolate, object));
957 Handle<FixedArray> entries;
958 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
959 isolate, entries,
960 JSReceiver::GetOwnEntries(receiver, ENUMERABLE_STRINGS));
961 return *isolate->factory()->NewJSArrayWithElements(entries);
962 }
963
BUILTIN(ObjectGetOwnPropertyDescriptors)964 BUILTIN(ObjectGetOwnPropertyDescriptors) {
965 HandleScope scope(isolate);
966 Handle<Object> object = args.atOrUndefined(isolate, 1);
967
968 Handle<JSReceiver> receiver;
969 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
970 Object::ToObject(isolate, object));
971
972 Handle<FixedArray> keys;
973 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
974 isolate, keys, KeyAccumulator::GetKeys(
975 receiver, KeyCollectionMode::kOwnOnly, ALL_PROPERTIES,
976 GetKeysConversion::kConvertToString));
977
978 Handle<JSObject> descriptors =
979 isolate->factory()->NewJSObject(isolate->object_function());
980
981 for (int i = 0; i < keys->length(); ++i) {
982 Handle<Name> key = Handle<Name>::cast(FixedArray::get(*keys, i, isolate));
983 PropertyDescriptor descriptor;
984 Maybe<bool> did_get_descriptor = JSReceiver::GetOwnPropertyDescriptor(
985 isolate, receiver, key, &descriptor);
986 MAYBE_RETURN(did_get_descriptor, isolate->heap()->exception());
987
988 if (!did_get_descriptor.FromJust()) continue;
989 Handle<Object> from_descriptor = descriptor.ToObject(isolate);
990
991 LookupIterator it = LookupIterator::PropertyOrElement(
992 isolate, descriptors, key, descriptors, LookupIterator::OWN);
993 Maybe<bool> success = JSReceiver::CreateDataProperty(&it, from_descriptor,
994 Object::DONT_THROW);
995 CHECK(success.FromJust());
996 }
997
998 return *descriptors;
999 }
1000
1001 // ES6 section 19.1.2.15 Object.preventExtensions ( O )
BUILTIN(ObjectPreventExtensions)1002 BUILTIN(ObjectPreventExtensions) {
1003 HandleScope scope(isolate);
1004 Handle<Object> object = args.atOrUndefined(isolate, 1);
1005 if (object->IsJSReceiver()) {
1006 MAYBE_RETURN(JSReceiver::PreventExtensions(Handle<JSReceiver>::cast(object),
1007 Object::THROW_ON_ERROR),
1008 isolate->heap()->exception());
1009 }
1010 return *object;
1011 }
1012
1013 // ES6 section 19.1.2.17 Object.seal ( O )
BUILTIN(ObjectSeal)1014 BUILTIN(ObjectSeal) {
1015 HandleScope scope(isolate);
1016 Handle<Object> object = args.atOrUndefined(isolate, 1);
1017 if (object->IsJSReceiver()) {
1018 MAYBE_RETURN(JSReceiver::SetIntegrityLevel(Handle<JSReceiver>::cast(object),
1019 SEALED, Object::THROW_ON_ERROR),
1020 isolate->heap()->exception());
1021 }
1022 return *object;
1023 }
1024
Generate_HasProperty(CodeStubAssembler * assembler)1025 void Builtins::Generate_HasProperty(CodeStubAssembler* assembler) {
1026 typedef HasPropertyDescriptor Descriptor;
1027 typedef compiler::Node Node;
1028
1029 Node* key = assembler->Parameter(Descriptor::kKey);
1030 Node* object = assembler->Parameter(Descriptor::kObject);
1031 Node* context = assembler->Parameter(Descriptor::kContext);
1032
1033 assembler->Return(
1034 assembler->HasProperty(object, key, context, Runtime::kHasProperty));
1035 }
1036
Generate_ForInFilter(CodeStubAssembler * assembler)1037 void Builtins::Generate_ForInFilter(CodeStubAssembler* assembler) {
1038 typedef compiler::Node Node;
1039 typedef ForInFilterDescriptor Descriptor;
1040
1041 Node* key = assembler->Parameter(Descriptor::kKey);
1042 Node* object = assembler->Parameter(Descriptor::kObject);
1043 Node* context = assembler->Parameter(Descriptor::kContext);
1044
1045 assembler->Return(assembler->ForInFilter(key, object, context));
1046 }
1047
Generate_InstanceOf(CodeStubAssembler * assembler)1048 void Builtins::Generate_InstanceOf(CodeStubAssembler* assembler) {
1049 typedef compiler::Node Node;
1050 typedef CompareDescriptor Descriptor;
1051 Node* object = assembler->Parameter(Descriptor::kLeft);
1052 Node* callable = assembler->Parameter(Descriptor::kRight);
1053 Node* context = assembler->Parameter(Descriptor::kContext);
1054
1055 assembler->Return(assembler->InstanceOf(object, callable, context));
1056 }
1057
1058 // ES6 section 7.3.19 OrdinaryHasInstance ( C, O )
Generate_OrdinaryHasInstance(CodeStubAssembler * assembler)1059 void Builtins::Generate_OrdinaryHasInstance(CodeStubAssembler* assembler) {
1060 typedef compiler::Node Node;
1061 typedef CompareDescriptor Descriptor;
1062
1063 Node* constructor = assembler->Parameter(Descriptor::kLeft);
1064 Node* object = assembler->Parameter(Descriptor::kRight);
1065 Node* context = assembler->Parameter(Descriptor::kContext);
1066
1067 assembler->Return(
1068 assembler->OrdinaryHasInstance(context, constructor, object));
1069 }
1070
1071 } // namespace internal
1072 } // namespace v8
1073