Simplify CheckPrototypeMaps.

This instruction only depends on the prototype and the holder and can
completely ignore the receiver and its map.

This change also fixes a small bug on arm where a cell was loaded
instead of the prototype from new space.

Review URL: http://codereview.chromium.org/6094020

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6290 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
vitalyr@chromium.org 2011-01-13 00:34:08 +00:00
parent ad58227fcf
commit 9e204dd5df
6 changed files with 26 additions and 28 deletions

View File

@ -76,6 +76,7 @@ class LCodeGen;
// LCallNamed
// LCallRuntime
// LCallStub
// LCheckPrototypeMaps
// LConstant
// LConstantD
// LConstantI
@ -109,7 +110,6 @@ class LCodeGen;
// LCheckFunction
// LCheckInstanceType
// LCheckMap
// LCheckPrototypeMaps
// LCheckSmi
// LClassOfTest
// LClassOfTestAndBranch
@ -1596,8 +1596,9 @@ class LCheckPrototypeMaps: public LInstruction {
DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps, "check-prototype-maps")
DECLARE_HYDROGEN_ACCESSOR(CheckPrototypeMaps)
Handle<JSObject> prototype() const { return hydrogen()->prototype(); }
Handle<JSObject> holder() const { return hydrogen()->holder(); }
Handle<Map> receiver_map() const { return hydrogen()->receiver_map(); }
LOperand* temp1() const { return temp1_; }
LOperand* temp2() const { return temp2_; }

View File

@ -2510,6 +2510,7 @@ void LCodeGen::LoadPrototype(Register result,
Handle<JSGlobalPropertyCell> cell =
Factory::NewJSGlobalPropertyCell(prototype);
__ mov(result, Operand(cell));
__ ldr(result, FieldMemOperand(result, JSGlobalPropertyCell::kValueOffset));
} else {
__ mov(result, Operand(prototype));
}
@ -2521,8 +2522,7 @@ void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) {
Register temp2 = ToRegister(instr->temp2());
Handle<JSObject> holder = instr->holder();
Handle<Map> receiver_map = instr->receiver_map();
Handle<JSObject> current_prototype(JSObject::cast(receiver_map->prototype()));
Handle<JSObject> current_prototype = instr->prototype();
// Load prototype object.
LoadPrototype(temp1, current_prototype);

View File

@ -92,6 +92,7 @@ class LChunkBuilder;
// HCallNew
// HCallRuntime
// HCallStub
// HCheckPrototypeMaps
// HConstant
// HControlInstruction
// HDeoptimize
@ -125,7 +126,6 @@ class LChunkBuilder;
// HCheckInstanceType
// HCheckMap
// HCheckNonSmi
// HCheckPrototypeMaps
// HCheckSmi
// HDeleteProperty
// HFixedArrayLength
@ -1622,42 +1622,40 @@ class HCheckNonSmi: public HUnaryOperation {
};
class HCheckPrototypeMaps: public HUnaryOperation {
class HCheckPrototypeMaps: public HInstruction {
public:
HCheckPrototypeMaps(HValue* value,
Handle<JSObject> holder,
Handle<Map> receiver_map)
: HUnaryOperation(value),
holder_(holder),
receiver_map_(receiver_map) {
set_representation(Representation::Tagged());
HCheckPrototypeMaps(Handle<JSObject> prototype, Handle<JSObject> holder)
: prototype_(prototype), holder_(holder) {
SetFlag(kUseGVN);
SetFlag(kDependsOnMaps);
}
virtual Representation RequiredInputRepresentation(int index) const {
return Representation::Tagged();
}
#ifdef DEBUG
virtual void Verify() const;
#endif
Handle<JSObject> prototype() const { return prototype_; }
Handle<JSObject> holder() const { return holder_; }
Handle<Map> receiver_map() const { return receiver_map_; }
DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps, "check_prototype_maps")
virtual intptr_t Hashcode() const {
ASSERT(!Heap::IsAllocationAllowed());
intptr_t hash = reinterpret_cast<intptr_t>(*prototype());
hash = 17 * hash + reinterpret_cast<intptr_t>(*holder());
return hash;
}
protected:
virtual bool DataEquals(HValue* other) const {
HCheckPrototypeMaps* b = HCheckPrototypeMaps::cast(other);
return holder_.is_identical_to(b->holder()) &&
receiver_map_.is_identical_to(b->receiver_map());
return prototype_.is_identical_to(b->prototype()) &&
holder_.is_identical_to(b->holder());
}
private:
Handle<JSObject> prototype_;
Handle<JSObject> holder_;
Handle<Map> receiver_map_;
};

View File

@ -3795,9 +3795,9 @@ void HGraphBuilder::AddCheckConstantFunction(Call* expr,
AddInstruction(new HCheckMap(receiver, receiver_map));
}
if (!expr->holder().is_null()) {
AddInstruction(new HCheckPrototypeMaps(receiver,
expr->holder(),
receiver_map));
AddInstruction(new HCheckPrototypeMaps(
Handle<JSObject>(JSObject::cast(receiver_map->prototype())),
expr->holder()));
}
}

View File

@ -3155,8 +3155,7 @@ void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) {
Register reg = ToRegister(instr->temp());
Handle<JSObject> holder = instr->holder();
Handle<Map> receiver_map = instr->receiver_map();
Handle<JSObject> current_prototype(JSObject::cast(receiver_map->prototype()));
Handle<JSObject> current_prototype = instr->prototype();
// Load prototype object.
LoadPrototype(reg, current_prototype);

View File

@ -77,6 +77,7 @@ class LCodeGen;
// LCallNamed
// LCallRuntime
// LCallStub
// LCheckPrototypeMaps
// LConstant
// LConstantD
// LConstantI
@ -111,7 +112,6 @@ class LCodeGen;
// LCheckFunction
// LCheckInstanceType
// LCheckMap
// LCheckPrototypeMaps
// LCheckSmi
// LClassOfTest
// LClassOfTestAndBranch
@ -1680,8 +1680,8 @@ class LCheckPrototypeMaps: public LTemplateInstruction<0, 0, 0> {
DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps, "check-prototype-maps")
DECLARE_HYDROGEN_ACCESSOR(CheckPrototypeMaps)
Handle<JSObject> prototype() const { return hydrogen()->prototype(); }
Handle<JSObject> holder() const { return hydrogen()->holder(); }
Handle<Map> receiver_map() const { return hydrogen()->receiver_map(); }
LOperand* temp() const { return temp_; }