Implement non-generic stores for object literals.
authormstarzinger@chromium.org <mstarzinger@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 13 Mar 2012 12:11:46 +0000 (12:11 +0000)
committermstarzinger@chromium.org <mstarzinger@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 13 Mar 2012 12:11:46 +0000 (12:11 +0000)
This uses the type feedback already present for computed value stores
into object literals to generate optimized stores in Crankshaft, thus
avoiding unnecessary generic stores with side effects.

R=svenpanne@chromium.org

Review URL: https://chromiumcodereview.appspot.com/9692036

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

src/ast.cc
src/ast.h
src/hydrogen.cc
src/hydrogen.h
src/type-info.cc
src/type-info.h

index 239e5d0ffe4475a2e885962a9a36832de23a8f54..011ce651cd0566e30ceb9a1626b88f3642ba8347 100644 (file)
@@ -602,6 +602,13 @@ void CompareOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
 }
 
 
+void ObjectLiteral::Property::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
+  receiver_type_ = oracle->ObjectLiteralStoreIsMonomorphic(this)
+      ? oracle->GetObjectLiteralStoreMap(this)
+      : Handle<Map>::null();
+}
+
+
 // ----------------------------------------------------------------------------
 // Implementation of AstVisitor
 
index 09864885e93e486b323b5d07bdc607a0256aae5a..65b984ebfcc96de8408e81a3226679065ce978eb 100644 (file)
--- a/src/ast.h
+++ b/src/ast.h
@@ -1320,6 +1320,11 @@ class ObjectLiteral: public MaterializedLiteral {
     Expression* value() { return value_; }
     Kind kind() { return kind_; }
 
+    // Type feedback information.
+    void RecordTypeFeedback(TypeFeedbackOracle* oracle);
+    bool IsMonomorphic() { return !receiver_type_.is_null(); }
+    Handle<Map> GetReceiverType() { return receiver_type_; }
+
     bool IsCompileTimeValue();
 
     void set_emit_store(bool emit_store);
@@ -1336,6 +1341,7 @@ class ObjectLiteral: public MaterializedLiteral {
     Expression* value_;
     Kind kind_;
     bool emit_store_;
+    Handle<Map> receiver_type_;
   };
 
   DECLARE_NODE_TYPE(ObjectLiteral)
index 6a7b6098cb8537d747f2ce674e41e56fdd0f0c7c..943d50511b8b5948eaa76ded3a46431011ae822b 100644 (file)
@@ -3738,18 +3738,13 @@ void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
       case ObjectLiteral::Property::COMPUTED:
         if (key->handle()->IsSymbol()) {
           if (property->emit_store()) {
+            property->RecordTypeFeedback(oracle());
             CHECK_ALIVE(VisitForValue(value));
             HValue* value = Pop();
             Handle<String> name = Handle<String>::cast(key->handle());
-            HStoreNamedGeneric* store =
-                new(zone()) HStoreNamedGeneric(
-                                context,
-                                literal,
-                                name,
-                                value,
-                                function_strict_mode_flag());
+            HInstruction* store = BuildStoreNamed(literal, value, property);
             AddInstruction(store);
-            AddSimulate(key->id());
+            if (store->HasObservableSideEffects()) AddSimulate(key->id());
           } else {
             CHECK_ALIVE(VisitForEffect(value));
           }
@@ -3952,6 +3947,25 @@ HInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object,
 }
 
 
+HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object,
+                                             HValue* value,
+                                             ObjectLiteral::Property* prop) {
+  Literal* key = prop->key()->AsLiteral();
+  Handle<String> name = Handle<String>::cast(key->handle());
+  ASSERT(!name.is_null());
+
+  LookupResult lookup(isolate());
+  Handle<Map> type = prop->GetReceiverType();
+  bool is_monomorphic = prop->IsMonomorphic() &&
+      ComputeStoredField(type, name, &lookup);
+
+  return is_monomorphic
+      ? BuildStoreNamedField(object, name, value, type, &lookup,
+                             true)  // Needs smi and map check.
+      : BuildStoreNamedGeneric(object, name, value);
+}
+
+
 HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object,
                                              HValue* value,
                                              Expression* expr) {
index b0d67ebb66c61f1aa8b790ddd392bd23edb5430c..cb39609f3d9e0d86fa0a489387503670c406b16d 100644 (file)
@@ -1077,6 +1077,9 @@ class HGraphBuilder: public AstVisitor {
   HInstruction* BuildStoreNamed(HValue* object,
                                 HValue* value,
                                 Expression* expr);
+  HInstruction* BuildStoreNamed(HValue* object,
+                                HValue* value,
+                                ObjectLiteral::Property* prop);
   HInstruction* BuildStoreNamedField(HValue* object,
                                      Handle<String> name,
                                      HValue* value,
index fa479b2e515b5c811b30c67bae9ce4c3fd4c9e09..926043719d97bf1ee2557a498e306add317c8597 100644 (file)
@@ -154,6 +154,13 @@ bool TypeFeedbackOracle::CallNewIsMonomorphic(CallNew* expr) {
 }
 
 
+bool TypeFeedbackOracle::ObjectLiteralStoreIsMonomorphic(
+    ObjectLiteral::Property* prop) {
+  Handle<Object> map_or_code = GetInfo(prop->key()->id());
+  return map_or_code->IsMap();
+}
+
+
 bool TypeFeedbackOracle::IsForInFastCase(ForInStatement* stmt) {
   Handle<Object> value = GetInfo(stmt->PrepareId());
   return value->IsSmi() &&
@@ -268,6 +275,13 @@ Handle<JSFunction> TypeFeedbackOracle::GetCallNewTarget(CallNew* expr) {
 }
 
 
+Handle<Map> TypeFeedbackOracle::GetObjectLiteralStoreMap(
+    ObjectLiteral::Property* prop) {
+  ASSERT(ObjectLiteralStoreIsMonomorphic(prop));
+  return Handle<Map>::cast(GetInfo(prop->key()->id()));
+}
+
+
 bool TypeFeedbackOracle::LoadIsBuiltin(Property* expr, Builtins::Name id) {
   return *GetInfo(expr->id()) ==
       isolate_->builtins()->builtin(id);
index 84ec51d97567dc4b7ec6665913985546d9711e0d..2e2ce10f960f7f9007b47d65ca1d86db51da519d 100644 (file)
@@ -29,6 +29,7 @@
 #define V8_TYPE_INFO_H_
 
 #include "allocation.h"
+#include "ast.h"
 #include "globals.h"
 #include "zone-inl.h"
 
@@ -243,6 +244,7 @@ class TypeFeedbackOracle BASE_EMBEDDED {
   bool StoreIsMegamorphicWithTypeInfo(Expression* expr);
   bool CallIsMonomorphic(Call* expr);
   bool CallNewIsMonomorphic(CallNew* expr);
+  bool ObjectLiteralStoreIsMonomorphic(ObjectLiteral::Property* prop);
 
   bool IsForInFastCase(ForInStatement* expr);
 
@@ -272,6 +274,8 @@ class TypeFeedbackOracle BASE_EMBEDDED {
   Handle<JSFunction> GetCallTarget(Call* expr);
   Handle<JSFunction> GetCallNewTarget(CallNew* expr);
 
+  Handle<Map> GetObjectLiteralStoreMap(ObjectLiteral::Property* prop);
+
   bool LoadIsBuiltin(Property* expr, Builtins::Name id);
 
   // TODO(1571) We can't use ToBooleanStub::Types as the return value because