Revision: 6615
Author: [email protected]
Date: Thu Feb 3 05:10:28 2011
Log: Introduce a hydrogen value for contexts, support context slot
assignment.
Each context in the context chain has a corresponding hydrogen value.
The context values are used for global object lookup and context slot
lookup. Add simple (non-compound) assignment to context slots.
Review URL: http://codereview.chromium.org/6390003
http://code.google.com/p/v8/source/detail?r=6615
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/hydrogen-instructions.cc
/branches/bleeding_edge/src/hydrogen-instructions.h
/branches/bleeding_edge/src/hydrogen.cc
/branches/bleeding_edge/src/hydrogen.h
/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/x64/lithium-x64.cc
/branches/bleeding_edge/src/x64/lithium-x64.h
=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.cc Wed Feb 2 05:55:29 2011
+++ /branches/bleeding_edge/src/arm/lithium-arm.cc Thu Feb 3 05:10:28 2011
@@ -258,7 +258,15 @@
void LLoadContextSlot::PrintDataTo(StringStream* stream) {
- stream->Add("(%d, %d)", context_chain_length(), slot_index());
+ InputAt(0)->PrintTo(stream);
+ stream->Add("[%d]", slot_index());
+}
+
+
+void LStoreContextSlot::PrintDataTo(StringStream* stream) {
+ InputAt(0)->PrintTo(stream);
+ stream->Add("[%d] <- ", slot_index());
+ InputAt(1)->PrintTo(stream);
}
@@ -1103,15 +1111,28 @@
LOperand* argument = Use(instr->argument());
return new LPushArgument(argument);
}
+
+
+LInstruction* LChunkBuilder::DoContext(HContext* instr) {
+ return DefineAsRegister(new LContext);
+}
+
+
+LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
+ LOperand* context = UseRegisterAtStart(instr->value());
+ return DefineAsRegister(new LOuterContext(context));
+}
LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
- return DefineAsRegister(new LGlobalObject);
+ LOperand* context = UseRegisterAtStart(instr->value());
+ return DefineAsRegister(new LGlobalObject(context));
}
LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) {
- return DefineAsRegister(new LGlobalReceiver);
+ LOperand* global_object = UseRegisterAtStart(instr->value());
+ return DefineAsRegister(new LGlobalReceiver(global_object));
}
@@ -1621,7 +1642,20 @@
LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
- return DefineAsRegister(new LLoadContextSlot);
+ LOperand* context = UseRegisterAtStart(instr->value());
+ return DefineAsRegister(new LLoadContextSlot(context));
+}
+
+
+LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
+ LOperand* context = UseTempRegister(instr->context());
+ LOperand* value;
+ if (instr->NeedsWriteBarrier()) {
+ value = UseTempRegister(instr->value());
+ } else {
+ value = UseRegister(instr->value());
+ }
+ return new LStoreContextSlot(context, value);
}
=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.h Wed Feb 2 05:55:29 2011
+++ /branches/bleeding_edge/src/arm/lithium-arm.h Thu Feb 3 05:10:28 2011
@@ -39,118 +39,6 @@
// Forward declarations.
class LCodeGen;
-
-// Type hierarchy:
-//
-// LInstruction
-// LTemplateInstruction
-// LControlInstruction
-// LBranch
-// LClassOfTestAndBranch
-// LCmpJSObjectEqAndBranch
-// LCmpIDAndBranch
-// LHasCachedArrayIndexAndBranch
-// LHasInstanceTypeAndBranch
-// LInstanceOfAndBranch
-// LIsNullAndBranch
-// LIsObjectAndBranch
-// LIsSmiAndBranch
-// LTypeofIsAndBranch
-// LAccessArgumentsAt
-// LArgumentsElements
-// LArgumentsLength
-// LAddI
-// LApplyArguments
-// LArithmeticD
-// LArithmeticT
-// LBitI
-// LBoundsCheck
-// LCmpID
-// LCmpJSObjectEq
-// LCmpT
-// LDivI
-// LInstanceOf
-// LInstanceOfKnownGlobal
-// LLoadKeyedFastElement
-// LLoadKeyedGeneric
-// LModI
-// LMulI
-// LPower
-// LShiftI
-// LSubI
-// LCallConstantFunction
-// LCallFunction
-// LCallGlobal
-// LCallKeyed
-// LCallKnownGlobal
-// LCallNamed
-// LCallRuntime
-// LCallStub
-// LConstant
-// LConstantD
-// LConstantI
-// LConstantT
-// LDeoptimize
-// LFunctionLiteral
-// LGap
-// LLabel
-// LGlobalObject
-// LGlobalReceiver
-// LGoto
-// LLazyBailout
-// LLoadGlobal
-// LCheckPrototypeMaps
-// LLoadContextSlot
-// LArrayLiteral
-// LObjectLiteral
-// LRegExpLiteral
-// LOsrEntry
-// LParameter
-// LRegExpConstructResult
-// LStackCheck
-// LStoreKeyed
-// LStoreKeyedFastElement
-// LStoreKeyedGeneric
-// LStoreNamed
-// LStoreNamedField
-// LStoreNamedGeneric
-// LStringCharCodeAt
-// LBitNotI
-// LCallNew
-// LCheckFunction
-// LCheckPrototypeMaps
-// LCheckInstanceType
-// LCheckMap
-// LCheckSmi
-// LClassOfTest
-// LDeleteProperty
-// LDoubleToI
-// LFixedArrayLength
-// LHasCachedArrayIndex
-// LHasInstanceType
-// LInteger32ToDouble
-// LIsNull
-// LIsObject
-// LIsSmi
-// LJSArrayLength
-// LLoadNamedField
-// LLoadNamedGeneric
-// LLoadFunctionPrototype
-// LNumberTagD
-// LNumberTagI
-// LPushArgument
-// LReturn
-// LSmiTag
-// LStoreGlobal
-// LStringLength
-// LTaggedToI
-// LThrow
-// LTypeof
-// LTypeofIs
-// LUnaryMathOperation
-// LValueOf
-// LUnknownOSRValue
-
#define LITHIUM_ALL_INSTRUCTION_LIST(V) \
V(ControlInstruction) \
V(Constant) \
@@ -187,6 +75,8 @@
V(CheckMap) \
V(CheckPrototypeMaps) \
V(CheckSmi) \
+ V(ClassOfTest) \
+ V(ClassOfTestAndBranch) \
V(CmpID) \
V(CmpIDAndBranch) \
V(CmpJSObjectEq) \
@@ -197,6 +87,7 @@
V(ConstantD) \
V(ConstantI) \
V(ConstantT) \
+ V(Context) \
V(DeleteProperty) \
V(Deoptimize) \
V(DivI) \
@@ -207,6 +98,10 @@
V(GlobalObject) \
V(GlobalReceiver) \
V(Goto) \
+ V(HasCachedArrayIndex) \
+ V(HasCachedArrayIndexAndBranch) \
+ V(HasInstanceType) \
+ V(HasInstanceTypeAndBranch) \
V(InstanceOf) \
V(InstanceOfAndBranch) \
V(InstanceOfKnownGlobal) \
@@ -218,22 +113,16 @@
V(IsSmi) \
V(IsSmiAndBranch) \
V(JSArrayLength) \
- V(HasInstanceType) \
- V(HasInstanceTypeAndBranch) \
- V(HasCachedArrayIndex) \
- V(HasCachedArrayIndexAndBranch) \
- V(ClassOfTest) \
- V(ClassOfTestAndBranch) \
V(Label) \
V(LazyBailout) \
V(LoadContextSlot) \
V(LoadElements) \
+ V(LoadFunctionPrototype) \
V(LoadGlobal) \
V(LoadKeyedFastElement) \
V(LoadKeyedGeneric) \
V(LoadNamedField) \
V(LoadNamedGeneric) \
- V(LoadFunctionPrototype) \
V(ModI) \
V(MulI) \
V(NumberTagD) \
@@ -241,6 +130,7 @@
V(NumberUntagD) \
V(ObjectLiteral) \
V(OsrEntry) \
+ V(OuterContext) \
V(Parameter) \
V(PushArgument) \
V(RegExpLiteral) \
@@ -249,14 +139,15 @@
V(SmiTag) \
V(SmiUntag) \
V(StackCheck) \
+ V(StoreContextSlot) \
V(StoreGlobal) \
V(StoreKeyedFastElement) \
V(StoreKeyedGeneric) \
V(StoreNamedField) \
V(StoreNamedGeneric) \
- V(SubI) \
V(StringCharCodeAt) \
V(StringLength) \
+ V(SubI) \
V(TaggedToI) \
V(Throw) \
V(Typeof) \
@@ -1266,13 +1157,36 @@
};
-class LLoadContextSlot: public LTemplateInstruction<1, 0, 0> {
+class LLoadContextSlot: public LTemplateInstruction<1, 1, 0> {
public:
+ explicit LLoadContextSlot(LOperand* context) {
+ inputs_[0] = context;
+ }
+
DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot, "load-context-slot")
DECLARE_HYDROGEN_ACCESSOR(LoadContextSlot)
- int context_chain_length() { return hydrogen()->context_chain_length(); }
+ LOperand* context() { return InputAt(0); }
int slot_index() { return hydrogen()->slot_index(); }
+
+ virtual void PrintDataTo(StringStream* stream);
+};
+
+
+class LStoreContextSlot: public LTemplateInstruction<0, 2, 0> {
+ public:
+ LStoreContextSlot(LOperand* context, LOperand* value) {
+ inputs_[0] = context;
+ inputs_[1] = value;
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot, "store-context-slot")
+ DECLARE_HYDROGEN_ACCESSOR(StoreContextSlot)
+
+ LOperand* context() { return InputAt(0); }
+ LOperand* value() { return InputAt(1); }
+ int slot_index() { return hydrogen()->slot_index(); }
+ int needs_write_barrier() { return hydrogen()->NeedsWriteBarrier(); }
virtual void PrintDataTo(StringStream* stream);
};
@@ -1288,15 +1202,45 @@
};
-class LGlobalObject: public LTemplateInstruction<1, 0, 0> {
+class LContext: public LTemplateInstruction<1, 0, 0> {
public:
+ DECLARE_CONCRETE_INSTRUCTION(Context, "context")
+};
+
+
+class LOuterContext: public LTemplateInstruction<1, 1, 0> {
+ public:
+ explicit LOuterContext(LOperand* context) {
+ inputs_[0] = context;
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(OuterContext, "outer-context")
+
+ LOperand* context() { return InputAt(0); }
+};
+
+
+class LGlobalObject: public LTemplateInstruction<1, 1, 0> {
+ public:
+ explicit LGlobalObject(LOperand* context) {
+ inputs_[0] = context;
+ }
+
DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global-object")
+
+ LOperand* context() { return InputAt(0); }
};
-class LGlobalReceiver: public LTemplateInstruction<1, 0, 0> {
+class LGlobalReceiver: public LTemplateInstruction<1, 1, 0> {
public:
+ explicit LGlobalReceiver(LOperand* global_object) {
+ inputs_[0] = global_object;
+ }
+
DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver, "global-receiver")
+
+ LOperand* global() { return InputAt(0); }
};
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Thu Feb 3
02:07:22 2011
+++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Thu Feb 3
05:10:28 2011
@@ -2212,11 +2212,25 @@
void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
- // TODO(antonm): load a context with a separate instruction.
+ Register context = ToRegister(instr->context());
Register result = ToRegister(instr->result());
- __ LoadContext(result, instr->context_chain_length());
+ __ ldr(result,
+ MemOperand(context,
Context::SlotOffset(Context::FCONTEXT_INDEX)));
__ ldr(result, ContextOperand(result, instr->slot_index()));
}
+
+
+void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
+ Register context = ToRegister(instr->context());
+ Register value = ToRegister(instr->value());
+ __ ldr(context,
+ MemOperand(context,
Context::SlotOffset(Context::FCONTEXT_INDEX)));
+ __ str(value, ContextOperand(context, instr->slot_index()));
+ if (instr->needs_write_barrier()) {
+ int offset = Context::SlotOffset(instr->slot_index());
+ __ RecordWrite(context, Operand(offset), value, scratch0());
+ }
+}
void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
@@ -2467,18 +2481,34 @@
__ push(argument_reg);
}
}
+
+
+void LCodeGen::DoContext(LContext* instr) {
+ Register result = ToRegister(instr->result());
+ __ mov(result, cp);
+}
+
+
+void LCodeGen::DoOuterContext(LOuterContext* instr) {
+ Register context = ToRegister(instr->context());
+ Register result = ToRegister(instr->result());
+ __ ldr(result,
+ MemOperand(context, Context::SlotOffset(Context::CLOSURE_INDEX)));
+ __ ldr(result, FieldMemOperand(result, JSFunction::kContextOffset));
+}
void LCodeGen::DoGlobalObject(LGlobalObject* instr) {
+ Register context = ToRegister(instr->context());
Register result = ToRegister(instr->result());
__ ldr(result, ContextOperand(cp, Context::GLOBAL_INDEX));
}
void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) {
+ Register global = ToRegister(instr->global());
Register result = ToRegister(instr->result());
- __ ldr(result, ContextOperand(cp, Context::GLOBAL_INDEX));
- __ ldr(result, FieldMemOperand(result,
GlobalObject::kGlobalReceiverOffset));
+ __ ldr(result, FieldMemOperand(global,
GlobalObject::kGlobalReceiverOffset));
}
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.cc Mon Jan 31
04:36:54 2011
+++ /branches/bleeding_edge/src/hydrogen-instructions.cc Thu Feb 3
05:10:28 2011
@@ -1193,7 +1193,15 @@
void HLoadContextSlot::PrintDataTo(StringStream* stream) const {
- stream->Add("(%d, %d)", context_chain_length(), slot_index());
+ value()->PrintNameTo(stream);
+ stream->Add("[%d]", slot_index());
+}
+
+
+void HStoreContextSlot::PrintDataTo(StringStream* stream) const {
+ context()->PrintNameTo(stream);
+ stream->Add("[%d] = ", slot_index());
+ value()->PrintNameTo(stream);
}
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.h Wed Feb 2 05:55:29
2011
+++ /branches/bleeding_edge/src/hydrogen-instructions.h Thu Feb 3 05:10:28
2011
@@ -98,6 +98,7 @@
V(CompareJSObjectEq) \
V(CompareMap) \
V(Constant) \
+ V(Context) \
V(DeleteProperty) \
V(Deoptimize) \
V(Div) \
@@ -129,6 +130,7 @@
V(Mul) \
V(ObjectLiteral) \
V(OsrEntry) \
+ V(OuterContext) \
V(Parameter) \
V(Power) \
V(PushArgument) \
@@ -139,6 +141,7 @@
V(Shr) \
V(Simulate) \
V(StackCheck) \
+ V(StoreContextSlot) \
V(StoreGlobal) \
V(StoreKeyedFastElement) \
V(StoreKeyedGeneric) \
@@ -163,6 +166,7 @@
V(GlobalVars) \
V(Maps) \
V(ArrayLengths) \
+ V(ContextSlots) \
V(OsrEntries)
#define DECLARE_INSTRUCTION(type) \
@@ -1060,12 +1064,39 @@
};
-class HGlobalObject: public HInstruction {
+class HContext: public HInstruction {
public:
- HGlobalObject() {
+ HContext() {
set_representation(Representation::Tagged());
SetFlag(kUseGVN);
- SetFlag(kDependsOnCalls);
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(Context, "context");
+
+ protected:
+ virtual bool DataEquals(HValue* other) const { return true; }
+};
+
+
+class HOuterContext: public HUnaryOperation {
+ public:
+ explicit HOuterContext(HValue* inner) : HUnaryOperation(inner) {
+ set_representation(Representation::Tagged());
+ SetFlag(kUseGVN);
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(OuterContext, "outer_context");
+
+ protected:
+ virtual bool DataEquals(HValue* other) const { return true; }
+};
+
+
+class HGlobalObject: public HUnaryOperation {
+ public:
+ explicit HGlobalObject(HValue* context) : HUnaryOperation(context) {
+ set_representation(Representation::Tagged());
+ SetFlag(kUseGVN);
}
DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global_object")
@@ -1075,12 +1106,12 @@
};
-class HGlobalReceiver: public HInstruction {
+class HGlobalReceiver: public HUnaryOperation {
public:
- HGlobalReceiver() {
+ explicit HGlobalReceiver(HValue* global_object)
+ : HUnaryOperation(global_object) {
set_representation(Representation::Tagged());
SetFlag(kUseGVN);
- SetFlag(kDependsOnCalls);
}
DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver, "global_receiver")
@@ -2613,39 +2644,70 @@
};
-class HLoadContextSlot: public HInstruction {
+class HLoadContextSlot: public HUnaryOperation {
public:
- HLoadContextSlot(int context_chain_length , int slot_index)
- : context_chain_length_(context_chain_length),
slot_index_(slot_index) {
+ HLoadContextSlot(HValue* context , int slot_index)
+ : HUnaryOperation(context), slot_index_(slot_index) {
set_representation(Representation::Tagged());
SetFlag(kUseGVN);
- SetFlag(kDependsOnCalls);
+ SetFlag(kDependsOnContextSlots);
}
- int context_chain_length() const { return context_chain_length_; }
int slot_index() const { return slot_index_; }
- virtual void PrintDataTo(StringStream* stream) const;
-
- virtual intptr_t Hashcode() const {
- return context_chain_length() * 29 + slot_index();
- }
+ virtual Representation RequiredInputRepresentation(int index) const {
+ return Representation::Tagged();
+ }
+
+ virtual void PrintDataTo(StringStream* stream) const;
DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot, "load_context_slot")
protected:
virtual bool DataEquals(HValue* other) const {
HLoadContextSlot* b = HLoadContextSlot::cast(other);
- return (context_chain_length() == b->context_chain_length())
- && (slot_index() == b->slot_index());
+ return (slot_index() == b->slot_index());
}
private:
- int context_chain_length_;
int slot_index_;
};
+static inline bool StoringValueNeedsWriteBarrier(HValue* value) {
+ return !value->type().IsSmi() &&
+ !(value->IsConstant() && HConstant::cast(value)->InOldSpace());
+}
+
+
+class HStoreContextSlot: public HBinaryOperation {
+ public:
+ HStoreContextSlot(HValue* context, int slot_index, HValue* value)
+ : HBinaryOperation(context, value), slot_index_(slot_index) {
+ SetFlag(kChangesContextSlots);
+ }
+
+ HValue* context() const { return OperandAt(0); }
+ HValue* value() const { return OperandAt(1); }
+ int slot_index() const { return slot_index_; }
+
+ bool NeedsWriteBarrier() const {
+ return StoringValueNeedsWriteBarrier(value());
+ }
+
+ virtual Representation RequiredInputRepresentation(int index) const {
+ return Representation::Tagged();
+ }
+
+ virtual void PrintDataTo(StringStream* stream) const;
+
+ DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot, "store_context_slot")
+
+ private:
+ int slot_index_;
+};
+
+
class HLoadNamedField: public HUnaryOperation {
public:
HLoadNamedField(HValue* object, bool is_in_object, int offset)
@@ -2777,12 +2839,6 @@
};
-static inline bool StoringValueNeedsWriteBarrier(HValue* value) {
- return !value->type().IsSmi() &&
- !(value->IsConstant() && HConstant::cast(value)->InOldSpace());
-}
-
-
class HStoreNamed: public HBinaryOperation {
public:
HStoreNamed(HValue* obj, Handle<Object> name, HValue* val)
@@ -2799,10 +2855,6 @@
Handle<Object> name() const { return name_; }
HValue* value() const { return OperandAt(1); }
void set_value(HValue* value) { SetOperandAt(1, value); }
-
- bool NeedsWriteBarrier() const {
- return StoringValueNeedsWriteBarrier(value());
- }
DECLARE_INSTRUCTION(StoreNamed)
@@ -2831,7 +2883,7 @@
DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store_named_field")
virtual Representation RequiredInputRepresentation(int index) const {
- return Representation::Tagged();
+ return Representation::Tagged();
}
virtual void PrintDataTo(StringStream* stream) const;
@@ -2839,6 +2891,10 @@
int offset() const { return offset_; }
Handle<Map> transition() const { return transition_; }
void set_transition(Handle<Map> map) { transition_ = map; }
+
+ bool NeedsWriteBarrier() const {
+ return StoringValueNeedsWriteBarrier(value());
+ }
private:
bool is_in_object_;
=======================================
--- /branches/bleeding_edge/src/hydrogen.cc Wed Feb 2 05:55:29 2011
+++ /branches/bleeding_edge/src/hydrogen.cc Thu Feb 3 05:10:28 2011
@@ -2953,6 +2953,19 @@
BAILOUT("read-only global variable");
}
}
+
+
+HValue* HGraphBuilder::BuildContextChainWalk(Variable* var) {
+ ASSERT(var->IsContextSlot());
+ HInstruction* context = new HContext;
+ AddInstruction(context);
+ int length = graph()->info()->scope()->ContextChainLength(var->scope());
+ while (length-- > 0) {
+ context = new HOuterContext(context);
+ AddInstruction(context);
+ }
+ return context;
+}
void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
@@ -2968,16 +2981,9 @@
if (variable->mode() == Variable::CONST) {
BAILOUT("reference to const context slot");
}
- Slot* slot = variable->AsSlot();
- CompilationInfo* info = graph()->info();
- int context_chain_length = info->function()->scope()->
- ContextChainLength(slot->var()->scope());
- ASSERT(context_chain_length >= 0);
- // TODO(antonm): if slot's value is not modified by closures, instead
- // of reading it out of context, we could just embed the value as
- // a constant.
- HLoadContextSlot* instr =
- new HLoadContextSlot(context_chain_length, slot->index());
+ HValue* context = BuildContextChainWalk(variable);
+ int index = variable->AsSlot()->index();
+ HLoadContextSlot* instr = new HLoadContextSlot(context, index);
ast_context()->ReturnInstruction(instr, expr->id());
} else if (variable->is_global()) {
LookupResult lookup;
@@ -3515,35 +3521,48 @@
if (proxy->IsArguments()) BAILOUT("assignment to arguments");
// Handle the assignment.
- if (var->is_global()) {
+ if (var->IsStackAllocated()) {
+ HValue* value = NULL;
+ // Handle stack-allocated variables on the right-hand side directly.
+ // We do not allow the arguments object to occur in a context where
it
+ // may escape, but assignments to stack-allocated locals are
+ // permitted. Handling such assignments here bypasses the check for
+ // the arguments object in VisitVariableProxy.
+ Variable* rhs_var = expr->value()->AsVariableProxy()->AsVariable();
+ if (rhs_var != NULL && rhs_var->IsStackAllocated()) {
+ value = environment()->Lookup(rhs_var);
+ } else {
+ VISIT_FOR_VALUE(expr->value());
+ value = Pop();
+ }
+ Bind(var, value);
+ ast_context()->ReturnValue(value);
+
+ } else if (var->IsContextSlot() && var->mode() != Variable::CONST) {
+ VISIT_FOR_VALUE(expr->value());
+ HValue* context = BuildContextChainWalk(var);
+ int index = var->AsSlot()->index();
+ HStoreContextSlot* instr = new HStoreContextSlot(context, index,
Top());
+ AddInstruction(instr);
+ if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
+ ast_context()->ReturnValue(Pop());
+
+ } else if (var->is_global()) {
VISIT_FOR_VALUE(expr->value());
HandleGlobalVariableAssignment(var,
Top(),
expr->position(),
expr->AssignmentId());
- } else if (var->IsStackAllocated()) {
- // We allow reference to the arguments object only in assignemtns
- // to local variables to make sure that the arguments object does
- // not escape and is not modified.
- VariableProxy* rhs = expr->value()->AsVariableProxy();
- if (rhs != NULL &&
- rhs->var()->IsStackAllocated() &&
-
environment()->Lookup(rhs->var())->CheckFlag(HValue::kIsArguments)) {
- Push(environment()->Lookup(rhs->var()));
- } else {
- VISIT_FOR_VALUE(expr->value());
- }
- Bind(proxy->var(), Top());
+ ast_context()->ReturnValue(Pop());
+
} else {
- BAILOUT("Assigning to no non-stack-allocated/non-global variable");
- }
- // Return the value.
- ast_context()->ReturnValue(Pop());
+ BAILOUT("assignment to LOOKUP or const CONTEXT variable");
+ }
} else if (prop != NULL) {
HandlePropertyAssignment(expr);
} else {
- BAILOUT("unsupported invalid lhs");
+ BAILOUT("invalid left-hand side in assignment");
}
}
@@ -4422,7 +4441,10 @@
if (known_global_function) {
// Push the global object instead of the global receiver because
// code generated by the full code generator expects it.
- PushAndAdd(new HGlobalObject);
+ HContext* context = new HContext;
+ HGlobalObject* global_object = new HGlobalObject(context);
+ AddInstruction(context);
+ PushAndAdd(global_object);
VisitArgumentList(expr->arguments());
CHECK_BAILOUT;
@@ -4431,7 +4453,7 @@
AddInstruction(new HCheckFunction(function, expr->target()));
// Replace the global object with the global receiver.
- HGlobalReceiver* global_receiver = new HGlobalReceiver;
+ HGlobalReceiver* global_receiver = new
HGlobalReceiver(global_object);
// Index of the receiver from the top of the expression stack.
const int receiver_index = argument_count - 1;
AddInstruction(global_receiver);
@@ -4458,7 +4480,9 @@
call = new HCallKnownGlobal(expr->target(), argument_count);
} else {
- PushAndAdd(new HGlobalObject);
+ HContext* context = new HContext;
+ AddInstruction(context);
+ PushAndAdd(new HGlobalObject(context));
VisitArgumentList(expr->arguments());
CHECK_BAILOUT;
@@ -4466,7 +4490,11 @@
}
} else {
- PushAndAdd(new HGlobalReceiver);
+ HContext* context = new HContext;
+ HGlobalObject* global_object = new HGlobalObject(context);
+ AddInstruction(context);
+ AddInstruction(global_object);
+ PushAndAdd(new HGlobalReceiver(global_object));
VisitArgumentList(expr->arguments());
CHECK_BAILOUT;
=======================================
--- /branches/bleeding_edge/src/hydrogen.h Mon Jan 31 04:36:54 2011
+++ /branches/bleeding_edge/src/hydrogen.h Thu Feb 3 05:10:28 2011
@@ -823,6 +823,8 @@
HValue* switch_value,
CaseClause* clause);
+ HValue* BuildContextChainWalk(Variable* var);
+
void AddCheckConstantFunction(Call* expr,
HValue* receiver,
Handle<Map> receiver_map,
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Thu Feb 3
02:07:22 2011
+++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Thu Feb 3
05:10:28 2011
@@ -1914,11 +1914,26 @@
void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
- // TODO(antonm): load a context with a separate instruction.
+ Register context = ToRegister(instr->InputAt(0));
Register result = ToRegister(instr->result());
- __ LoadContext(result, instr->context_chain_length());
+ __ mov(result,
+ Operand(context, Context::SlotOffset(Context::FCONTEXT_INDEX)));
__ mov(result, ContextOperand(result, instr->slot_index()));
}
+
+
+void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
+ Register context = ToRegister(instr->context());
+ Register value = ToRegister(instr->value());
+ __ mov(context,
+ Operand(context, Context::SlotOffset(Context::FCONTEXT_INDEX)));
+ __ mov(ContextOperand(context, instr->slot_index()), value);
+ if (instr->needs_write_barrier()) {
+ Register temp = ToRegister(instr->TempAt(0));
+ int offset = Context::SlotOffset(instr->slot_index());
+ __ RecordWrite(context, offset, value, temp);
+ }
+}
void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
@@ -2153,18 +2168,33 @@
__ push(ToOperand(argument));
}
}
+
+
+void LCodeGen::DoContext(LContext* instr) {
+ Register result = ToRegister(instr->result());
+ __ mov(result, esi);
+}
+
+
+void LCodeGen::DoOuterContext(LOuterContext* instr) {
+ Register context = ToRegister(instr->context());
+ Register result = ToRegister(instr->result());
+ __ mov(result, Operand(context,
Context::SlotOffset(Context::CLOSURE_INDEX)));
+ __ mov(result, FieldOperand(result, JSFunction::kContextOffset));
+}
void LCodeGen::DoGlobalObject(LGlobalObject* instr) {
+ Register context = ToRegister(instr->context());
Register result = ToRegister(instr->result());
- __ mov(result, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
+ __ mov(result, Operand(context,
Context::SlotOffset(Context::GLOBAL_INDEX)));
}
void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) {
+ Register global = ToRegister(instr->global());
Register result = ToRegister(instr->result());
- __ mov(result, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
- __ mov(result, FieldOperand(result,
GlobalObject::kGlobalReceiverOffset));
+ __ mov(result, FieldOperand(global,
GlobalObject::kGlobalReceiverOffset));
}
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.cc Wed Feb 2 05:55:29
2011
+++ /branches/bleeding_edge/src/ia32/lithium-ia32.cc Thu Feb 3 05:10:28
2011
@@ -268,7 +268,15 @@
void LLoadContextSlot::PrintDataTo(StringStream* stream) {
- stream->Add("(%d, %d)", context_chain_length(), slot_index());
+ InputAt(0)->PrintTo(stream);
+ stream->Add("[%d]", slot_index());
+}
+
+
+void LStoreContextSlot::PrintDataTo(StringStream* stream) {
+ InputAt(0)->PrintTo(stream);
+ stream->Add("[%d] <- ", slot_index());
+ InputAt(1)->PrintTo(stream);
}
@@ -1138,15 +1146,28 @@
LOperand* argument = UseOrConstant(instr->argument());
return new LPushArgument(argument);
}
+
+
+LInstruction* LChunkBuilder::DoContext(HContext* instr) {
+ return DefineAsRegister(new LContext);
+}
+
+
+LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
+ LOperand* context = UseRegisterAtStart(instr->value());
+ return DefineAsRegister(new LOuterContext(context));
+}
LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
- return DefineAsRegister(new LGlobalObject);
+ LOperand* context = UseRegisterAtStart(instr->value());
+ return DefineAsRegister(new LGlobalObject(context));
}
LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) {
- return DefineAsRegister(new LGlobalReceiver);
+ LOperand* global_object = UseRegisterAtStart(instr->value());
+ return DefineAsRegister(new LGlobalReceiver(global_object));
}
@@ -1658,7 +1679,23 @@
LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
- return DefineAsRegister(new LLoadContextSlot);
+ LOperand* context = UseRegisterAtStart(instr->value());
+ return DefineAsRegister(new LLoadContextSlot(context));
+}
+
+
+LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
+ LOperand* context = UseTempRegister(instr->context());
+ LOperand* value;
+ LOperand* temp;
+ if (instr->NeedsWriteBarrier()) {
+ value = UseTempRegister(instr->value());
+ temp = TempRegister();
+ } else {
+ value = UseRegister(instr->value());
+ temp = NULL;
+ }
+ return new LStoreContextSlot(context, value, temp);
}
@@ -1756,7 +1793,8 @@
// We only need a scratch register if we have a write barrier or we
// have a store into the properties array (not in-object-property).
LOperand* temp = (!instr->is_in_object() || needs_write_barrier)
- ? TempRegister() : NULL;
+ ? TempRegister()
+ : NULL;
return new LStoreNamedField(obj, val, temp);
}
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.h Wed Feb 2 05:55:29 2011
+++ /branches/bleeding_edge/src/ia32/lithium-ia32.h Thu Feb 3 05:10:28 2011
@@ -39,118 +39,6 @@
// Forward declarations.
class LCodeGen;
-
-// Type hierarchy:
-//
-// LInstruction
-// LTemplateInstruction
-// LControlInstruction
-// LBranch
-// LClassOfTestAndBranch
-// LCmpJSObjectEqAndBranch
-// LCmpIDAndBranch
-// LHasCachedArrayIndexAndBranch
-// LHasInstanceTypeAndBranch
-// LInstanceOfAndBranch
-// LIsNullAndBranch
-// LIsObjectAndBranch
-// LIsSmiAndBranch
-// LTypeofIsAndBranch
-// LAccessArgumentsAt
-// LArgumentsElements
-// LArgumentsLength
-// LAddI
-// LApplyArguments
-// LArithmeticD
-// LArithmeticT
-// LBitI
-// LBoundsCheck
-// LCmpID
-// LCmpJSObjectEq
-// LCmpT
-// LDivI
-// LInstanceOf
-// LInstanceOfKnownGlobal
-// LLoadKeyedFastElement
-// LLoadKeyedGeneric
-// LModI
-// LMulI
-// LPower
-// LShiftI
-// LSubI
-// LCallConstantFunction
-// LCallFunction
-// LCallGlobal
-// LCallKeyed
-// LCallKnownGlobal
-// LCallNamed
-// LCallRuntime
-// LCallStub
-// LConstant
-// LConstantD
-// LConstantI
-// LConstantT
-// LDeoptimize
-// LFunctionLiteral
-// LGap
-// LLabel
-// LGlobalObject
-// LGlobalReceiver
-// LGoto
-// LLazyBailout
-// LLoadGlobal
-// LCheckPrototypeMaps
-// LLoadContextSlot
-// LArrayLiteral
-// LObjectLiteral
-// LRegExpLiteral
-// LOsrEntry
-// LParameter
-// LRegExpConstructResult
-// LStackCheck
-// LStoreKeyed
-// LStoreKeyedFastElement
-// LStoreKeyedGeneric
-// LStoreNamed
-// LStoreNamedField
-// LStoreNamedGeneric
-// LStringCharCodeAt
-// LBitNotI
-// LCallNew
-// LCheckFunction
-// LCheckPrototypeMaps
-// LCheckInstanceType
-// LCheckMap
-// LCheckSmi
-// LClassOfTest
-// LDeleteProperty
-// LDoubleToI
-// LFixedArrayLength
-// LHasCachedArrayIndex
-// LHasInstanceType
-// LInteger32ToDouble
-// LIsNull
-// LIsObject
-// LIsSmi
-// LJSArrayLength
-// LLoadNamedField
-// LLoadNamedGeneric
-// LLoadFunctionPrototype
-// LNumberTagD
-// LNumberTagI
-// LPushArgument
-// LReturn
-// LSmiTag
-// LStoreGlobal
-// LStringLength
-// LTaggedToI
-// LThrow
-// LTypeof
-// LTypeofIs
-// LUnaryMathOperation
-// LValueOf
-// LUnknownOSRValue
-
#define LITHIUM_ALL_INSTRUCTION_LIST(V) \
V(ControlInstruction) \
V(Constant) \
@@ -187,6 +75,8 @@
V(CheckMap) \
V(CheckPrototypeMaps) \
V(CheckSmi) \
+ V(ClassOfTest) \
+ V(ClassOfTestAndBranch) \
V(CmpID) \
V(CmpIDAndBranch) \
V(CmpJSObjectEq) \
@@ -197,16 +87,21 @@
V(ConstantD) \
V(ConstantI) \
V(ConstantT) \
+ V(Context) \
V(DeleteProperty) \
V(Deoptimize) \
V(DivI) \
V(DoubleToI) \
+ V(FixedArrayLength) \
V(FunctionLiteral) \
V(Gap) \
V(GlobalObject) \
V(GlobalReceiver) \
V(Goto) \
- V(FixedArrayLength) \
+ V(HasCachedArrayIndex) \
+ V(HasCachedArrayIndexAndBranch) \
+ V(HasInstanceType) \
+ V(HasInstanceTypeAndBranch) \
V(InstanceOf) \
V(InstanceOfAndBranch) \
V(InstanceOfKnownGlobal) \
@@ -218,22 +113,16 @@
V(IsSmi) \
V(IsSmiAndBranch) \
V(JSArrayLength) \
- V(HasInstanceType) \
- V(HasInstanceTypeAndBranch) \
- V(HasCachedArrayIndex) \
- V(HasCachedArrayIndexAndBranch) \
- V(ClassOfTest) \
- V(ClassOfTestAndBranch) \
V(Label) \
V(LazyBailout) \
V(LoadContextSlot) \
V(LoadElements) \
+ V(LoadFunctionPrototype) \
V(LoadGlobal) \
V(LoadKeyedFastElement) \
V(LoadKeyedGeneric) \
V(LoadNamedField) \
V(LoadNamedGeneric) \
- V(LoadFunctionPrototype) \
V(ModI) \
V(MulI) \
V(NumberTagD) \
@@ -241,6 +130,7 @@
V(NumberUntagD) \
V(ObjectLiteral) \
V(OsrEntry) \
+ V(OuterContext) \
V(Parameter) \
V(Power) \
V(PushArgument) \
@@ -250,6 +140,7 @@
V(SmiTag) \
V(SmiUntag) \
V(StackCheck) \
+ V(StoreContextSlot) \
V(StoreGlobal) \
V(StoreKeyedFastElement) \
V(StoreKeyedGeneric) \
@@ -1286,13 +1177,37 @@
};
-class LLoadContextSlot: public LTemplateInstruction<1, 0, 0> {
+class LLoadContextSlot: public LTemplateInstruction<1, 1, 0> {
public:
+ explicit LLoadContextSlot(LOperand* context) {
+ inputs_[0] = context;
+ }
+
DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot, "load-context-slot")
DECLARE_HYDROGEN_ACCESSOR(LoadContextSlot)
- int context_chain_length() { return hydrogen()->context_chain_length(); }
+ LOperand* context() { return InputAt(0); }
int slot_index() { return hydrogen()->slot_index(); }
+
+ virtual void PrintDataTo(StringStream* stream);
+};
+
+
+class LStoreContextSlot: public LTemplateInstruction<0, 2, 1> {
+ public:
+ LStoreContextSlot(LOperand* context, LOperand* value, LOperand* temp) {
+ inputs_[0] = context;
+ inputs_[1] = value;
+ temps_[0] = temp;
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot, "store-context-slot")
+ DECLARE_HYDROGEN_ACCESSOR(StoreContextSlot)
+
+ LOperand* context() { return InputAt(0); }
+ LOperand* value() { return InputAt(1); }
+ int slot_index() { return hydrogen()->slot_index(); }
+ int needs_write_barrier() { return hydrogen()->NeedsWriteBarrier(); }
virtual void PrintDataTo(StringStream* stream);
};
@@ -1308,15 +1223,45 @@
};
-class LGlobalObject: public LTemplateInstruction<1, 0, 0> {
+class LContext: public LTemplateInstruction<1, 0, 0> {
public:
+ DECLARE_CONCRETE_INSTRUCTION(Context, "context")
+};
+
+
+class LOuterContext: public LTemplateInstruction<1, 1, 0> {
+ public:
+ explicit LOuterContext(LOperand* context) {
+ inputs_[0] = context;
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(OuterContext, "outer-context")
+
+ LOperand* context() { return InputAt(0); }
+};
+
+
+class LGlobalObject: public LTemplateInstruction<1, 1, 0> {
+ public:
+ explicit LGlobalObject(LOperand* context) {
+ inputs_[0] = context;
+ }
+
DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global-object")
+
+ LOperand* context() { return InputAt(0); }
};
-class LGlobalReceiver: public LTemplateInstruction<1, 0, 0> {
+class LGlobalReceiver: public LTemplateInstruction<1, 1, 0> {
public:
+ explicit LGlobalReceiver(LOperand* global_object) {
+ inputs_[0] = global_object;
+ }
+
DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver, "global-receiver")
+
+ LOperand* global() { return InputAt(0); }
};
=======================================
--- /branches/bleeding_edge/src/x64/lithium-x64.cc Wed Feb 2 06:08:30 2011
+++ /branches/bleeding_edge/src/x64/lithium-x64.cc Thu Feb 3 05:10:28 2011
@@ -262,7 +262,8 @@
void LLoadContextSlot::PrintDataTo(StringStream* stream) {
- stream->Add("(%d, %d)", context_chain_length(), slot_index());
+ InputAt(0)->PrintTo(stream);
+ stream->Add("[%d]", slot_index());
}
@@ -1047,6 +1048,18 @@
LOperand* argument = UseOrConstant(instr->argument());
return new LPushArgument(argument);
}
+
+
+LInstruction* LChunkBuilder::DoContext(HContext* instr) {
+ Abort("Unimplemented: DoContext");
+ return NULL;
+}
+
+
+LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
+ Abort("Unimplemented: DoOuterContext");
+ return NULL;
+}
LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
@@ -1472,13 +1485,20 @@
LInstruction* LChunkBuilder::DoStoreGlobal(HStoreGlobal* instr) {
- return new LStoreGlobal(UseRegisterAtStart(instr->value()));}
+ return new LStoreGlobal(UseRegisterAtStart(instr->value()));
+}
LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
Abort("Unimplemented: %s", "DoLoadContextSlot");
return NULL;
}
+
+
+LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
+ Abort("Unimplemented: DoStoreContextSlot");
+ return NULL;
+}
LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
=======================================
--- /branches/bleeding_edge/src/x64/lithium-x64.h Wed Feb 2 05:55:29 2011
+++ /branches/bleeding_edge/src/x64/lithium-x64.h Thu Feb 3 05:10:28 2011
@@ -1280,12 +1280,16 @@
};
-class LLoadContextSlot: public LTemplateInstruction<1, 0, 0> {
+class LLoadContextSlot: public LTemplateInstruction<1, 1, 0> {
public:
+ explicit LLoadContextSlot(LOperand* context) {
+ inputs_[0] = context;
+ }
+
DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot, "load-context-slot")
DECLARE_HYDROGEN_ACCESSOR(LoadContextSlot)
- int context_chain_length() { return hydrogen()->context_chain_length(); }
+ LOperand* context() { return InputAt(0); }
int slot_index() { return hydrogen()->slot_index(); }
virtual void PrintDataTo(StringStream* stream);
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev