}
+LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
+ HLoadFunctionPrototype* instr) {
+ return AssignEnvironment(DefineAsRegister(
+ new LLoadFunctionPrototype(UseRegister(instr->function()),
+ TempRegister())));
+}
+
+
LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) {
LOperand* input = UseRegisterAtStart(instr->value());
return DefineSameAsFirst(new LLoadElements(input));
// LIsSmiAndBranch
// LLoadNamedField
// LLoadNamedGeneric
+// LLoadFunctionPrototype
// LNumberTagD
// LNumberTagI
// LPushArgument
V(LoadKeyedGeneric) \
V(LoadNamedField) \
V(LoadNamedGeneric) \
+ V(LoadFunctionPrototype) \
V(ModI) \
V(MulI) \
V(NumberTagD) \
};
+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) { }
}
+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) {
Abort("DoLoadElements unimplemented.");
}
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());
is_monomorphic_(false),
receiver_types_(NULL),
is_array_length_(false),
+ is_function_prototype_(false),
is_arguments_access_(false) { }
DECLARE_NODE_TYPE(Property)
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.
void set_is_arguments_access(bool is_arguments_access) {
bool is_monomorphic_;
ZoneMapList* receiver_types_;
bool is_array_length_;
+ bool is_function_prototype_;
bool is_arguments_access_;
Handle<Map> monomorphic_receiver_type_;
// HLoadKeyed
// HLoadKeyedFastElement
// HLoadKeyedGeneric
-// HLoadNamedGeneric
// HPower
// HStoreNamed
// HStoreNamedField
// HLoadElements
// HTypeofIs
// HLoadNamedField
+// HLoadNamedGeneric
+// HLoadFunctionPrototype
// HPushArgument
// HTypeof
// HUnaryMathOperation
V(LoadKeyedGeneric) \
V(LoadNamedField) \
V(LoadNamedGeneric) \
+ V(LoadFunctionPrototype) \
V(Mod) \
V(Mul) \
V(ObjectLiteral) \
V(GlobalVars) \
V(Maps) \
V(ArrayLengths) \
+ V(FunctionPrototypes) \
V(OsrEntries)
#define DECLARE_INSTRUCTION(type) \
};
+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) {
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();
}
+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) {
ASSERT(instr->result()->Equals(instr->input()));
Register reg = ToRegister(instr->input());
}
+LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
+ HLoadFunctionPrototype* instr) {
+ return AssignEnvironment(DefineAsRegister(
+ new LLoadFunctionPrototype(UseRegister(instr->function()),
+ TempRegister())));
+}
+
+
LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) {
LOperand* input = UseRegisterAtStart(instr->value());
return DefineSameAsFirst(new LLoadElements(input));
// LIsSmiAndBranch
// LLoadNamedField
// LLoadNamedGeneric
+// LLoadFunctionPrototype
// LNumberTagD
// LNumberTagI
// LPushArgument
V(LoadKeyedGeneric) \
V(LoadNamedField) \
V(LoadNamedGeneric) \
+ V(LoadFunctionPrototype) \
V(ModI) \
V(MulI) \
V(NumberTagD) \
};
+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) { }