Allow FastCloneShallowObjectStub to use AllocationMementos.
authormvstanton@chromium.org <mvstanton@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 11 Oct 2013 09:25:14 +0000 (09:25 +0000)
committermvstanton@chromium.org <mvstanton@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 11 Oct 2013 09:25:14 +0000 (09:25 +0000)
(currently turned off)

BUG=
R=mstarzinger@chromium.org

Review URL: https://codereview.chromium.org/26827002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@17154 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/code-stubs-hydrogen.cc
src/flag-definitions.h
src/hydrogen.cc
src/runtime.cc

index dcf9e5b..c6fcac7 100644 (file)
@@ -436,22 +436,30 @@ template <>
 HValue* CodeStubGraphBuilder<FastCloneShallowObjectStub>::BuildCodeStub() {
   HValue* undefined = graph()->GetConstantUndefined();
 
-  HInstruction* boilerplate = Add<HLoadKeyed>(GetParameter(0),
-                                              GetParameter(1),
-                                              static_cast<HValue*>(NULL),
-                                              FAST_ELEMENTS);
+  HInstruction* allocation_site = Add<HLoadKeyed>(GetParameter(0),
+                                                  GetParameter(1),
+                                                  static_cast<HValue*>(NULL),
+                                                  FAST_ELEMENTS);
 
   IfBuilder checker(this);
-  checker.IfNot<HCompareObjectEqAndBranch, HValue*>(boilerplate,
+  checker.IfNot<HCompareObjectEqAndBranch, HValue*>(allocation_site,
                                                     undefined);
   checker.And();
 
+  HObjectAccess access = HObjectAccess::ForAllocationSiteTransitionInfo();
+  HInstruction* boilerplate = Add<HLoadNamedField>(allocation_site, access);
+
   int size = JSObject::kHeaderSize + casted_stub()->length() * kPointerSize;
+  int object_size = size;
+  if (FLAG_allocation_site_pretenuring) {
+    size += AllocationMemento::kSize;
+  }
+
   HValue* boilerplate_map = Add<HLoadNamedField>(
       boilerplate, HObjectAccess::ForMap());
   HValue* boilerplate_size = Add<HLoadNamedField>(
       boilerplate_map, HObjectAccess::ForMapInstanceSize());
-  HValue* size_in_words = Add<HConstant>(size >> kPointerSizeLog2);
+  HValue* size_in_words = Add<HConstant>(object_size >> kPointerSizeLog2);
   checker.If<HCompareNumericAndBranch>(boilerplate_size,
                                        size_in_words, Token::EQ);
   checker.Then();
@@ -461,12 +469,17 @@ HValue* CodeStubGraphBuilder<FastCloneShallowObjectStub>::BuildCodeStub() {
   HInstruction* object = Add<HAllocate>(size_in_bytes, HType::JSObject(),
       isolate()->heap()->GetPretenureMode(), JS_OBJECT_TYPE);
 
-  for (int i = 0; i < size; i += kPointerSize) {
+  for (int i = 0; i < object_size; i += kPointerSize) {
     HObjectAccess access = HObjectAccess::ForJSObjectOffset(i);
     Add<HStoreNamedField>(object, access,
                           Add<HLoadNamedField>(boilerplate, access));
   }
 
+  ASSERT(FLAG_allocation_site_pretenuring || (size == object_size));
+  if (FLAG_allocation_site_pretenuring) {
+    BuildCreateAllocationMemento(object, object_size, allocation_site);
+  }
+
   environment()->Push(object);
   checker.ElseDeopt("Uninitialized boilerplate in fast clone");
   checker.End();
index 5b6814e..7450ef9 100644 (file)
@@ -207,6 +207,8 @@ DEFINE_bool(pretenuring, true, "allocate objects in old space")
 // TODO(hpayer): We will remove this flag as soon as we have pretenuring
 // support for specific allocation sites.
 DEFINE_bool(pretenuring_call_new, false, "pretenure call new")
+DEFINE_bool(allocation_site_pretenuring, false,
+            "pretenure with allocation sites")
 DEFINE_bool(track_fields, true, "track fields with only smi values")
 DEFINE_bool(track_double_fields, true, "track fields with double values")
 DEFINE_bool(track_heap_object_fields, true, "track fields with heap values")
index 45fbbc0..db8de3f 100644 (file)
@@ -4335,15 +4335,20 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
 
   // Check whether to use fast or slow deep-copying for boilerplate.
   int max_properties = kMaxFastLiteralProperties;
-  Handle<Object> boilerplate(closure->literals()->get(
-      expr->literal_index()), isolate());
-  if (boilerplate->IsJSObject() &&
-      IsFastLiteral(Handle<JSObject>::cast(boilerplate),
-                    kMaxFastLiteralDepth,
-                    &max_properties)) {
-    Handle<JSObject> boilerplate_object = Handle<JSObject>::cast(boilerplate);
+  Handle<Object> literals_cell(closure->literals()->get(expr->literal_index()),
+                               isolate());
+  Handle<AllocationSite> site;
+  Handle<JSObject> boilerplate;
+  if (!literals_cell->IsUndefined()) {
+    // Retrieve the boilerplate
+    site = Handle<AllocationSite>::cast(literals_cell);
+    boilerplate = Handle<JSObject>(JSObject::cast(site->transition_info()),
+                                   isolate());
+  }
 
-    literal = BuildFastLiteral(boilerplate_object);
+  if (!boilerplate.is_null() &&
+      IsFastLiteral(boilerplate, kMaxFastLiteralDepth, &max_properties)) {
+    literal = BuildFastLiteral(boilerplate);
   } else {
     NoObservableSideEffectsScope no_effects(this);
     Handle<FixedArray> closure_literals(closure->literals(), isolate());
index 4ad9d61..77014b1 100644 (file)
@@ -486,16 +486,24 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateObjectLiteral) {
   bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0;
 
   // Check if boilerplate exists. If not, create it first.
-  Handle<Object> boilerplate(literals->get(literals_index), isolate);
-  if (*boilerplate == isolate->heap()->undefined_value()) {
+  Handle<Object> literal_site(literals->get(literals_index), isolate);
+  Handle<AllocationSite> site;
+  Handle<Object> boilerplate;
+  if (*literal_site == isolate->heap()->undefined_value()) {
     boilerplate = CreateObjectLiteralBoilerplate(isolate,
                                                  literals,
                                                  constant_properties,
                                                  should_have_fast_elements,
                                                  has_function_literal);
     RETURN_IF_EMPTY_HANDLE(isolate, boilerplate);
+    site = isolate->factory()->NewAllocationSite();
+    site->set_transition_info(*boilerplate);
+
     // Update the functions literal and return the boilerplate.
-    literals->set(literals_index, *boilerplate);
+    literals->set(literals_index, *site);
+  } else {
+    site = Handle<AllocationSite>::cast(literal_site);
+    boilerplate = Handle<JSObject>(JSObject::cast(site->transition_info()));
   }
 
   Handle<Object> copy = JSObject::DeepCopy(Handle<JSObject>::cast(boilerplate));