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