Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(297)

Unified Diff: src/codegen-ia32.cc

Issue 6538: Moved the function GetValue from the code generator to the Reference... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 12 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« src/codegen-arm.cc ('K') | « src/codegen-arm.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/codegen-ia32.cc
===================================================================
--- src/codegen-ia32.cc (revision 461)
+++ src/codegen-ia32.cc (working copy)
@@ -57,6 +57,7 @@
// on the execution stack to represent the reference.
enum InitState { CONST_INIT, NOT_CONST_INIT };
+enum TypeofState { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF };
class Reference BASE_EMBEDDED {
public:
@@ -79,6 +80,18 @@
bool is_slot() const { return type_ == SLOT; }
bool is_property() const { return type_ == NAMED || type_ == KEYED; }
+ // Return the name. Only valid for named property references.
+ Handle<String> GetName();
+
+ // Generate code to push the value of the reference on top of the
+ // expression stack. The reference is expected to be already on top of
+ // the expression stack, and it is left in place with its value above it.
+ void GetValue(TypeofState typeof_state);
+
+ // Generate code to store the value on top of the expression stack in the
+ // reference. The reference is expected to be immediately below the value
+ // on the expression stack. The stored value is left in place (with the
+ // reference intact below it) to support chained assignments.
void SetValue(InitState init_state);
private:
@@ -98,42 +111,29 @@
class CodeGenState BASE_EMBEDDED {
public:
- enum AccessType {
- UNDEFINED,
- LOAD,
- LOAD_TYPEOF_EXPR
- };
-
// Create an initial code generator state. Destroying the initial state
// leaves the code generator with a NULL state.
explicit CodeGenState(Ia32CodeGenerator* owner);
// Create a code generator state based on a code generator's current
- // state. The new state has its own access type and pair of branch
- // labels, and no reference.
+ // state. The new state has its own typeof state and pair of branch
+ // labels.
CodeGenState(Ia32CodeGenerator* owner,
- AccessType access,
+ TypeofState typeof_state,
Label* true_target,
Label* false_target);
- // Create a code generator state based on a code generator's current
- // state. The new state has an access type of LOAD, its own reference,
- // and inherits the pair of branch labels of the current state.
- CodeGenState(Ia32CodeGenerator* owner, Reference* ref);
-
// Destroy a code generator state and restore the owning code generator's
// previous state.
~CodeGenState();
- AccessType access() const { return access_; }
- Reference* ref() const { return ref_; }
+ TypeofState typeof_state() const { return typeof_state_; }
Label* true_target() const { return true_target_; }
Label* false_target() const { return false_target_; }
private:
Ia32CodeGenerator* owner_;
- AccessType access_;
- Reference* ref_;
+ TypeofState typeof_state_;
Label* true_target_;
Label* false_target_;
CodeGenState* previous_;
@@ -185,9 +185,7 @@
// State
bool has_cc() const { return cc_reg_ >= 0; }
- CodeGenState::AccessType access() const { return state_->access(); }
- Reference* ref() const { return state_->ref(); }
- bool is_referenced() const { return state_->ref() != NULL; }
+ TypeofState typeof_state() const { return state_->typeof_state(); }
Label* true_target() const { return state_->true_target(); }
Label* false_target() const { return state_->false_target(); }
@@ -216,14 +214,16 @@
Operand SlotOperand(Slot* slot, Register tmp);
void LoadCondition(Expression* x,
- CodeGenState::AccessType access,
+ TypeofState typeof_state,
Label* true_target,
Label* false_target,
bool force_cc);
- void Load(Expression* x,
- CodeGenState::AccessType access = CodeGenState::LOAD);
+ void Load(Expression* x, TypeofState typeof_state = NOT_INSIDE_TYPEOF);
void LoadGlobal();
+ // Read a value from a slot and leave it on top of the expression stack.
+ void LoadFromSlot(Slot* slot, TypeofState typeof_state);
+
// Special code for typeof expressions: Unfortunately, we must
// be careful when loading the expression in 'typeof'
// expressions. We are not allowed to throw reference errors for
@@ -232,23 +232,6 @@
// through the context chain.
void LoadTypeofExpression(Expression* x);
- // References
-
- // Generate code to fetch the value of a reference. The reference is
- // expected to be on top of the expression stack. It is left in place and
- // its value is pushed on top of it.
- void GetValue(Reference* ref) {
- ASSERT(!has_cc());
- ASSERT(!ref->is_illegal());
- CodeGenState new_state(this, ref);
- Visit(ref->expression());
- }
-
- // Generate code to fetch a value from a property of a reference. The
- // reference is expected on top of the expression stack. It is left in
- // place and its value is pushed on top of it.
- void GetReferenceProperty(Expression* key);
-
void ToBoolean(Label* true_target, Label* false_target);
void GenericBinaryOperation(
@@ -340,8 +323,7 @@
CodeGenState::CodeGenState(Ia32CodeGenerator* owner)
: owner_(owner),
- access_(UNDEFINED),
- ref_(NULL),
+ typeof_state_(NOT_INSIDE_TYPEOF),
true_target_(NULL),
false_target_(NULL),
previous_(NULL) {
@@ -350,12 +332,11 @@
CodeGenState::CodeGenState(Ia32CodeGenerator* owner,
- AccessType access,
+ TypeofState typeof_state,
Label* true_target,
Label* false_target)
: owner_(owner),
- access_(access),
- ref_(NULL),
+ typeof_state_(typeof_state),
true_target_(true_target),
false_target_(false_target),
previous_(owner->state()) {
@@ -363,17 +344,6 @@
}
-CodeGenState::CodeGenState(Ia32CodeGenerator* owner, Reference* ref)
- : owner_(owner),
- access_(LOAD),
- ref_(ref),
- true_target_(owner->state()->true_target_),
- false_target_(owner->state()->false_target_),
- previous_(owner->state()) {
- owner_->set_state(this);
-}
-
-
CodeGenState::~CodeGenState() {
ASSERT(owner_->state() == this);
owner_->set_state(previous_);
@@ -759,15 +729,13 @@
// register and no value is pushed. If the condition code register was set,
// has_cc() is true and cc_reg_ contains the condition to test for 'true'.
void Ia32CodeGenerator::LoadCondition(Expression* x,
- CodeGenState::AccessType access,
+ TypeofState typeof_state,
Label* true_target,
Label* false_target,
bool force_cc) {
- ASSERT(access == CodeGenState::LOAD ||
- access == CodeGenState::LOAD_TYPEOF_EXPR);
- ASSERT(!has_cc() && !is_referenced());
+ ASSERT(!has_cc());
- { CodeGenState new_state(this, access, true_target, false_target);
+ { CodeGenState new_state(this, typeof_state, true_target, false_target);
Visit(x);
}
if (force_cc && !has_cc()) {
@@ -777,13 +745,10 @@
}
-void Ia32CodeGenerator::Load(Expression* x, CodeGenState::AccessType access) {
- ASSERT(access == CodeGenState::LOAD ||
- access == CodeGenState::LOAD_TYPEOF_EXPR);
-
+void Ia32CodeGenerator::Load(Expression* x, TypeofState typeof_state) {
Label true_target;
Label false_target;
- LoadCondition(x, access, &true_target, &false_target, false);
+ LoadCondition(x, typeof_state, &true_target, &false_target, false);
if (has_cc()) {
// convert cc_reg_ into a bool
@@ -832,8 +797,8 @@
// TODO(1241834): Get rid of this function in favor of just using Load, now
-// that we have the LOAD_TYPEOF_EXPR access type. => Need to handle
-// global variables w/o reference errors elsewhere.
+// that we have the INSIDE_TYPEOF typeof state. => Need to handle global
+// variables w/o reference errors elsewhere.
void Ia32CodeGenerator::LoadTypeofExpression(Expression* x) {
Variable* variable = x->AsVariableProxy()->AsVariable();
if (variable != NULL && !variable->is_this() && variable->is_global()) {
@@ -847,7 +812,7 @@
Property property(&global, &key, RelocInfo::kNoPosition);
Load(&property);
} else {
- Load(x, CodeGenState::LOAD_TYPEOF_EXPR);
+ Load(x, INSIDE_TYPEOF);
}
}
@@ -864,6 +829,7 @@
void Ia32CodeGenerator::LoadReference(Reference* ref) {
+ Comment cmnt(masm_, "[ LoadReference");
Expression* e = ref->expression();
Property* property = e->AsProperty();
Variable* var = e->AsVariableProxy()->AsVariable();
@@ -905,7 +871,7 @@
void Ia32CodeGenerator::UnloadReference(Reference* ref) {
- // Pop n references on the stack while preserving TOS
+ // Pop a reference from the stack while preserving TOS.
Comment cmnt(masm_, "[ UnloadReference");
int size = ref->size();
if (size <= 0) {
@@ -985,47 +951,6 @@
}
-void Ia32CodeGenerator::GetReferenceProperty(Expression* key) {
- ASSERT(!ref()->is_illegal());
-
- // TODO(1241834): Make sure that this it is safe to ignore the distinction
- // between access types LOAD and LOAD_TYPEOF_EXPR. If there is a chance
- // that reference errors can be thrown below, we must distinguish between
- // the two kinds of loads (typeof expression loads must not throw a
- // reference error).
- if (ref()->type() == Reference::NAMED) {
- // Compute the name of the property.
- Literal* literal = key->AsLiteral();
- Handle<String> name(String::cast(*literal->handle()));
-
- Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
- Variable* var = ref()->expression()->AsVariableProxy()->AsVariable();
- // Setup the name register.
- __ Set(ecx, Immediate(name));
- if (var != NULL) {
- ASSERT(var->is_global());
- __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
- } else {
- __ call(ic, RelocInfo::CODE_TARGET);
- }
- } else {
- // Access keyed property.
- ASSERT(ref()->type() == Reference::KEYED);
-
- // Call IC code.
- Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
- Variable* var = ref()->expression()->AsVariableProxy()->AsVariable();
- if (var != NULL) {
- ASSERT(var->is_global());
- __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
- } else {
- __ call(ic, RelocInfo::CODE_TARGET);
- }
- }
- __ push(eax); // IC call leaves result in eax, push it out
-}
-
-
class FloatingPointHelper : public AllStatic {
public:
// Code pattern for loading floating point values. Input values must
@@ -1676,7 +1601,9 @@
void Ia32CodeGenerator::CallWithArguments(ZoneList<Expression*>* args,
int position) {
// Push the arguments ("left-to-right") on the stack.
- for (int i = 0; i < args->length(); i++) Load(args->at(i));
+ for (int i = 0; i < args->length(); i++) {
+ Load(args->at(i));
+ }
iposva 2008/10/07 19:43:31 Thanks!
// Record the position for debugging purposes.
__ RecordPosition(position);
@@ -1821,7 +1748,7 @@
Label then;
Label else_;
// if (cond)
- LoadCondition(node->condition(), CodeGenState::LOAD, &then, &else_, true);
+ LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &else_, true);
Branch(false, &else_);
// then
__ bind(&then);
@@ -1835,7 +1762,7 @@
ASSERT(!has_else_stm);
Label then;
// if (cond)
- LoadCondition(node->condition(), CodeGenState::LOAD, &then, &exit, true);
+ LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &exit, true);
Branch(false, &exit);
// then
__ bind(&then);
@@ -1845,7 +1772,7 @@
ASSERT(!has_then_stm);
Label else_;
// if (!cond)
- LoadCondition(node->condition(), CodeGenState::LOAD, &exit, &else_, true);
+ LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &exit, &else_, true);
Branch(true, &exit);
// else
__ bind(&else_);
@@ -1854,7 +1781,7 @@
} else {
ASSERT(!has_then_stm && !has_else_stm);
// if (cond)
- LoadCondition(node->condition(), CodeGenState::LOAD, &exit, &exit, false);
+ LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &exit, &exit, false);
if (has_cc()) {
cc_reg_ = no_condition;
} else {
@@ -2139,7 +2066,7 @@
case ALWAYS_FALSE:
break;
case DONT_KNOW:
- LoadCondition(node->cond(), CodeGenState::LOAD, &loop,
+ LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &loop,
node->break_target(), true);
Branch(true, &loop);
break;
@@ -2608,78 +2535,71 @@
void Ia32CodeGenerator::VisitConditional(Conditional* node) {
Comment cmnt(masm_, "[ Conditional");
Label then, else_, exit;
- LoadCondition(node->condition(), CodeGenState::LOAD, &then, &else_, true);
+ LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &else_, true);
Branch(false, &else_);
__ bind(&then);
- Load(node->then_expression(), access());
+ Load(node->then_expression(), typeof_state());
__ jmp(&exit);
__ bind(&else_);
- Load(node->else_expression(), access());
+ Load(node->else_expression(), typeof_state());
__ bind(&exit);
}
-void Ia32CodeGenerator::VisitSlot(Slot* node) {
- ASSERT(access() != CodeGenState::UNDEFINED);
- Comment cmnt(masm_, "[ Slot");
+void Ia32CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
+ if (slot->type() == Slot::LOOKUP) {
+ ASSERT(slot->var()->mode() == Variable::DYNAMIC);
- if (node->type() == Slot::LOOKUP) {
- ASSERT(node->var()->mode() == Variable::DYNAMIC);
-
// For now, just do a runtime call.
- __ push(Operand(esi));
- __ push(Immediate(node->var()->name()));
+ __ push(esi);
+ __ push(Immediate(slot->var()->name()));
- if (access() == CodeGenState::LOAD) {
- __ CallRuntime(Runtime::kLoadContextSlot, 2);
- } else {
- ASSERT(access() == CodeGenState::LOAD_TYPEOF_EXPR);
+ if (typeof_state == INSIDE_TYPEOF) {
__ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
+ } else {
+ __ CallRuntime(Runtime::kLoadContextSlot, 2);
}
__ push(eax);
} else {
// Note: We would like to keep the assert below, but it fires because of
// some nasty code in LoadTypeofExpression() which should be removed...
- // ASSERT(node->var()->mode() != Variable::DYNAMIC);
-
- if (node->var()->mode() == Variable::CONST) {
+ // ASSERT(slot->var()->mode() != Variable::DYNAMIC);
+ if (slot->var()->mode() == Variable::CONST) {
// Const slots may contain 'the hole' value (the constant hasn't been
// initialized yet) which needs to be converted into the 'undefined'
// value.
Comment cmnt(masm_, "[ Load const");
- Label L;
- __ mov(eax, SlotOperand(node, ecx));
+ Label exit;
+ __ mov(eax, SlotOperand(slot, ecx));
__ cmp(eax, Factory::the_hole_value());
- __ j(not_equal, &L);
+ __ j(not_equal, &exit);
__ mov(eax, Factory::undefined_value());
- __ bind(&L);
+ __ bind(&exit);
__ push(eax);
} else {
- __ push(SlotOperand(node, ecx));
+ __ push(SlotOperand(slot, ecx));
}
}
}
+void Ia32CodeGenerator::VisitSlot(Slot* node) {
+ Comment cmnt(masm_, "[ Slot");
+ LoadFromSlot(node, typeof_state());
+}
+
+
void Ia32CodeGenerator::VisitVariableProxy(VariableProxy* node) {
Comment cmnt(masm_, "[ VariableProxy");
- Variable* var_node = node->var();
-
- Expression* expr = var_node->rewrite();
+ Variable* var = node->var();
+ Expression* expr = var->rewrite();
if (expr != NULL) {
Visit(expr);
} else {
- ASSERT(var_node->is_global());
- if (is_referenced()) {
- if (var_node->AsProperty() != NULL) {
- __ RecordPosition(var_node->AsProperty()->position());
- }
- GetReferenceProperty(new Literal(var_node->name()));
- } else {
- Reference property(this, node);
- GetValue(&property);
- }
+ ASSERT(var->is_global());
+ Reference ref(this, node);
+ ref.GetValue(typeof_state());
}
}
@@ -2942,7 +2862,7 @@
Load(node->value());
} else {
- GetValue(&target);
+ target.GetValue(NOT_INSIDE_TYPEOF);
Literal* literal = node->value()->AsLiteral();
if (IsInlineSmi(literal)) {
SmiOperation(node->binary_op(), literal->handle(), false, NO_OVERWRITE);
@@ -2983,15 +2903,8 @@
void Ia32CodeGenerator::VisitProperty(Property* node) {
Comment cmnt(masm_, "[ Property");
-
- if (is_referenced()) {
- __ RecordPosition(node->position());
- GetReferenceProperty(node->key());
- } else {
- Reference property(this, node);
- __ RecordPosition(node->position());
- GetValue(&property);
- }
+ Reference property(this, node);
+ property.GetValue(typeof_state());
}
@@ -3090,7 +3003,7 @@
// Load the function to call from the property through a reference.
Reference ref(this, property);
- GetValue(&ref);
+ ref.GetValue(NOT_INSIDE_TYPEOF);
// Pass receiver to called function.
// The reference's size is non-negative.
@@ -3456,7 +3369,7 @@
Token::Value op = node->op();
if (op == Token::NOT) {
- LoadCondition(node->expression(), CodeGenState::LOAD,
+ LoadCondition(node->expression(), NOT_INSIDE_TYPEOF,
false_target(), true_target(), true);
cc_reg_ = NegateCondition(cc_reg_);
@@ -3677,7 +3590,7 @@
{ Reference target(this, node->expression());
if (target.is_illegal()) return;
- GetValue(&target);
+ target.GetValue(NOT_INSIDE_TYPEOF);
int result_offset = target.size() * kPointerSize;
CountOperationDeferred* deferred =
@@ -3732,14 +3645,14 @@
if (op == Token::AND) {
Label is_true;
- LoadCondition(node->left(), CodeGenState::LOAD, &is_true,
+ LoadCondition(node->left(), NOT_INSIDE_TYPEOF, &is_true,
false_target(), false);
if (has_cc()) {
Branch(false, false_target());
// Evaluate right side expression.
__ bind(&is_true);
- LoadCondition(node->right(), CodeGenState::LOAD, true_target(),
+ LoadCondition(node->right(), NOT_INSIDE_TYPEOF, true_target(),
false_target(), false);
} else {
@@ -3768,14 +3681,14 @@
} else if (op == Token::OR) {
Label is_false;
- LoadCondition(node->left(), CodeGenState::LOAD, true_target(),
+ LoadCondition(node->left(), NOT_INSIDE_TYPEOF, true_target(),
&is_false, false);
if (has_cc()) {
Branch(true, true_target());
// Evaluate right side expression.
__ bind(&is_false);
- LoadCondition(node->right(), CodeGenState::LOAD, true_target(),
+ LoadCondition(node->right(), NOT_INSIDE_TYPEOF, true_target(),
false_target(), false);
} else {
@@ -4090,6 +4003,87 @@
#undef __
#define __ masm->
+Handle<String> Reference::GetName() {
+ ASSERT(type_ == NAMED);
+ Property* property = expression_->AsProperty();
+ if (property == NULL) {
+ // Global variable reference treated as a named property reference.
+ VariableProxy* proxy = expression_->AsVariableProxy();
+ ASSERT(proxy->AsVariable() != NULL);
+ ASSERT(proxy->AsVariable()->is_global());
+ return proxy->name();
+ } else {
+ MacroAssembler* masm = cgen_->masm();
+ __ RecordPosition(property->position());
+ Literal* raw_name = property->key()->AsLiteral();
+ ASSERT(raw_name != NULL);
+ return Handle<String>(String::cast(*raw_name->handle()));
+ }
+}
+
+
+void Reference::GetValue(TypeofState typeof_state) {
+ ASSERT(!is_illegal());
+ ASSERT(!cgen_->has_cc());
+ MacroAssembler* masm = cgen_->masm();
+ switch (type_) {
+ case SLOT: {
+ Comment cmnt(masm, "[ Load from Slot");
+ Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
+ ASSERT(slot != NULL);
+ cgen_->LoadFromSlot(slot, typeof_state);
+ break;
+ }
+
+ case NAMED: {
+ // TODO(1241834): Make sure that this it is safe to ignore the
+ // distinction between expressions in a typeof and not in a typeof. If
+ // there is a chance that reference errors can be thrown below, we
+ // must distinguish between the two kinds of loads (typeof expression
+ // loads must not throw a reference error).
+ Comment cmnt(masm, "[ Load from named Property");
+ Handle<String> name(GetName());
+ Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
+ // Setup the name register.
+ __ mov(ecx, name);
+
+ Variable* var = expression_->AsVariableProxy()->AsVariable();
+ if (var != NULL) {
+ ASSERT(var->is_global());
+ __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
+ } else {
+ __ call(ic, RelocInfo::CODE_TARGET);
+ }
+ __ push(eax); // IC call leaves result in eax, push it out
+ break;
+ }
+
+ case KEYED: {
+ // TODO(1241834): Make sure that this it is safe to ignore the
+ // distinction between expressions in a typeof and not in a typeof.
+ Comment cmnt(masm, "[ Load from keyed Property");
+ Property* property = expression_->AsProperty();
+ ASSERT(property != NULL);
+ __ RecordPosition(property->position());
+ Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+
+ Variable* var = expression_->AsVariableProxy()->AsVariable();
+ if (var != NULL) {
+ ASSERT(var->is_global());
+ __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
+ } else {
+ __ call(ic, RelocInfo::CODE_TARGET);
+ }
+ __ push(eax); // IC call leaves result in eax, push it out
+ break;
+ }
+
+ default:
+ UNREACHABLE();
+ }
+}
+
+
void Reference::SetValue(InitState init_state) {
ASSERT(!is_illegal());
ASSERT(!cgen_->has_cc());
@@ -4172,22 +4166,8 @@
case NAMED: {
Comment cmnt(masm, "[ Store to named Property");
- Property* property = expression_->AsProperty();
- Handle<String> name;
- if (property == NULL) {
- // Global variable reference treated as named property access.
- VariableProxy* proxy = expression_->AsVariableProxy();
- ASSERT(proxy->AsVariable() != NULL);
- ASSERT(proxy->AsVariable()->is_global());
- name = proxy->name();
- } else {
- Literal* raw_name = property->key()->AsLiteral();
- ASSERT(raw_name != NULL);
- name = Handle<String>(String::cast(*raw_name->handle()));
- __ RecordPosition(property->position());
- }
-
// Call the appropriate IC code.
+ Handle<String> name(GetName());
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
// TODO(1222589): Make the IC grab the values from the stack.
__ pop(eax);
« src/codegen-arm.cc ('K') | « src/codegen-arm.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698