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

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

Issue 2385423005: [stubs] Implement fast TF Builtin for Object.create (Closed)
Patch Set: fix heap verification call Created 4 years, 2 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
OLDNEW
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
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(
Igor Sheludko 2016/10/18 12:33:21 a->IsFastMap(properties_map); ?
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->BranchIfWordEqual(a->LoadMapNumberOfOwnDescriptors(properties_map),
Igor Sheludko 2016/10/18 12:33:21 Here you load the bit_field3 again.
Camillo Bruni 2016/10/18 14:06:00 Ah, that was the reason I had the bitfield raw up
493 map = Map::CopyInitialMap(map); 498 a->IntPtrConstant(0), &no_properties, &call_runtime);
494 Map::SetPrototype(map, prototype, FAST_PROTOTYPE); 499 }
495 PrototypeInfo::SetObjectCreateMap(info, map); 500
496 } 501 // Create a new object with the given prototype.
497 } else { 502 a->Bind(&no_properties);
498 map = Map::TransitionToPrototype(map, prototype, REGULAR_PROTOTYPE); 503 {
504 Variable map(a, MachineRepresentation::kTagged);
505 Label non_null_proto(a), instantiate_map(a), good(a);
506
507 a->BranchIf(a->WordEqual(prototype, a->NullConstant()), &good,
508 &non_null_proto);
509
510 a->Bind(&good);
511 {
512 map.Bind(a->LoadContextElement(context,
513 Context::OBJECT_WITH_NULL_PROTOTYPE_MAP));
514 a->Goto(&instantiate_map);
515 }
516
517 a->Bind(&non_null_proto);
518 {
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->TaggedIsSmi(weak_cell), &call_runtime);
Camillo Bruni 2016/10/18 14:06:00 I removed the tagged check here as it is most like
533 a->GotoUnless(a->HasInstanceType(weak_cell, WEAK_CELL_TYPE),
Igor Sheludko 2016/10/18 12:33:21 Probably it should be an Assert instead. And map c
Camillo Bruni 2016/10/18 14:06:00 Added a test to cover the uninitlized ObjectCreate
534 &call_runtime);
535 map.Bind(a->LoadWeakCellValue(weak_cell, &call_runtime));
536 a->Goto(&instantiate_map);
537 }
538
539 a->Bind(&instantiate_map);
540 {
541 Node* instance = a->AllocateJSObjectFromMap(map.value());
542 a->Return(instance);
499 } 543 }
500 } 544 }
501 545
502 // Actually allocate the object. 546 a->Bind(&call_runtime);
503 Handle<JSObject> object = isolate->factory()->NewJSObjectFromMap(map); 547 {
504 548 a->Return(
505 // Define the properties if properties was specified and is not undefined. 549 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 } 550 }
511
512 return *object;
513 } 551 }
514 552
515 // ES6 section 19.1.2.3 Object.defineProperties 553 // ES6 section 19.1.2.3 Object.defineProperties
516 BUILTIN(ObjectDefineProperties) { 554 BUILTIN(ObjectDefineProperties) {
517 HandleScope scope(isolate); 555 HandleScope scope(isolate);
518 DCHECK_EQ(3, args.length()); 556 DCHECK_EQ(3, args.length());
519 Handle<Object> target = args.at<Object>(1); 557 Handle<Object> target = args.at<Object>(1);
520 Handle<Object> properties = args.at<Object>(2); 558 Handle<Object> properties = args.at<Object>(2);
521 559
522 RETURN_RESULT_OR_FAILURE( 560 RETURN_RESULT_OR_FAILURE(
(...skipping 490 matching lines...) Expand 10 before | Expand all | Expand 10 after
1013 typedef CompareDescriptor Descriptor; 1051 typedef CompareDescriptor Descriptor;
1014 Node* object = assembler->Parameter(Descriptor::kLeft); 1052 Node* object = assembler->Parameter(Descriptor::kLeft);
1015 Node* callable = assembler->Parameter(Descriptor::kRight); 1053 Node* callable = assembler->Parameter(Descriptor::kRight);
1016 Node* context = assembler->Parameter(Descriptor::kContext); 1054 Node* context = assembler->Parameter(Descriptor::kContext);
1017 1055
1018 assembler->Return(assembler->InstanceOf(object, callable, context)); 1056 assembler->Return(assembler->InstanceOf(object, callable, context));
1019 } 1057 }
1020 1058
1021 } // namespace internal 1059 } // namespace internal
1022 } // namespace v8 1060 } // namespace v8
OLDNEW
« no previous file with comments | « src/builtins/builtins.h ('k') | src/code-stub-assembler.h » ('j') | src/code-stub-assembler.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698