OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 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 | 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/code-factory.h" | 8 #include "src/code-factory.h" |
9 #include "src/property-descriptor.h" | 9 #include "src/property-descriptor.h" |
10 | 10 |
(...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
452 &return_object, &return_function); | 452 &return_object, &return_function); |
453 } | 453 } |
454 | 454 |
455 // Default | 455 // Default |
456 assembler->Bind(&return_object); | 456 assembler->Bind(&return_object); |
457 assembler->Return(assembler->HeapConstant( | 457 assembler->Return(assembler->HeapConstant( |
458 assembler->isolate()->factory()->object_to_string())); | 458 assembler->isolate()->factory()->object_to_string())); |
459 } | 459 } |
460 } | 460 } |
461 | 461 |
462 // ES6 section 19.1.2.2 Object.create ( O [ , Properties ] ) | 462 void Builtins::Generate_ObjectCreate(CodeStubAssembler* a) { |
463 // TODO(verwaest): Support the common cases with precached map directly in | 463 typedef compiler::Node Node; |
464 // an Object.create stub. | 464 typedef CodeStubAssembler::Label Label; |
465 BUILTIN(ObjectCreate) { | 465 typedef CodeStubAssembler::Variable Variable; |
466 HandleScope scope(isolate); | 466 |
467 Handle<Object> prototype = args.atOrUndefined(isolate, 1); | 467 Node* prototype = a->Parameter(1); |
468 if (!prototype->IsNull(isolate) && !prototype->IsJSReceiver()) { | 468 Node* properties = a->Parameter(2); |
469 THROW_NEW_ERROR_RETURN_FAILURE( | 469 Node* context = a->Parameter(3 + 2); |
470 isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, prototype)); | 470 |
| 471 Label call_runtime(a, Label::kDeferred), prototype_valid(a), no_properties(a); |
| 472 { |
| 473 a->Comment("Argument 1 check: prototype"); |
| 474 a->GotoIf(a->WordEqual(prototype, a->NullConstant()), &prototype_valid); |
| 475 a->BranchIfJSReceiver(prototype, &prototype_valid, &call_runtime); |
471 } | 476 } |
472 | 477 |
473 // Generate the map with the specified {prototype} based on the Object | 478 a->Bind(&prototype_valid); |
474 // function's initial map from the current native context. | 479 { |
475 // TODO(bmeurer): Use a dedicated cache for Object.create; think about | 480 a->Comment("Argument 2 check: properties"); |
476 // slack tracking for Object.create. | 481 // Check that we have a simple object |
477 Handle<Map> map(isolate->native_context()->object_function()->initial_map(), | 482 a->GotoIf(a->TaggedIsSmi(properties), &call_runtime); |
478 isolate); | 483 // Undefined implies no properties. |
479 if (map->prototype() != *prototype) { | 484 a->GotoIf(a->WordEqual(properties, a->UndefinedConstant()), &no_properties); |
480 if (prototype->IsNull(isolate)) { | 485 Node* properties_map = a->LoadMap(properties); |
481 map = isolate->object_with_null_prototype_map(); | 486 a->GotoIf(a->IsSpecialReceiverMap(properties_map), &call_runtime); |
482 } else if (prototype->IsJSObject()) { | 487 // Stay on the fast path only if there are no elements. |
483 Handle<JSObject> js_prototype = Handle<JSObject>::cast(prototype); | 488 a->GotoUnless(a->WordEqual(a->LoadElements(properties), |
484 if (!js_prototype->map()->is_prototype_map()) { | 489 a->LoadRoot(Heap::kEmptyFixedArrayRootIndex)), |
485 JSObject::OptimizeAsPrototype(js_prototype, FAST_PROTOTYPE); | 490 &call_runtime); |
486 } | 491 // Jump to the runtime for slow objects. |
487 Handle<PrototypeInfo> info = | 492 Node* bit_field3 = a->LoadMapBitField3(properties_map); |
488 Map::GetOrCreatePrototypeInfo(js_prototype, isolate); | 493 Node* is_fast_map = a->Word32Equal( |
489 // TODO(verwaest): Use inobject slack tracking for this map. | 494 a->BitFieldDecode<Map::DictionaryMap>(bit_field3), a->Int32Constant(0)); |
490 if (info->HasObjectCreateMap()) { | 495 a->GotoUnless(is_fast_map, &call_runtime); |
491 map = handle(info->ObjectCreateMap(), isolate); | 496 |
492 } else { | 497 a->Branch( |
493 map = Map::CopyInitialMap(map); | 498 a->WordEqual( |
494 Map::SetPrototype(map, prototype, FAST_PROTOTYPE); | 499 a->BitFieldDecodeWord<Map::NumberOfOwnDescriptorsBits>(bit_field3), |
495 PrototypeInfo::SetObjectCreateMap(info, map); | 500 a->IntPtrConstant(0)), |
496 } | 501 &no_properties, &call_runtime); |
497 } else { | 502 } |
498 map = Map::TransitionToPrototype(map, prototype, REGULAR_PROTOTYPE); | 503 |
| 504 // Create a new object with the given prototype. |
| 505 a->Bind(&no_properties); |
| 506 { |
| 507 Variable map(a, MachineRepresentation::kTagged); |
| 508 Label non_null_proto(a), instantiate_map(a), good(a); |
| 509 |
| 510 a->Branch(a->WordEqual(prototype, a->NullConstant()), &good, |
| 511 &non_null_proto); |
| 512 |
| 513 a->Bind(&good); |
| 514 { |
| 515 map.Bind(a->LoadContextElement(context, |
| 516 Context::OBJECT_WITH_NULL_PROTOTYPE_MAP)); |
| 517 a->Goto(&instantiate_map); |
| 518 } |
| 519 |
| 520 a->Bind(&non_null_proto); |
| 521 { |
| 522 Node* object_function = |
| 523 a->LoadContextElement(context, Context::OBJECT_FUNCTION_INDEX); |
| 524 Node* object_function_map = a->LoadObjectField( |
| 525 object_function, JSFunction::kPrototypeOrInitialMapOffset); |
| 526 map.Bind(object_function_map); |
| 527 a->GotoIf(a->WordEqual(prototype, a->LoadMapPrototype(map.value())), |
| 528 &instantiate_map); |
| 529 // Try loading the prototype info. |
| 530 Node* prototype_info = |
| 531 a->LoadMapPrototypeInfo(a->LoadMap(prototype), &call_runtime); |
| 532 a->Comment("Load ObjectCreateMap from PrototypeInfo"); |
| 533 Node* weak_cell = |
| 534 a->LoadObjectField(prototype_info, PrototypeInfo::kObjectCreateMap); |
| 535 a->GotoIf(a->WordEqual(weak_cell, a->UndefinedConstant()), &call_runtime); |
| 536 map.Bind(a->LoadWeakCellValue(weak_cell, &call_runtime)); |
| 537 a->Goto(&instantiate_map); |
| 538 } |
| 539 |
| 540 a->Bind(&instantiate_map); |
| 541 { |
| 542 Node* instance = a->AllocateJSObjectFromMap(map.value()); |
| 543 a->Return(instance); |
499 } | 544 } |
500 } | 545 } |
501 | 546 |
502 // Actually allocate the object. | 547 a->Bind(&call_runtime); |
503 Handle<JSObject> object = isolate->factory()->NewJSObjectFromMap(map); | 548 { |
504 | 549 a->Return( |
505 // Define the properties if properties was specified and is not undefined. | 550 a->CallRuntime(Runtime::kObjectCreate, context, prototype, properties)); |
506 Handle<Object> properties = args.atOrUndefined(isolate, 2); | |
507 if (!properties->IsUndefined(isolate)) { | |
508 RETURN_FAILURE_ON_EXCEPTION( | |
509 isolate, JSReceiver::DefineProperties(isolate, object, properties)); | |
510 } | 551 } |
511 | |
512 return *object; | |
513 } | 552 } |
514 | 553 |
515 // ES6 section 19.1.2.3 Object.defineProperties | 554 // ES6 section 19.1.2.3 Object.defineProperties |
516 BUILTIN(ObjectDefineProperties) { | 555 BUILTIN(ObjectDefineProperties) { |
517 HandleScope scope(isolate); | 556 HandleScope scope(isolate); |
518 DCHECK_EQ(3, args.length()); | 557 DCHECK_EQ(3, args.length()); |
519 Handle<Object> target = args.at<Object>(1); | 558 Handle<Object> target = args.at<Object>(1); |
520 Handle<Object> properties = args.at<Object>(2); | 559 Handle<Object> properties = args.at<Object>(2); |
521 | 560 |
522 RETURN_RESULT_OR_FAILURE( | 561 RETURN_RESULT_OR_FAILURE( |
(...skipping 490 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1013 typedef CompareDescriptor Descriptor; | 1052 typedef CompareDescriptor Descriptor; |
1014 Node* object = assembler->Parameter(Descriptor::kLeft); | 1053 Node* object = assembler->Parameter(Descriptor::kLeft); |
1015 Node* callable = assembler->Parameter(Descriptor::kRight); | 1054 Node* callable = assembler->Parameter(Descriptor::kRight); |
1016 Node* context = assembler->Parameter(Descriptor::kContext); | 1055 Node* context = assembler->Parameter(Descriptor::kContext); |
1017 | 1056 |
1018 assembler->Return(assembler->InstanceOf(object, callable, context)); | 1057 assembler->Return(assembler->InstanceOf(object, callable, context)); |
1019 } | 1058 } |
1020 | 1059 |
1021 } // namespace internal | 1060 } // namespace internal |
1022 } // namespace v8 | 1061 } // namespace v8 |
OLD | NEW |