Small cleanup of the code generator: make the static code gen

functions and the ones defined on the AST nodes take a code generator,
rather than a macro assembler and (sometimes) scope.

Uniformly use the __ macro for masm_/masm in the codegen*.cc files.
Review URL: http://codereview.chromium.org/5663

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@408 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent d7599384
...@@ -159,8 +159,7 @@ class Expression: public Node { ...@@ -159,8 +159,7 @@ class Expression: public Node {
// the expression stack, and a reference containing the expression // the expression stack, and a reference containing the expression
// immediately below that. This function is overridden for expression // immediately below that. This function is overridden for expression
// types that can be stored into. // types that can be stored into.
virtual void GenerateStoreCode(MacroAssembler* masm, virtual void GenerateStoreCode(CodeGenerator* cgen,
Scope* scope,
Reference* ref, Reference* ref,
InitState init_state) { InitState init_state) {
UNREACHABLE(); UNREACHABLE();
...@@ -763,8 +762,7 @@ class VariableProxy: public Expression { ...@@ -763,8 +762,7 @@ class VariableProxy: public Expression {
// side of an assignment. The code will expect the stored value on top of // side of an assignment. The code will expect the stored value on top of
// the expression stack, and a reference containing the expression // the expression stack, and a reference containing the expression
// immediately below that. // immediately below that.
virtual void GenerateStoreCode(MacroAssembler* masm, virtual void GenerateStoreCode(CodeGenerator* cgen,
Scope* scope,
Reference* ref, Reference* ref,
InitState init_state); InitState init_state);
protected: protected:
...@@ -846,8 +844,7 @@ class Slot: public Expression { ...@@ -846,8 +844,7 @@ class Slot: public Expression {
// side of an assignment. The code will expect the stored value on top of // side of an assignment. The code will expect the stored value on top of
// the expression stack, and a reference containing the expression // the expression stack, and a reference containing the expression
// immediately below that. // immediately below that.
virtual void GenerateStoreCode(MacroAssembler* masm, virtual void GenerateStoreCode(CodeGenerator* cgen,
Scope* scope,
Reference* ref, Reference* ref,
InitState init_state); InitState init_state);
private: private:
...@@ -881,8 +878,7 @@ class Property: public Expression { ...@@ -881,8 +878,7 @@ class Property: public Expression {
// side of an assignment. The code will expect the stored value on top of // side of an assignment. The code will expect the stored value on top of
// the expression stack, and a reference containing the expression // the expression stack, and a reference containing the expression
// immediately below that. // immediately below that.
virtual void GenerateStoreCode(MacroAssembler* masm, virtual void GenerateStoreCode(CodeGenerator* cgen,
Scope* scope,
Reference* ref, Reference* ref,
InitState init_state); InitState init_state);
private: private:
......
...@@ -140,6 +140,8 @@ class ArmCodeGenerator: public CodeGenerator { ...@@ -140,6 +140,8 @@ class ArmCodeGenerator: public CodeGenerator {
MacroAssembler* masm() { return masm_; } MacroAssembler* masm() { return masm_; }
Scope* scope() const { return scope_; }
CodeGenState* state() { return state_; } CodeGenState* state() { return state_; }
void set_state(CodeGenState* state) { state_ = state; } void set_state(CodeGenState* state) { state_ = state; }
...@@ -188,29 +190,29 @@ class ArmCodeGenerator: public CodeGenerator { ...@@ -188,29 +190,29 @@ class ArmCodeGenerator: public CodeGenerator {
return MemOperand(context, Context::SlotOffset(index)); return MemOperand(context, Context::SlotOffset(index));
} }
static MemOperand ParameterOperand(Scope* scope, int index) { static MemOperand ParameterOperand(const CodeGenerator* cgen, int index) {
int num_parameters = cgen->scope()->num_parameters();
// index -2 corresponds to the activated closure, -1 corresponds // index -2 corresponds to the activated closure, -1 corresponds
// to the receiver // to the receiver
ASSERT(-2 <= index && index < scope->num_parameters()); ASSERT(-2 <= index && index < num_parameters);
int offset = (1 + scope->num_parameters() - index) * kPointerSize; int offset = (1 + num_parameters - index) * kPointerSize;
return MemOperand(fp, offset); return MemOperand(fp, offset);
} }
MemOperand ParameterOperand(int index) const { MemOperand ParameterOperand(int index) const {
return ParameterOperand(scope_, index); return ParameterOperand(this, index);
} }
MemOperand FunctionOperand() const { MemOperand FunctionOperand() const {
return MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset); return MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset);
} }
static MemOperand SlotOperand(MacroAssembler* masm, static MemOperand SlotOperand(CodeGenerator* cgen,
Scope* scope,
Slot* slot, Slot* slot,
Register tmp); Register tmp);
MemOperand SlotOperand(Slot* slot, Register tmp) { MemOperand SlotOperand(Slot* slot, Register tmp) {
return SlotOperand(masm_, scope_, slot, tmp); return SlotOperand(this, slot, tmp);
} }
void LoadCondition(Expression* x, CodeGenState::AccessType access, void LoadCondition(Expression* x, CodeGenState::AccessType access,
...@@ -246,7 +248,7 @@ class ArmCodeGenerator: public CodeGenerator { ...@@ -246,7 +248,7 @@ class ArmCodeGenerator: public CodeGenerator {
void SetValue(Reference* ref) { void SetValue(Reference* ref) {
ASSERT(!has_cc()); ASSERT(!has_cc());
ASSERT(!ref->is_illegal()); ASSERT(!ref->is_illegal());
ref->expression()->GenerateStoreCode(masm_, scope_, ref, NOT_CONST_INIT); ref->expression()->GenerateStoreCode(this, ref, NOT_CONST_INIT);
} }
// Generate code to store a value in a reference. The stored value is // Generate code to store a value in a reference. The stored value is
...@@ -255,7 +257,7 @@ class ArmCodeGenerator: public CodeGenerator { ...@@ -255,7 +257,7 @@ class ArmCodeGenerator: public CodeGenerator {
void InitConst(Reference* ref) { void InitConst(Reference* ref) {
ASSERT(!has_cc()); ASSERT(!has_cc());
ASSERT(!ref->is_illegal()); ASSERT(!ref->is_illegal());
ref->expression()->GenerateStoreCode(masm_, scope_, ref, CONST_INIT); ref->expression()->GenerateStoreCode(this, ref, CONST_INIT);
} }
// Generate code to fetch a value from a property of a reference. The // Generate code to fetch a value from a property of a reference. The
...@@ -267,7 +269,7 @@ class ArmCodeGenerator: public CodeGenerator { ...@@ -267,7 +269,7 @@ class ArmCodeGenerator: public CodeGenerator {
// stored value is expected on top of the expression stack, with the // stored value is expected on top of the expression stack, with the
// reference immediately below it. The expression stack is left // reference immediately below it. The expression stack is left
// unchanged. // unchanged.
static void SetReferenceProperty(MacroAssembler* masm, static void SetReferenceProperty(CodeGenerator* cgen,
Reference* ref, Reference* ref,
Expression* key); Expression* key);
...@@ -376,7 +378,6 @@ CodeGenState::~CodeGenState() { ...@@ -376,7 +378,6 @@ CodeGenState::~CodeGenState() {
#define __ masm_-> #define __ masm_->
Handle<Code> ArmCodeGenerator::MakeCode(FunctionLiteral* flit, Handle<Code> ArmCodeGenerator::MakeCode(FunctionLiteral* flit,
Handle<Script> script, Handle<Script> script,
bool is_eval) { bool is_eval) {
...@@ -670,8 +671,10 @@ void ArmCodeGenerator::GenCode(FunctionLiteral* fun) { ...@@ -670,8 +671,10 @@ void ArmCodeGenerator::GenCode(FunctionLiteral* fun) {
} }
MemOperand ArmCodeGenerator::SlotOperand(MacroAssembler* masm, #undef __
Scope* scope, #define __ masm->
MemOperand ArmCodeGenerator::SlotOperand(CodeGenerator* cgen,
Slot* slot, Slot* slot,
Register tmp) { Register tmp) {
// Currently, this assertion will fail if we try to assign to // Currently, this assertion will fail if we try to assign to
...@@ -686,11 +689,11 @@ MemOperand ArmCodeGenerator::SlotOperand(MacroAssembler* masm, ...@@ -686,11 +689,11 @@ MemOperand ArmCodeGenerator::SlotOperand(MacroAssembler* masm,
int index = slot->index(); int index = slot->index();
switch (slot->type()) { switch (slot->type()) {
case Slot::PARAMETER: case Slot::PARAMETER:
return ParameterOperand(scope, index); return ParameterOperand(cgen, index);
case Slot::LOCAL: { case Slot::LOCAL: {
ASSERT(0 <= index && ASSERT(0 <= index &&
index < scope->num_stack_slots() && index < cgen->scope()->num_stack_slots() &&
index >= 0); index >= 0);
int local_offset = JavaScriptFrameConstants::kLocal0Offset - int local_offset = JavaScriptFrameConstants::kLocal0Offset -
index * kPointerSize; index * kPointerSize;
...@@ -698,18 +701,20 @@ MemOperand ArmCodeGenerator::SlotOperand(MacroAssembler* masm, ...@@ -698,18 +701,20 @@ MemOperand ArmCodeGenerator::SlotOperand(MacroAssembler* masm,
} }
case Slot::CONTEXT: { case Slot::CONTEXT: {
MacroAssembler* masm = cgen->masm();
// Follow the context chain if necessary. // Follow the context chain if necessary.
ASSERT(!tmp.is(cp)); // do not overwrite context register ASSERT(!tmp.is(cp)); // do not overwrite context register
Register context = cp; Register context = cp;
int chain_length = scope->ContextChainLength(slot->var()->scope()); int chain_length =
cgen->scope()->ContextChainLength(slot->var()->scope());
for (int i = chain_length; i-- > 0;) { for (int i = chain_length; i-- > 0;) {
// Load the closure. // Load the closure.
// (All contexts, even 'with' contexts, have a closure, // (All contexts, even 'with' contexts, have a closure,
// and it is the same for all contexts inside a function. // and it is the same for all contexts inside a function.
// There is no need to go to the function context first.) // There is no need to go to the function context first.)
masm->ldr(tmp, ContextOperand(context, Context::CLOSURE_INDEX)); __ ldr(tmp, ContextOperand(context, Context::CLOSURE_INDEX));
// Load the function context (which is the incoming, outer context). // Load the function context (which is the incoming, outer context).
masm->ldr(tmp, FieldMemOperand(tmp, JSFunction::kContextOffset)); __ ldr(tmp, FieldMemOperand(tmp, JSFunction::kContextOffset));
context = tmp; context = tmp;
} }
// We may have a 'with' context now. Get the function context. // We may have a 'with' context now. Get the function context.
...@@ -719,7 +724,7 @@ MemOperand ArmCodeGenerator::SlotOperand(MacroAssembler* masm, ...@@ -719,7 +724,7 @@ MemOperand ArmCodeGenerator::SlotOperand(MacroAssembler* masm,
// cause the function context of a function context is itself. Before // cause the function context of a function context is itself. Before
// deleting this mov we should try to create a counter-example first, // deleting this mov we should try to create a counter-example first,
// though...) // though...)
masm->ldr(tmp, ContextOperand(context, Context::FCONTEXT_INDEX)); __ ldr(tmp, ContextOperand(context, Context::FCONTEXT_INDEX));
return ContextOperand(tmp, index); return ContextOperand(tmp, index);
} }
...@@ -730,6 +735,9 @@ MemOperand ArmCodeGenerator::SlotOperand(MacroAssembler* masm, ...@@ -730,6 +735,9 @@ MemOperand ArmCodeGenerator::SlotOperand(MacroAssembler* masm,
} }
#undef __
#define __ masm_->
// Loads a value on the stack. If it is a boolean value, the result may have // Loads a value on the stack. If it is a boolean value, the result may have
// been (partially) translated into branches, or it may have set the condition // been (partially) translated into branches, or it may have set the condition
// code register. If force_cc is set, the value is forced to set the condition // code register. If force_cc is set, the value is forced to set the condition
...@@ -894,50 +902,53 @@ void ArmCodeGenerator::UnloadReference(Reference* ref) { ...@@ -894,50 +902,53 @@ void ArmCodeGenerator::UnloadReference(Reference* ref) {
} }
void Property::GenerateStoreCode(MacroAssembler* masm, #undef __
Scope* scope, #define __ masm->
void Property::GenerateStoreCode(CodeGenerator* cgen,
Reference* ref, Reference* ref,
InitState init_state) { InitState init_state) {
MacroAssembler* masm = cgen->masm();
Comment cmnt(masm, "[ Store to Property"); Comment cmnt(masm, "[ Store to Property");
masm->RecordPosition(position()); __ RecordPosition(position());
ArmCodeGenerator::SetReferenceProperty(masm, ref, key()); ArmCodeGenerator::SetReferenceProperty(cgen, ref, key());
} }
void VariableProxy::GenerateStoreCode(MacroAssembler* masm, void VariableProxy::GenerateStoreCode(CodeGenerator* cgen,
Scope* scope,
Reference* ref, Reference* ref,
InitState init_state) { InitState init_state) {
MacroAssembler* masm = cgen->masm();
Comment cmnt(masm, "[ Store to VariableProxy"); Comment cmnt(masm, "[ Store to VariableProxy");
Variable* node = var(); Variable* node = var();
Expression* expr = node->rewrite(); Expression* expr = node->rewrite();
if (expr != NULL) { if (expr != NULL) {
expr->GenerateStoreCode(masm, scope, ref, init_state); expr->GenerateStoreCode(cgen, ref, init_state);
} else { } else {
ASSERT(node->is_global()); ASSERT(node->is_global());
if (node->AsProperty() != NULL) { if (node->AsProperty() != NULL) {
masm->RecordPosition(node->AsProperty()->position()); __ RecordPosition(node->AsProperty()->position());
} }
ArmCodeGenerator::SetReferenceProperty(masm, ref, Expression* key = new Literal(node->name());
new Literal(node->name())); ArmCodeGenerator::SetReferenceProperty(cgen, ref, key);
} }
} }
void Slot::GenerateStoreCode(MacroAssembler* masm, void Slot::GenerateStoreCode(CodeGenerator* cgen,
Scope* scope,
Reference* ref, Reference* ref,
InitState init_state) { InitState init_state) {
MacroAssembler* masm = cgen->masm();
Comment cmnt(masm, "[ Store to Slot"); Comment cmnt(masm, "[ Store to Slot");
if (type() == Slot::LOOKUP) { if (type() == Slot::LOOKUP) {
ASSERT(var()->mode() == Variable::DYNAMIC); ASSERT(var()->mode() == Variable::DYNAMIC);
// For now, just do a runtime call. // For now, just do a runtime call.
masm->push(cp); __ push(cp);
masm->mov(r0, Operand(var()->name())); __ mov(r0, Operand(var()->name()));
masm->push(r0); __ push(r0);
if (init_state == CONST_INIT) { if (init_state == CONST_INIT) {
// Same as the case for a normal store, but ignores attribute // Same as the case for a normal store, but ignores attribute
...@@ -954,13 +965,13 @@ void Slot::GenerateStoreCode(MacroAssembler* masm, ...@@ -954,13 +965,13 @@ void Slot::GenerateStoreCode(MacroAssembler* masm,
// the expression operands are defined and valid, and thus we need the // the expression operands are defined and valid, and thus we need the
// split into 2 operations: declaration of the context slot followed // split into 2 operations: declaration of the context slot followed
// by initialization. // by initialization.
masm->CallRuntime(Runtime::kInitializeConstContextSlot, 3); __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
} else { } else {
masm->CallRuntime(Runtime::kStoreContextSlot, 3); __ CallRuntime(Runtime::kStoreContextSlot, 3);
} }
// Storing a variable must keep the (new) value on the expression // Storing a variable must keep the (new) value on the expression
// stack. This is necessary for compiling assignment expressions. // stack. This is necessary for compiling assignment expressions.
masm->push(r0); __ push(r0);
} else { } else {
ASSERT(var()->mode() != Variable::DYNAMIC); ASSERT(var()->mode() != Variable::DYNAMIC);
...@@ -972,9 +983,9 @@ void Slot::GenerateStoreCode(MacroAssembler* masm, ...@@ -972,9 +983,9 @@ void Slot::GenerateStoreCode(MacroAssembler* masm,
// still contains 'the hole' value). When the assignment is executed, // still contains 'the hole' value). When the assignment is executed,
// the code is identical to a normal store (see below). // the code is identical to a normal store (see below).
Comment cmnt(masm, "[ Init const"); Comment cmnt(masm, "[ Init const");
masm->ldr(r2, ArmCodeGenerator::SlotOperand(masm, scope, this, r2)); __ ldr(r2, ArmCodeGenerator::SlotOperand(cgen, this, r2));
masm->cmp(r2, Operand(Factory::the_hole_value())); __ cmp(r2, Operand(Factory::the_hole_value()));
masm->b(ne, &exit); __ b(ne, &exit);
} }
// We must execute the store. // We must execute the store.
...@@ -986,28 +997,31 @@ void Slot::GenerateStoreCode(MacroAssembler* masm, ...@@ -986,28 +997,31 @@ void Slot::GenerateStoreCode(MacroAssembler* masm,
// because of const declarations which will initialize consts to 'the // because of const declarations which will initialize consts to 'the
// hole' value and by doing so, end up calling this code. r2 may be // hole' value and by doing so, end up calling this code. r2 may be
// loaded with context; used below in RecordWrite. // loaded with context; used below in RecordWrite.
masm->pop(r0); __ pop(r0);
masm->str(r0, ArmCodeGenerator::SlotOperand(masm, scope, this, r2)); __ str(r0, ArmCodeGenerator::SlotOperand(cgen, this, r2));
masm->push(r0); __ push(r0);
if (type() == Slot::CONTEXT) { if (type() == Slot::CONTEXT) {
// Skip write barrier if the written value is a smi. // Skip write barrier if the written value is a smi.
masm->tst(r0, Operand(kSmiTagMask)); __ tst(r0, Operand(kSmiTagMask));
masm->b(eq, &exit); __ b(eq, &exit);
// r2 is loaded with context when calling SlotOperand above. // r2 is loaded with context when calling SlotOperand above.
int offset = FixedArray::kHeaderSize + index() * kPointerSize; int offset = FixedArray::kHeaderSize + index() * kPointerSize;
masm->mov(r3, Operand(offset)); __ mov(r3, Operand(offset));
masm->RecordWrite(r2, r3, r1); __ RecordWrite(r2, r3, r1);
} }
// If we definitely did not jump over the assignment, we do not need to // If we definitely did not jump over the assignment, we do not need to
// bind the exit label. Doing so can defeat peephole optimization. // bind the exit label. Doing so can defeat peephole optimization.
if (init_state == CONST_INIT || type() == Slot::CONTEXT) { if (init_state == CONST_INIT || type() == Slot::CONTEXT) {
masm->bind(&exit); __ bind(&exit);
} }
} }
} }
#undef __
#define __ masm_->
// ECMA-262, section 9.2, page 30: ToBoolean(). Convert the given // ECMA-262, section 9.2, page 30: ToBoolean(). Convert the given
// register to a boolean in the condition code register. The code // register to a boolean in the condition code register. The code
// may jump to 'false_target' in case the register converts to 'false'. // may jump to 'false_target' in case the register converts to 'false'.
...@@ -1051,7 +1065,6 @@ void ArmCodeGenerator::ToBoolean(Label* true_target, ...@@ -1051,7 +1065,6 @@ void ArmCodeGenerator::ToBoolean(Label* true_target,
#undef __ #undef __
#define __ masm-> #define __ masm->
class GetPropertyStub : public CodeStub { class GetPropertyStub : public CodeStub {
public: public:
GetPropertyStub() { } GetPropertyStub() { }
...@@ -1993,7 +2006,6 @@ void ArgumentsAccessStub::Generate(MacroAssembler* masm) { ...@@ -1993,7 +2006,6 @@ void ArgumentsAccessStub::Generate(MacroAssembler* masm) {
#undef __ #undef __
#define __ masm_-> #define __ masm_->
void ArmCodeGenerator::GetReferenceProperty(Expression* key) { void ArmCodeGenerator::GetReferenceProperty(Expression* key) {
ASSERT(!ref()->is_illegal()); ASSERT(!ref()->is_illegal());
Reference::Type type = ref()->type(); Reference::Type type = ref()->type();
...@@ -2032,13 +2044,16 @@ void ArmCodeGenerator::GetReferenceProperty(Expression* key) { ...@@ -2032,13 +2044,16 @@ void ArmCodeGenerator::GetReferenceProperty(Expression* key) {
} }
void ArmCodeGenerator::SetReferenceProperty(MacroAssembler* masm, #undef __
#define __ masm->
void ArmCodeGenerator::SetReferenceProperty(CodeGenerator* cgen,
Reference* ref, Reference* ref,
Expression* key) { Expression* key) {
ASSERT(!ref->is_illegal()); ASSERT(!ref->is_illegal());
Reference::Type type = ref->type(); MacroAssembler* masm = cgen->masm();
if (type == Reference::NAMED) { if (ref->type() == Reference::NAMED) {
// Compute the name of the property. // Compute the name of the property.
Literal* literal = key->AsLiteral(); Literal* literal = key->AsLiteral();
Handle<String> name(String::cast(*literal->handle())); Handle<String> name(String::cast(*literal->handle()));
...@@ -2052,7 +2067,7 @@ void ArmCodeGenerator::SetReferenceProperty(MacroAssembler* masm, ...@@ -2052,7 +2067,7 @@ void ArmCodeGenerator::SetReferenceProperty(MacroAssembler* masm,
} else { } else {
// Access keyed property. // Access keyed property.
ASSERT(type == Reference::KEYED); ASSERT(ref->type() == Reference::KEYED);
masm->pop(r0); // value masm->pop(r0); // value
SetPropertyStub stub; SetPropertyStub stub;
...@@ -2062,6 +2077,9 @@ void ArmCodeGenerator::SetReferenceProperty(MacroAssembler* masm, ...@@ -2062,6 +2077,9 @@ void ArmCodeGenerator::SetReferenceProperty(MacroAssembler* masm,
} }
#undef __
#define __ masm_->
void ArmCodeGenerator::GenericBinaryOperation(Token::Value op) { void ArmCodeGenerator::GenericBinaryOperation(Token::Value op) {
// sp[0] : y // sp[0] : y
// sp[1] : x // sp[1] : x
......
...@@ -146,6 +146,8 @@ class Ia32CodeGenerator: public CodeGenerator { ...@@ -146,6 +146,8 @@ class Ia32CodeGenerator: public CodeGenerator {
MacroAssembler* masm() { return masm_; } MacroAssembler* masm() { return masm_; }
Scope* scope() const { return scope_; }
CodeGenState* state() { return state_; } CodeGenState* state() { return state_; }
void set_state(CodeGenState* state) { state_ = state; } void set_state(CodeGenState* state) { state_ = state; }
...@@ -191,13 +193,14 @@ class Ia32CodeGenerator: public CodeGenerator { ...@@ -191,13 +193,14 @@ class Ia32CodeGenerator: public CodeGenerator {
// Support functions for accessing parameters. Static versions can // Support functions for accessing parameters. Static versions can
// require some code generator state to be passed in as arguments. // require some code generator state to be passed in as arguments.
static Operand ParameterOperand(Scope* scope, int index) { static Operand ParameterOperand(const CodeGenerator* cgen, int index) {
ASSERT(-2 <= index && index < scope->num_parameters()); int num_parameters = cgen->scope()->num_parameters();
return Operand(ebp, (1 + scope->num_parameters() - index) * kPointerSize); ASSERT(-2 <= index && index < num_parameters);
return Operand(ebp, (1 + num_parameters - index) * kPointerSize);
} }
Operand ParameterOperand(int index) const { Operand ParameterOperand(int index) const {
return ParameterOperand(scope_, index); return ParameterOperand(this, index);
} }
Operand ReceiverOperand() const { return ParameterOperand(-1); } Operand ReceiverOperand() const { return ParameterOperand(-1); }
...@@ -210,13 +213,12 @@ class Ia32CodeGenerator: public CodeGenerator { ...@@ -210,13 +213,12 @@ class Ia32CodeGenerator: public CodeGenerator {
return Operand(context, Context::SlotOffset(index)); return Operand(context, Context::SlotOffset(index));
} }
static Operand SlotOperand(MacroAssembler* masm, static Operand SlotOperand(CodeGenerator* cgen,
Scope* scope,
Slot* slot, Slot* slot,
Register tmp); Register tmp);
Operand SlotOperand(Slot* slot, Register tmp) { Operand SlotOperand(Slot* slot, Register tmp) {
return SlotOperand(masm_, scope_, slot, tmp); return SlotOperand(this, slot, tmp);
} }
void LoadCondition(Expression* x, void LoadCondition(Expression* x,
...@@ -254,14 +256,14 @@ class Ia32CodeGenerator: public CodeGenerator { ...@@ -254,14 +256,14 @@ class Ia32CodeGenerator: public CodeGenerator {
void SetValue(Reference* ref) { void SetValue(Reference* ref) {
ASSERT(!has_cc()); ASSERT(!has_cc());
ASSERT(!ref->is_illegal()); ASSERT(!ref->is_illegal());
ref->expression()->GenerateStoreCode(masm_, scope_, ref, NOT_CONST_INIT); ref->expression()->GenerateStoreCode(this, ref, NOT_CONST_INIT);
} }
// Same as SetValue, used to set the initial value of a constant. // Same as SetValue, used to set the initial value of a constant.
void InitConst(Reference* ref) { void InitConst(Reference* ref) {
ASSERT(!has_cc()); ASSERT(!has_cc());
ASSERT(!ref->is_illegal()); ASSERT(!ref->is_illegal());
ref->expression()->GenerateStoreCode(masm_, scope_, ref, CONST_INIT); ref->expression()->GenerateStoreCode(this, ref, CONST_INIT);
} }
// Generate code to fetch a value from a property of a reference. The // Generate code to fetch a value from a property of a reference. The
...@@ -273,7 +275,7 @@ class Ia32CodeGenerator: public CodeGenerator { ...@@ -273,7 +275,7 @@ class Ia32CodeGenerator: public CodeGenerator {
// stored value is expected on top of the expression stack, with the // stored value is expected on top of the expression stack, with the
// reference immediately below it. The expression stack is left // reference immediately below it. The expression stack is left
// unchanged. // unchanged.
static void SetReferenceProperty(MacroAssembler* masm, static void SetReferenceProperty(CodeGenerator* cgen,
Reference* ref, Reference* ref,
Expression* key); Expression* key);
...@@ -425,7 +427,6 @@ CodeGenState::~CodeGenState() { ...@@ -425,7 +427,6 @@ CodeGenState::~CodeGenState() {
#define __ masm_-> #define __ masm_->
Handle<Code> Ia32CodeGenerator::MakeCode(FunctionLiteral* flit, Handle<Code> Ia32CodeGenerator::MakeCode(FunctionLiteral* flit,
Handle<Script> script, Handle<Script> script,
bool is_eval) { bool is_eval) {
...@@ -731,8 +732,10 @@ void Ia32CodeGenerator::GenCode(FunctionLiteral* fun) { ...@@ -731,8 +732,10 @@ void Ia32CodeGenerator::GenCode(FunctionLiteral* fun) {
} }
Operand Ia32CodeGenerator::SlotOperand(MacroAssembler* masm, #undef __
Scope* scope, #define __ masm->
Operand Ia32CodeGenerator::SlotOperand(CodeGenerator* cgen,
Slot* slot, Slot* slot,
Register tmp) { Register tmp) {
// Currently, this assertion will fail if we try to assign to // Currently, this assertion will fail if we try to assign to
...@@ -746,27 +749,29 @@ Operand Ia32CodeGenerator::SlotOperand(MacroAssembler* masm, ...@@ -746,27 +749,29 @@ Operand Ia32CodeGenerator::SlotOperand(MacroAssembler* masm,
ASSERT(slot != NULL); ASSERT(slot != NULL);
int index = slot->index(); int index = slot->index();
switch (slot->type()) { switch (slot->type()) {
case Slot::PARAMETER: return ParameterOperand(scope, index); case Slot::PARAMETER: return ParameterOperand(cgen, index);
case Slot::LOCAL: { case Slot::LOCAL: {
ASSERT(0 <= index && index < scope->num_stack_slots()); ASSERT(0 <= index && index < cgen->scope()->num_stack_slots());
const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset; const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset;
return Operand(ebp, kLocal0Offset - index * kPointerSize); return Operand(ebp, kLocal0Offset - index * kPointerSize);
} }
case Slot::CONTEXT: { case Slot::CONTEXT: {
MacroAssembler* masm = cgen->masm();
// Follow the context chain if necessary. // Follow the context chain if necessary.
ASSERT(!tmp.is(esi)); // do not overwrite context register ASSERT(!tmp.is(esi)); // do not overwrite context register
Register context = esi; Register context = esi;
int chain_length = scope->ContextChainLength(slot->var()->scope()); int chain_length =
cgen->scope()->ContextChainLength(slot->var()->scope());
for (int i = chain_length; i-- > 0;) { for (int i = chain_length; i-- > 0;) {
// Load the closure. // Load the closure.
// (All contexts, even 'with' contexts, have a closure, // (All contexts, even 'with' contexts, have a closure,
// and it is the same for all contexts inside a function. // and it is the same for all contexts inside a function.
// There is no need to go to the function context first.) // There is no need to go to the function context first.)
masm->mov(tmp, ContextOperand(context, Context::CLOSURE_INDEX)); __ mov(tmp, ContextOperand(context, Context::CLOSURE_INDEX));
// Load the function context (which is the incoming, outer context). // Load the function context (which is the incoming, outer context).
masm->mov(tmp, FieldOperand(tmp, JSFunction::kContextOffset)); __ mov(tmp, FieldOperand(tmp, JSFunction::kContextOffset));
context = tmp; context = tmp;
} }
// We may have a 'with' context now. Get the function context. // We may have a 'with' context now. Get the function context.
...@@ -776,7 +781,7 @@ Operand Ia32CodeGenerator::SlotOperand(MacroAssembler* masm, ...@@ -776,7 +781,7 @@ Operand Ia32CodeGenerator::SlotOperand(MacroAssembler* masm,
// cause the function context of a function context is itself. Before // cause the function context of a function context is itself. Before
// deleting this mov we should try to create a counter-example first, // deleting this mov we should try to create a counter-example first,
// though...) // though...)
masm->mov(tmp, ContextOperand(context, Context::FCONTEXT_INDEX)); __ mov(tmp, ContextOperand(context, Context::FCONTEXT_INDEX));
return ContextOperand(tmp, index); return ContextOperand(tmp, index);
} }
...@@ -787,6 +792,9 @@ Operand Ia32CodeGenerator::SlotOperand(MacroAssembler* masm, ...@@ -787,6 +792,9 @@ Operand Ia32CodeGenerator::SlotOperand(MacroAssembler* masm,
} }
#undef __
#define __ masm_->
// Loads a value on TOS. If it is a boolean value, the result may have been // Loads a value on TOS. If it is a boolean value, the result may have been
// (partially) translated into branches, or it may have set the condition code // (partially) translated into branches, or it may have set the condition code
// register. If force_cc is set, the value is forced to set the condition code // register. If force_cc is set, the value is forced to set the condition code
...@@ -951,49 +959,52 @@ void Ia32CodeGenerator::UnloadReference(Reference* ref) { ...@@ -951,49 +959,52 @@ void Ia32CodeGenerator::UnloadReference(Reference* ref) {
} }
void Property::GenerateStoreCode(MacroAssembler* masm, #undef __
Scope* scope, #define __ masm->
void Property::GenerateStoreCode(CodeGenerator* cgen,
Reference* ref, Reference* ref,
InitState init_state) { InitState init_state) {
MacroAssembler* masm = cgen->masm();
Comment cmnt(masm, "[ Store to Property"); Comment cmnt(masm, "[ Store to Property");
masm->RecordPosition(position()); __ RecordPosition(position());
Ia32CodeGenerator::SetReferenceProperty(masm, ref, key()); Ia32CodeGenerator::SetReferenceProperty(cgen, ref, key());
} }
void VariableProxy::GenerateStoreCode(MacroAssembler* masm, void VariableProxy::GenerateStoreCode(CodeGenerator* cgen,
Scope* scope,
Reference* ref, Reference* ref,
InitState init_state) { InitState init_state) {
MacroAssembler* masm = cgen->masm();
Comment cmnt(masm, "[ Store to VariableProxy"); Comment cmnt(masm, "[ Store to VariableProxy");
Variable* node = var(); Variable* node = var();
Expression* expr = node->rewrite(); Expression* expr = node->rewrite();
if (expr != NULL) { if (expr != NULL) {
expr->GenerateStoreCode(masm, scope, ref, init_state); expr->GenerateStoreCode(cgen, ref, init_state);
} else { } else {
ASSERT(node->is_global()); ASSERT(node->is_global());
if (node->AsProperty() != NULL) { if (node->AsProperty() != NULL) {
masm->RecordPosition(node->AsProperty()->position()); __ RecordPosition(node->AsProperty()->position());
} }
Ia32CodeGenerator::SetReferenceProperty(masm, ref, Expression* key = new Literal(node->name());
new Literal(node->name())); Ia32CodeGenerator::SetReferenceProperty(cgen, ref, key);
} }
} }
void Slot::GenerateStoreCode(MacroAssembler* masm, void Slot::GenerateStoreCode(CodeGenerator* cgen,
Scope* scope,
Reference* ref, Reference* ref,
InitState init_state) { InitState init_state) {
MacroAssembler* masm = cgen->masm();
Comment cmnt(masm, "[ Store to Slot"); Comment cmnt(masm, "[ Store to Slot");
if (type() == Slot::LOOKUP) { if (type() == Slot::LOOKUP) {
ASSERT(var()->mode() == Variable::DYNAMIC); ASSERT(var()->mode() == Variable::DYNAMIC);
// For now, just do a runtime call. // For now, just do a runtime call.
masm->push(Operand(esi)); __ push(esi);
masm->push(Immediate(var()->name())); __ push(Immediate(var()->name()));
if (init_state == CONST_INIT) { if (init_state == CONST_INIT) {
// Same as the case for a normal store, but ignores attribute // Same as the case for a normal store, but ignores attribute
...@@ -1010,13 +1021,13 @@ void Slot::GenerateStoreCode(MacroAssembler* masm, ...@@ -1010,13 +1021,13 @@ void Slot::GenerateStoreCode(MacroAssembler* masm,
// the expression operands are defined and valid, and thus we need the // the expression operands are defined and valid, and thus we need the
// split into 2 operations: declaration of the context slot followed // split into 2 operations: declaration of the context slot followed
// by initialization. // by initialization.
masm->CallRuntime(Runtime::kInitializeConstContextSlot, 3); __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
} else { } else {
masm->CallRuntime(Runtime::kStoreContextSlot, 3); __ CallRuntime(Runtime::kStoreContextSlot, 3);
} }
// Storing a variable must keep the (new) value on the expression // Storing a variable must keep the (new) value on the expression
// stack. This is necessary for compiling assignment expressions. // stack. This is necessary for compiling assignment expressions.
masm->push(eax); __ push(eax);
} else { } else {
ASSERT(var()->mode() != Variable::DYNAMIC); ASSERT(var()->mode() != Variable::DYNAMIC);
...@@ -1028,9 +1039,9 @@ void Slot::GenerateStoreCode(MacroAssembler* masm, ...@@ -1028,9 +1039,9 @@ void Slot::GenerateStoreCode(MacroAssembler* masm,
// still contains 'the hole' value). When the assignment is executed, // still contains 'the hole' value). When the assignment is executed,
// the code is identical to a normal store (see below). // the code is identical to a normal store (see below).
Comment cmnt(masm, "[ Init const"); Comment cmnt(masm, "[ Init const");
masm->mov(eax, Ia32CodeGenerator::SlotOperand(masm, scope, this, ecx)); __ mov(eax, Ia32CodeGenerator::SlotOperand(cgen, this, ecx));
masm->cmp(eax, Factory::the_hole_value()); __ cmp(eax, Factory::the_hole_value());
masm->j(not_equal, &exit); __ j(not_equal, &exit);
} }
// We must execute the store. // We must execute the store.
...@@ -1042,24 +1053,21 @@ void Slot::GenerateStoreCode(MacroAssembler* masm, ...@@ -1042,24 +1053,21 @@ void Slot::GenerateStoreCode(MacroAssembler* masm,
// Variable::CONST because of const declarations which will initialize // Variable::CONST because of const declarations which will initialize
// consts to 'the hole' value and by doing so, end up calling this // consts to 'the hole' value and by doing so, end up calling this
// code. // code.
masm->pop(eax); __ pop(eax);
masm->mov(Ia32CodeGenerator::SlotOperand(masm, scope, this, ecx), eax); __ mov(Ia32CodeGenerator::SlotOperand(cgen, this, ecx), eax);
masm->push(eax); // RecordWrite may destroy the value in eax. __ push(eax); // RecordWrite may destroy the value in eax.
if (type() == Slot::CONTEXT) { if (type() == Slot::CONTEXT) {
// ecx is loaded with context when calling SlotOperand above. // ecx is loaded with context when calling SlotOperand above.
int offset = FixedArray::kHeaderSize + index() * kPointerSize; int offset = FixedArray::kHeaderSize + index() * kPointerSize;
masm->RecordWrite(ecx, offset, eax, ebx); __ RecordWrite(ecx, offset, eax, ebx);
} }
// If we definitely did not jump over the assignment, we do not need to // If we definitely did not jump over the assignment, we do not need to
// bind the exit label. Doing so can defeat peephole optimization. // bind the exit label. Doing so can defeat peephole optimization.
if (init_state == CONST_INIT) masm->bind(&exit); if (init_state == CONST_INIT) __ bind(&exit);
} }
} }
#undef __
#define __ masm->
class ToBooleanStub: public CodeStub { class ToBooleanStub: public CodeStub {
public: public:
ToBooleanStub() { } ToBooleanStub() { }
...@@ -1138,10 +1146,10 @@ void ToBooleanStub::Generate(MacroAssembler* masm) { ...@@ -1138,10 +1146,10 @@ void ToBooleanStub::Generate(MacroAssembler* masm) {
__ ret(1 * kPointerSize); __ ret(1 * kPointerSize);
} }
#undef __ #undef __
#define __ masm_-> #define __ masm_->
// ECMA-262, section 9.2, page 30: ToBoolean(). Pop the top of stack and // ECMA-262, section 9.2, page 30: ToBoolean(). Pop the top of stack and
// convert it to a boolean in the condition code register or jump to // convert it to a boolean in the condition code register or jump to
// 'false_target'/'true_target' as appropriate. // 'false_target'/'true_target' as appropriate.
...@@ -1226,13 +1234,16 @@ void Ia32CodeGenerator::GetReferenceProperty(Expression* key) { ...@@ -1226,13 +1234,16 @@ void Ia32CodeGenerator::GetReferenceProperty(Expression* key) {
} }
void Ia32CodeGenerator::SetReferenceProperty(MacroAssembler* masm, #undef __
#define __ masm->
void Ia32CodeGenerator::SetReferenceProperty(CodeGenerator* cgen,
Reference* ref, Reference* ref,
Expression* key) { Expression* key) {
ASSERT(!ref->is_illegal()); ASSERT(!ref->is_illegal());
Reference::Type type = ref->type(); MacroAssembler* masm = cgen->masm();
if (type == Reference::NAMED) { if (ref->type() == Reference::NAMED) {
// Compute the name of the property. // Compute the name of the property.
Literal* literal = key->AsLiteral(); Literal* literal = key->AsLiteral();
Handle<String> name(String::cast(*literal->handle())); Handle<String> name(String::cast(*literal->handle()));
...@@ -1240,28 +1251,24 @@ void Ia32CodeGenerator::SetReferenceProperty(MacroAssembler* masm, ...@@ -1240,28 +1251,24 @@ void Ia32CodeGenerator::SetReferenceProperty(MacroAssembler* masm,
// Call the appropriate IC code. // Call the appropriate IC code.
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
// TODO(1222589): Make the IC grab the values from the stack. // TODO(1222589): Make the IC grab the values from the stack.
masm->pop(eax); __ pop(eax);
// Setup the name register. // Setup the name register.
masm->Set(ecx, Immediate(name)); __ Set(ecx, Immediate(name));
masm->call(ic, RelocInfo::CODE_TARGET); __ call(ic, RelocInfo::CODE_TARGET);
} else { } else {
// Access keyed property. // Access keyed property.
ASSERT(type == Reference::KEYED); ASSERT(ref->type() == Reference::KEYED);
// Call IC code. // Call IC code.
Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
// TODO(1222589): Make the IC grab the values from the stack. // TODO(1222589): Make the IC grab the values from the stack.
masm->pop(eax); __ pop(eax);
masm->call(ic, RelocInfo::CODE_TARGET); __ call(ic, RelocInfo::CODE_TARGET);
} }
masm->push(eax); // IC call leaves result in eax, push it out __ push(eax); // IC call leaves result in eax, push it out
} }
#undef __
#define __ masm->
class FloatingPointHelper : public AllStatic { class FloatingPointHelper : public AllStatic {
public: public:
// Code pattern for loading floating point values. Input values must // Code pattern for loading floating point values. Input values must
...@@ -1771,10 +1778,6 @@ void FloatingPointHelper::CheckFloatOperands(MacroAssembler* masm, ...@@ -1771,10 +1778,6 @@ void FloatingPointHelper::CheckFloatOperands(MacroAssembler* masm,
} }
#undef __
#define __ masm->
void UnarySubStub::Generate(MacroAssembler* masm) { void UnarySubStub::Generate(MacroAssembler* masm) {
Label undo; Label undo;
Label slow; Label slow;
...@@ -1827,7 +1830,7 @@ void UnarySubStub::Generate(MacroAssembler* masm) { ...@@ -1827,7 +1830,7 @@ void UnarySubStub::Generate(MacroAssembler* masm) {
__ bind(&done); __ bind(&done);
masm->StubReturn(1); __ StubReturn(1);
} }
...@@ -1928,7 +1931,6 @@ void ArgumentsAccessStub::Generate(MacroAssembler* masm) { ...@@ -1928,7 +1931,6 @@ void ArgumentsAccessStub::Generate(MacroAssembler* masm) {
#undef __ #undef __
#define __ masm_-> #define __ masm_->
void Ia32CodeGenerator::GenericBinaryOperation(Token::Value op, void Ia32CodeGenerator::GenericBinaryOperation(Token::Value op,
OverwriteMode overwrite_mode) { OverwriteMode overwrite_mode) {
Comment cmnt(masm_, "[ BinaryOperation"); Comment cmnt(masm_, "[ BinaryOperation");
...@@ -2483,7 +2485,6 @@ void StackCheckStub::Generate(MacroAssembler* masm) { ...@@ -2483,7 +2485,6 @@ void StackCheckStub::Generate(MacroAssembler* masm) {
#undef __ #undef __
#define __ masm_-> #define __ masm_->
void Ia32CodeGenerator::Comparison(Condition cc, bool strict) { void Ia32CodeGenerator::Comparison(Condition cc, bool strict) {
// Strict only makes sense for equality comparisons. // Strict only makes sense for equality comparisons.
ASSERT(!strict || cc == equal); ASSERT(!strict || cc == equal);
...@@ -2592,36 +2593,42 @@ class CallFunctionStub: public CodeStub { ...@@ -2592,36 +2593,42 @@ class CallFunctionStub: public CodeStub {
}; };
#undef __
#define __ masm->
void CallFunctionStub::Generate(MacroAssembler* masm) { void CallFunctionStub::Generate(MacroAssembler* masm) {
Label slow; Label slow;
// Get the function to call from the stack. // Get the function to call from the stack.
// +2 ~ receiver, return address // +2 ~ receiver, return address
masm->mov(edi, Operand(esp, (argc_ + 2) * kPointerSize)); __ mov(edi, Operand(esp, (argc_ + 2) * kPointerSize));
// Check that the function really is a JavaScript function. // Check that the function really is a JavaScript function.
masm->test(edi, Immediate(kSmiTagMask)); __ test(edi, Immediate(kSmiTagMask));
masm->j(zero, &slow, not_taken); __ j(zero, &slow, not_taken);
// Get the map. // Get the map.
masm->mov(ecx, FieldOperand(edi, HeapObject::kMapOffset)); __ mov(ecx, FieldOperand(edi, HeapObject::kMapOffset));
masm->movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
masm->cmp(ecx, JS_FUNCTION_TYPE); __ cmp(ecx, JS_FUNCTION_TYPE);
masm->j(not_equal, &slow, not_taken); __ j(not_equal, &slow, not_taken);
// Fast-case: Just invoke the function. // Fast-case: Just invoke the function.
ParameterCount actual(argc_); ParameterCount actual(argc_);
masm->InvokeFunction(edi, actual, JUMP_FUNCTION); __ InvokeFunction(edi, actual, JUMP_FUNCTION);
// Slow-case: Non-function called. // Slow-case: Non-function called.
masm->bind(&slow); __ bind(&slow);
masm->Set(eax, Immediate(argc_)); __ Set(eax, Immediate(argc_));
masm->Set(ebx, Immediate(0)); __ Set(ebx, Immediate(0));
masm->GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION); __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION);
Handle<Code> adaptor(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)); Handle<Code> adaptor(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline));
masm->jmp(adaptor, RelocInfo::CODE_TARGET); __ jmp(adaptor, RelocInfo::CODE_TARGET);
} }
#undef __
#define __ masm_->
// Call the function just below TOS on the stack with the given // Call the function just below TOS on the stack with the given
// arguments. The receiver is the TOS. // arguments. The receiver is the TOS.
void Ia32CodeGenerator::CallWithArguments(ZoneList<Expression*>* args, void Ia32CodeGenerator::CallWithArguments(ZoneList<Expression*>* args,
...@@ -4630,7 +4637,6 @@ class CountOperationDeferred: public DeferredCode { ...@@ -4630,7 +4637,6 @@ class CountOperationDeferred: public DeferredCode {
#undef __ #undef __
#define __ masm-> #define __ masm->
class RevertToNumberStub: public CodeStub { class RevertToNumberStub: public CodeStub {
public: public:
explicit RevertToNumberStub(bool is_increment) explicit RevertToNumberStub(bool is_increment)
...@@ -4735,7 +4741,6 @@ void CounterOpStub::Generate(MacroAssembler* masm) { ...@@ -4735,7 +4741,6 @@ void CounterOpStub::Generate(MacroAssembler* masm) {
#undef __ #undef __
#define __ masm_-> #define __ masm_->
void CountOperationDeferred::Generate() { void CountOperationDeferred::Generate() {
if (is_postfix_) { if (is_postfix_) {
RevertToNumberStub to_number_stub(is_increment_); RevertToNumberStub to_number_stub(is_increment_);
...@@ -5173,7 +5178,6 @@ void Ia32CodeGenerator::ExitJSFrame() { ...@@ -5173,7 +5178,6 @@ void Ia32CodeGenerator::ExitJSFrame() {
#undef __ #undef __
#define __ masm-> #define __ masm->
void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
ASSERT(StackHandlerConstants::kSize == 6 * kPointerSize); // adjust this code ASSERT(StackHandlerConstants::kSize == 6 * kPointerSize); // adjust this code
ExternalReference handler_address(Top::k_handler_address); ExternalReference handler_address(Top::k_handler_address);
......
...@@ -123,6 +123,7 @@ class CodeGenerator: public Visitor { ...@@ -123,6 +123,7 @@ class CodeGenerator: public Visitor {
virtual MacroAssembler* masm() = 0; virtual MacroAssembler* masm() = 0;
virtual Scope* scope() const = 0;
void AddDeferred(DeferredCode* code) { deferred_.Add(code); } void AddDeferred(DeferredCode* code) { deferred_.Add(code); }
void ProcessDeferred(); void ProcessDeferred();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment