Revision: 6112
Author: [email protected]
Date: Wed Dec 22 07:43:32 2010
Log: Support load function prototype in hydrogen/lithium.

Review URL: http://codereview.chromium.org/6009005
http://code.google.com/p/v8/source/detail?r=6112

Modified:
 /branches/bleeding_edge/src/arm/lithium-arm.cc
 /branches/bleeding_edge/src/arm/lithium-arm.h
 /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
 /branches/bleeding_edge/src/ast.cc
 /branches/bleeding_edge/src/ast.h
 /branches/bleeding_edge/src/hydrogen-instructions.h
 /branches/bleeding_edge/src/hydrogen.cc
 /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc
 /branches/bleeding_edge/src/ia32/lithium-ia32.cc
 /branches/bleeding_edge/src/ia32/lithium-ia32.h

=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.cc      Tue Dec 21 02:52:50 2010
+++ /branches/bleeding_edge/src/arm/lithium-arm.cc      Wed Dec 22 07:43:32 2010
@@ -1852,6 +1852,14 @@
   LInstruction* result = DefineFixed(new LLoadNamedGeneric(object), r0);
   return MarkAsCall(result, instr);
 }
+
+
+LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
+    HLoadFunctionPrototype* instr) {
+  return AssignEnvironment(DefineAsRegister(
+      new LLoadFunctionPrototype(UseRegister(instr->function()),
+                                 TempRegister())));
+}


 LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) {
=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.h       Wed Dec 15 04:32:19 2010
+++ /branches/bleeding_edge/src/arm/lithium-arm.h       Wed Dec 22 07:43:32 2010
@@ -127,6 +127,7 @@
 //     LIsSmiAndBranch
 //     LLoadNamedField
 //     LLoadNamedGeneric
+//     LLoadFunctionPrototype
 //     LNumberTagD
 //     LNumberTagI
 //     LPushArgument
@@ -223,6 +224,7 @@
   V(LoadKeyedGeneric)                           \
   V(LoadNamedField)                             \
   V(LoadNamedGeneric)                           \
+  V(LoadFunctionPrototype)                      \
   V(ModI)                                       \
   V(MulI)                                       \
   V(NumberTagD)                                 \
@@ -1256,6 +1258,22 @@
 };


+class LLoadFunctionPrototype: public LUnaryOperation {
+ public:
+  LLoadFunctionPrototype(LOperand* function, LOperand* temporary)
+      : LUnaryOperation(function), temporary_(temporary) { }
+
+ DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load-function-prototype")
+  DECLARE_HYDROGEN_ACCESSOR(LoadFunctionPrototype)
+
+  LOperand* function() const { return input(); }
+  LOperand* temporary() const { return temporary_; }
+
+ private:
+  LOperand* temporary_;
+};
+
+
 class LLoadElements: public LUnaryOperation {
  public:
   explicit LLoadElements(LOperand* obj) : LUnaryOperation(obj) { }
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Tue Dec 21 02:52:50 2010 +++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Wed Dec 22 07:43:32 2010
@@ -1445,6 +1445,50 @@
   Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
+
+
+void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
+  Register function = ToRegister(instr->function());
+  Register temp = ToRegister(instr->temporary());
+  Register result = ToRegister(instr->result());
+
+  // Check that the function really is a function. Load map into the
+  // result register.
+  __ CompareObjectType(function, result, temp, JS_FUNCTION_TYPE);
+  DeoptimizeIf(ne, instr->environment());
+
+  // Make sure that the function has an instance prototype.
+  Label non_instance;
+  __ ldrb(temp, FieldMemOperand(result, Map::kBitFieldOffset));
+  __ tst(temp, Operand(1 << Map::kHasNonInstancePrototype));
+  __ b(ne, &non_instance);
+
+  // Get the prototype or initial map from the function.
+  __ ldr(result,
+ FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
+
+  // Check that the function has a prototype or an initial map.
+  __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
+  __ cmp(result, ip);
+  DeoptimizeIf(eq, instr->environment());
+
+  // If the function does not have an initial map, we're done.
+  Label done;
+  __ CompareObjectType(result, temp, temp, MAP_TYPE);
+  __ b(ne, &done);
+
+  // Get the prototype from the initial map.
+  __ ldr(result, FieldMemOperand(result, Map::kPrototypeOffset));
+  __ jmp(&done);
+
+  // Non-instance prototype: Fetch prototype from constructor field
+  // in initial map.
+  __ bind(&non_instance);
+  __ ldr(result, FieldMemOperand(result, Map::kConstructorOffset));
+
+  // All done.
+  __ bind(&done);
+}


 void LCodeGen::DoLoadElements(LLoadElements* instr) {
=======================================
--- /branches/bleeding_edge/src/ast.cc  Tue Dec 14 10:53:48 2010
+++ /branches/bleeding_edge/src/ast.cc  Wed Dec 22 07:43:32 2010
@@ -517,6 +517,9 @@
   if (key()->IsPropertyName()) {
     if (oracle->LoadIsBuiltin(this, Builtins::LoadIC_ArrayLength)) {
       is_array_length_ = true;
+    } else if (oracle->LoadIsBuiltin(this,
+                                     Builtins::LoadIC_FunctionPrototype)) {
+      is_function_prototype_ = true;
     } else {
       Literal* lit_key = key()->AsLiteral();
       ASSERT(lit_key != NULL && lit_key->handle()->IsString());
=======================================
--- /branches/bleeding_edge/src/ast.h   Wed Dec 22 01:49:26 2010
+++ /branches/bleeding_edge/src/ast.h   Wed Dec 22 07:43:32 2010
@@ -1208,6 +1208,7 @@
         is_monomorphic_(false),
         receiver_types_(NULL),
         is_array_length_(false),
+        is_function_prototype_(false),
         is_arguments_access_(false) { }

   DECLARE_NODE_TYPE(Property)
@@ -1219,6 +1220,8 @@
   Expression* key() const { return key_; }
   int position() const { return pos_; }
   bool is_synthetic() const { return type_ == SYNTHETIC; }
+
+  bool IsFunctionPrototype() const { return is_function_prototype_; }

   // Marks that this is actually an argument rewritten to a keyed property
   // accessing the argument through the arguments shadow object.
@@ -1249,6 +1252,7 @@
   bool is_monomorphic_;
   ZoneMapList* receiver_types_;
   bool is_array_length_;
+  bool is_function_prototype_;
   bool is_arguments_access_;
   Handle<Map> monomorphic_receiver_type_;

=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.h Mon Dec 20 05:52:14 2010 +++ /branches/bleeding_edge/src/hydrogen-instructions.h Wed Dec 22 07:43:32 2010
@@ -76,7 +76,6 @@
 //       HLoadKeyed
 //         HLoadKeyedFastElement
 //         HLoadKeyedGeneric
-//       HLoadNamedGeneric
 //       HPower
 //       HStoreNamed
 //         HStoreNamedField
@@ -132,6 +131,8 @@
 //       HLoadElements
 //         HTypeofIs
 //       HLoadNamedField
+//       HLoadNamedGeneric
+//       HLoadFunctionPrototype
 //       HPushArgument
 //       HTypeof
 //       HUnaryMathOperation
@@ -221,6 +222,7 @@
   V(LoadKeyedGeneric)                          \
   V(LoadNamedField)                            \
   V(LoadNamedGeneric)                          \
+  V(LoadFunctionPrototype)                     \
   V(Mod)                                       \
   V(Mul)                                       \
   V(ObjectLiteral)                             \
@@ -256,6 +258,7 @@
   V(GlobalVars)                                \
   V(Maps)                                      \
   V(ArrayLengths)                              \
+  V(FunctionPrototypes)                        \
   V(OsrEntries)

 #define DECLARE_INSTRUCTION(type)                   \
@@ -2617,6 +2620,27 @@
 };


+class HLoadFunctionPrototype: public HUnaryOperation {
+ public:
+  explicit HLoadFunctionPrototype(HValue* function)
+      : HUnaryOperation(function) {
+    set_representation(Representation::Tagged());
+    SetFlagMask(kDependsOnFunctionPrototypes);
+  }
+
+  HValue* function() const { return OperandAt(0); }
+
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::Tagged();
+  }
+
+ DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load_function_prototype")
+
+ protected:
+  virtual bool DataEquals(HValue* other) const { return true; }
+};
+
+
 class HLoadKeyed: public HBinaryOperation {
  public:
   HLoadKeyed(HValue* obj, HValue* key) : HBinaryOperation(obj, key) {
=======================================
--- /branches/bleeding_edge/src/hydrogen.cc     Tue Dec 21 03:21:04 2010
+++ /branches/bleeding_edge/src/hydrogen.cc     Wed Dec 22 07:43:32 2010
@@ -3722,6 +3722,11 @@
     AddInstruction(new HCheckNonSmi(array));
     instr = new HArrayLength(array);

+  } else if (expr->IsFunctionPrototype()) {
+    HValue* function = Pop();
+    AddInstruction(new HCheckNonSmi(function));
+    instr = new HLoadFunctionPrototype(function);
+
   } else if (expr->key()->IsPropertyName()) {
     Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
     ZoneMapList* types = expr->GetReceiverTypes();
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Wed Dec 22 01:55:19 2010 +++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Wed Dec 22 07:43:32 2010
@@ -1835,6 +1835,48 @@
   Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
+
+
+void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
+  Register function = ToRegister(instr->function());
+  Register temp = ToRegister(instr->temporary());
+  Register result = ToRegister(instr->result());
+
+  // Check that the function really is a function.
+  __ CmpObjectType(function, JS_FUNCTION_TYPE, result);
+  DeoptimizeIf(not_equal, instr->environment());
+
+  // Check whether the function has an instance prototype.
+  NearLabel non_instance;
+  __ test_b(FieldOperand(result, Map::kBitFieldOffset),
+            1 << Map::kHasNonInstancePrototype);
+  __ j(not_zero, &non_instance);
+
+  // Get the prototype or initial map from the function.
+  __ mov(result,
+         FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
+
+  // Check that the function has a prototype or an initial map.
+  __ cmp(Operand(result), Immediate(Factory::the_hole_value()));
+  DeoptimizeIf(equal, instr->environment());
+
+  // If the function does not have an initial map, we're done.
+  NearLabel done;
+  __ CmpObjectType(result, MAP_TYPE, temp);
+  __ j(not_equal, &done);
+
+  // Get the prototype from the initial map.
+  __ mov(result, FieldOperand(result, Map::kPrototypeOffset));
+  __ jmp(&done);
+
+  // Non-instance prototype: Fetch prototype from constructor field
+  // in the function's map.
+  __ bind(&non_instance);
+  __ mov(result, FieldOperand(result, Map::kConstructorOffset));
+
+  // All done.
+  __ bind(&done);
+}


 void LCodeGen::DoLoadElements(LLoadElements* instr) {
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.cc Mon Dec 20 05:52:14 2010 +++ /branches/bleeding_edge/src/ia32/lithium-ia32.cc Wed Dec 22 07:43:32 2010
@@ -1858,6 +1858,14 @@
   LInstruction* result = DefineFixed(new LLoadNamedGeneric(object), eax);
   return MarkAsCall(result, instr);
 }
+
+
+LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
+    HLoadFunctionPrototype* instr) {
+  return AssignEnvironment(DefineAsRegister(
+      new LLoadFunctionPrototype(UseRegister(instr->function()),
+                                 TempRegister())));
+}


 LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) {
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.h     Wed Dec 15 04:32:19 2010
+++ /branches/bleeding_edge/src/ia32/lithium-ia32.h     Wed Dec 22 07:43:32 2010
@@ -130,6 +130,7 @@
 //     LIsSmiAndBranch
 //     LLoadNamedField
 //     LLoadNamedGeneric
+//     LLoadFunctionPrototype
 //     LNumberTagD
 //     LNumberTagI
 //     LPushArgument
@@ -226,6 +227,7 @@
   V(LoadKeyedGeneric)                           \
   V(LoadNamedField)                             \
   V(LoadNamedGeneric)                           \
+  V(LoadFunctionPrototype)                      \
   V(ModI)                                       \
   V(MulI)                                       \
   V(NumberTagD)                                 \
@@ -1271,6 +1273,22 @@
 };


+class LLoadFunctionPrototype: public LUnaryOperation {
+ public:
+  LLoadFunctionPrototype(LOperand* function, LOperand* temporary)
+      : LUnaryOperation(function), temporary_(temporary) { }
+
+ DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load-function-prototype")
+  DECLARE_HYDROGEN_ACCESSOR(LoadFunctionPrototype)
+
+  LOperand* function() const { return input(); }
+  LOperand* temporary() const { return temporary_; }
+
+ private:
+  LOperand* temporary_;
+};
+
+
 class LLoadElements: public LUnaryOperation {
  public:
   explicit LLoadElements(LOperand* obj) : LUnaryOperation(obj) { }

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to