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