Some cleanup of the toplevel code generator:

* Rename the operation of filling a context with a value.  Formerly it
  was 'Move', now it's 'Apply' so as to avoid confusion with various
  other Moves (eg, in the toplevel codegen, in the macro assemblers).

* Use the abstraction Drop rather than math on the stack pointer.

* Add a predicate on AST expression nodes to abstract a repeated test
  whether we should us a regular (named) IC or a keyed IC.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3580 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 55b73d94
......@@ -614,15 +614,7 @@ void CodeGenerator::LoadReference(Reference* ref) {
// The expression is either a property or a variable proxy that rewrites
// to a property.
LoadAndSpill(property->obj());
// We use a named reference if the key is a literal symbol, unless it is
// a string that can be legally parsed as an integer. This is because
// otherwise we will not get into the slow case code that handles [] on
// String objects.
Literal* literal = property->key()->AsLiteral();
uint32_t dummy;
if (literal != NULL &&
literal->handle()->IsSymbol() &&
!String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) {
if (property->key()->IsPropertyName()) {
ref->set_type(Reference::NAMED);
} else {
LoadAndSpill(property->key());
......
This diff is collapsed.
......@@ -162,9 +162,9 @@ void MacroAssembler::StackLimitCheck(Label* on_stack_overflow) {
}
void MacroAssembler::Drop(int stack_elements, Condition cond) {
if (stack_elements > 0) {
add(sp, sp, Operand(stack_elements * kPointerSize), LeaveCC, cond);
void MacroAssembler::Drop(int count, Condition cond) {
if (count > 0) {
add(sp, sp, Operand(count * kPointerSize), LeaveCC, cond);
}
}
......
......@@ -64,7 +64,11 @@ class MacroAssembler: public Assembler {
void Call(byte* target, RelocInfo::Mode rmode, Condition cond = al);
void Call(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al);
void Ret(Condition cond = al);
void Drop(int stack_elements, Condition cond = al);
// Emit code to discard a non-negative number of pointer-sized elements
// from the stack, clobbering only the sp register.
void Drop(int count, Condition cond = al);
void Call(Label* target);
void Move(Register dst, Handle<Object> value);
// Jumps to the label at the index given by the Smi in "index".
......
......@@ -187,6 +187,11 @@ class Expression: public AstNode {
virtual bool IsValidJSON() { return false; }
virtual bool IsValidLeftHandSide() { return false; }
// Symbols that cannot be parsed as array indices are considered property
// names. We do not treat symbols that can be array indexes as property
// names because [] for string objects is handled only by keyed ICs.
virtual bool IsPropertyName() { return false; }
// Mark the expression as being compiled as an expression
// statement. This is used to transform postfix increments to
// (faster) prefix increments.
......@@ -707,6 +712,14 @@ class Literal: public Expression {
virtual bool IsValidJSON() { return true; }
virtual bool IsPropertyName() {
if (handle_->IsSymbol()) {
uint32_t ignored;
return !String::cast(*handle_)->AsArrayIndex(&ignored);
}
return false;
}
// Identity testers.
bool IsNull() const { return handle_.is_identical_to(Factory::null_value()); }
bool IsTrue() const { return handle_.is_identical_to(Factory::true_value()); }
......
......@@ -902,11 +902,7 @@ void CodeGenSelector::VisitAssignment(Assignment* expr) {
// We will only visit the key during code generation for keyed property
// stores. Leave its expression context uninitialized for named
// property stores.
Literal* lit = prop->key()->AsLiteral();
uint32_t ignored;
if (lit == NULL ||
!lit->handle()->IsSymbol() ||
String::cast(*(lit->handle()))->AsArrayIndex(&ignored)) {
if (!prop->key()->IsPropertyName()) {
ProcessExpression(prop->key(), Expression::kValue);
CHECK_BAILOUT;
}
......@@ -1030,11 +1026,7 @@ void CodeGenSelector::VisitCountOperation(CountOperation* expr) {
// We will only visit the key during code generation for keyed property
// stores. Leave its expression context uninitialized for named
// property stores.
Literal* lit = prop->key()->AsLiteral();
uint32_t ignored;
if (lit == NULL ||
!lit->handle()->IsSymbol() ||
String::cast(*(lit->handle()))->AsArrayIndex(&ignored)) {
if (!prop->key()->IsPropertyName()) {
ProcessExpression(prop->key(), Expression::kValue);
CHECK_BAILOUT;
}
......
......@@ -75,6 +75,39 @@ int FastCodeGenerator::SlotOffset(Slot* slot) {
}
void FastCodeGenerator::Apply(Expression::Context context, Register reg) {
switch (context) {
case Expression::kUninitialized:
UNREACHABLE();
case Expression::kEffect:
break;
case Expression::kValue:
__ push(reg);
break;
case Expression::kTest:
TestAndBranch(reg, true_label_, false_label_);
break;
case Expression::kValueTest: {
Label discard;
__ push(reg);
TestAndBranch(reg, true_label_, &discard);
__ bind(&discard);
__ Drop(1);
__ jmp(false_label_);
break;
}
case Expression::kTestValue: {
Label discard;
__ push(reg);
TestAndBranch(reg, &discard, false_label_);
__ bind(&discard);
__ Drop(1);
__ jmp(true_label_);
}
}
}
void FastCodeGenerator::VisitDeclarations(
ZoneList<Declaration*>* declarations) {
int length = declarations->length();
......@@ -624,7 +657,7 @@ void FastCodeGenerator::VisitSlot(Slot* expr) {
void FastCodeGenerator::VisitLiteral(Literal* expr) {
Comment cmnt(masm_, "[ Literal");
Move(expr->context(), expr);
Apply(expr->context(), expr);
}
......
......@@ -212,10 +212,23 @@ class FastCodeGenerator: public AstVisitor {
int SlotOffset(Slot* slot);
void Move(Expression::Context destination, Register source);
void MoveTOS(Expression::Context destination);
void Move(Expression::Context destination, Slot* source, Register scratch);
void Move(Expression::Context destination, Literal* source);
// Emit code to complete the evaluation of an expression based on its
// expression context and given its value is in a register, non-lookup
// slot, or a literal.
void Apply(Expression::Context context, Register reg);
void Apply(Expression::Context context, Slot* slot, Register scratch);
void Apply(Expression::Context context, Literal* lit);
// Emit code to complete the evaluation of an expression based on its
// expression context and given its value is on top of the stack.
void ApplyTOS(Expression::Context context);
// Emit code to discard count elements from the top of stack, then
// complete the evaluation of an expression based on its expression
// context and given its value is in a register.
void DropAndApply(int count, Expression::Context context, Register reg);
void Move(Slot* dst, Register source, Register scratch1, Register scratch2);
void Move(Register dst, Slot* source);
......@@ -224,12 +237,6 @@ class FastCodeGenerator: public AstVisitor {
// register.
MemOperand EmitSlotSearch(Slot* slot, Register scratch);
// Drop the TOS, and store source to destination.
// If destination is TOS, just overwrite TOS with source.
void DropAndMove(Expression::Context destination,
Register source,
int drop_count = 1);
// Test the JavaScript value in source as if in a test context, compile
// control flow to a pair of labels.
void TestAndBranch(Register source, Label* true_label, Label* false_label);
......
......@@ -664,15 +664,7 @@ void CodeGenerator::LoadReference(Reference* ref) {
// The expression is either a property or a variable proxy that rewrites
// to a property.
Load(property->obj());
// We use a named reference if the key is a literal symbol, unless it is
// a string that can be legally parsed as an integer. This is because
// otherwise we will not get into the slow case code that handles [] on
// String objects.
Literal* literal = property->key()->AsLiteral();
uint32_t dummy;
if (literal != NULL &&
literal->handle()->IsSymbol() &&
!String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) {
if (property->key()->IsPropertyName()) {
ref->set_type(Reference::NAMED);
} else {
Load(property->key());
......
This diff is collapsed.
......@@ -368,6 +368,8 @@ class MacroAssembler: public Assembler {
void Ret();
// Emit code to discard a non-negative number of pointer-sized elements
// from the stack, clobbering only the esp register.
void Drop(int element_count);
void Call(Label* target) { call(target); }
......
......@@ -4256,15 +4256,7 @@ void CodeGenerator::LoadReference(Reference* ref) {
// The expression is either a property or a variable proxy that rewrites
// to a property.
Load(property->obj());
// We use a named reference if the key is a literal symbol, unless it is
// a string that can be legally parsed as an integer. This is because
// otherwise we will not get into the slow case code that handles [] on
// String objects.
Literal* literal = property->key()->AsLiteral();
uint32_t dummy;
if (literal != NULL &&
literal->handle()->IsSymbol() &&
!String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) {
if (property->key()->IsPropertyName()) {
ref->set_type(Reference::NAMED);
} else {
Load(property->key());
......
This diff is collapsed.
......@@ -415,7 +415,11 @@ class MacroAssembler: public Assembler {
void Cmp(Register dst, Handle<Object> source);
void Cmp(const Operand& dst, Handle<Object> source);
void Push(Handle<Object> source);
// Emit code to discard a non-negative number of pointer-sized elements
// from the stack, clobbering only the rsp register.
void Drop(int stack_elements);
void Call(Label* target) { call(target); }
// Control Flow
......
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