Index: src/fast-codegen.cc |
diff --git a/src/fast-codegen.cc b/src/fast-codegen.cc |
index 36d7297fb01a334bae0dcac5168fd9c34abaf991..587cda8061e3878f012f02ec3e9fc2afa6e326ec 100644 |
--- a/src/fast-codegen.cc |
+++ b/src/fast-codegen.cc |
@@ -293,7 +293,30 @@ void FastCodeGenSyntaxChecker::VisitThrow(Throw* expr) { |
void FastCodeGenSyntaxChecker::VisitProperty(Property* expr) { |
- BAILOUT("Property"); |
+ // We support named this property references. |
+ VariableProxy* proxy = expr->obj()->AsVariableProxy(); |
+ if (proxy == NULL || !proxy->var()->is_this()) { |
+ BAILOUT("Non-this-property reference"); |
+ } |
+ if (!expr->key()->IsPropertyName()) { |
+ BAILOUT("Non-named-property reference"); |
+ } |
+ |
+ // We will only specialize for fields on the object itself. |
+ // Expression::IsPropertyName implies that the name is a literal |
+ // symbol but we do not assume that. |
+ Literal* key = expr->key()->AsLiteral(); |
+ if (key != NULL && key->handle()->IsString()) { |
+ Handle<Object> receiver = info()->receiver(); |
+ Handle<String> name = Handle<String>::cast(key->handle()); |
+ LookupResult lookup; |
+ receiver->Lookup(*name, &lookup); |
+ if (lookup.holder() != *receiver) BAILOUT("Non-own property reference"); |
+ if (!lookup.type() == FIELD) BAILOUT("Non-field property reference"); |
+ } else { |
+ UNREACHABLE(); |
+ BAILOUT("Unexpected non-string-literal property key"); |
+ } |
} |
@@ -323,7 +346,48 @@ void FastCodeGenSyntaxChecker::VisitCountOperation(CountOperation* expr) { |
void FastCodeGenSyntaxChecker::VisitBinaryOperation(BinaryOperation* expr) { |
- BAILOUT("BinaryOperation"); |
+ // We support bitwise OR. |
+ switch (expr->op()) { |
+ case Token::COMMA: |
+ BAILOUT("BinaryOperation COMMA"); |
+ case Token::OR: |
+ BAILOUT("BinaryOperation OR"); |
+ case Token::AND: |
+ BAILOUT("BinaryOperation AND"); |
+ |
+ case Token::BIT_OR: |
+ // We support expressions nested on the left because they only require |
+ // a pair of registers to keep all intermediate values in registers |
+ // (i.e., the expression stack has height no more than two). |
+ if (!expr->right()->IsLeaf()) BAILOUT("expression nested on right"); |
+ Visit(expr->left()); |
+ CHECK_BAILOUT; |
+ Visit(expr->right()); |
+ break; |
+ |
+ case Token::BIT_XOR: |
+ BAILOUT("BinaryOperation BIT_XOR"); |
+ case Token::BIT_AND: |
+ BAILOUT("BinaryOperation BIT_AND"); |
+ case Token::SHL: |
+ BAILOUT("BinaryOperation SHL"); |
+ case Token::SAR: |
+ BAILOUT("BinaryOperation SAR"); |
+ case Token::SHR: |
+ BAILOUT("BinaryOperation SHR"); |
+ case Token::ADD: |
+ BAILOUT("BinaryOperation ADD"); |
+ case Token::SUB: |
+ BAILOUT("BinaryOperation SUB"); |
+ case Token::MUL: |
+ BAILOUT("BinaryOperation MUL"); |
+ case Token::DIV: |
+ BAILOUT("BinaryOperation DIV"); |
+ case Token::MOD: |
+ BAILOUT("BinaryOperation MOD"); |
+ default: |
+ UNREACHABLE(); |
+ } |
} |
@@ -489,12 +553,6 @@ void FastCodeGenerator::VisitSlot(Slot* expr) { |
void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
ASSERT(expr->var()->is_global() && !expr->var()->is_this()); |
- Comment cmnt(masm(), ";; Global"); |
- if (FLAG_print_ir) { |
- SmartPointer<char> name = expr->name()->ToCString(); |
- PrintF("%d: t%d = Global(%s)\n", expr->num(), expr->num(), *name); |
- } |
- |
// Check if we can compile a global variable load directly from the cell. |
ASSERT(info()->has_global_object()); |
LookupResult lookup; |
@@ -503,7 +561,17 @@ void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
ASSERT(lookup.IsValid()); |
ASSERT(lookup.IsDontDelete()); |
Handle<Object> cell(info()->global_object()->GetPropertyCell(&lookup)); |
- EmitGlobalVariableLoad(cell); |
+ |
+ // Global variable lookups do not have side effects, so we do not need to |
+ // emit code if we are in an effect context. |
+ if (!destination().is(no_reg)) { |
+ Comment cmnt(masm(), ";; Global"); |
+ if (FLAG_print_ir) { |
+ SmartPointer<char> name = expr->name()->ToCString(); |
+ PrintF("%d: t%d = Global(%s)\n", expr->num(), expr->num(), *name); |
+ } |
+ EmitGlobalVariableLoad(cell); |
+ } |
} |
@@ -533,8 +601,13 @@ void FastCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) { |
void FastCodeGenerator::VisitAssignment(Assignment* expr) { |
- // Known to be a simple this property assignment. |
- Visit(expr->value()); |
+ // Known to be a simple this property assignment. Effectively a unary |
+ // operation. |
+ { Register my_destination = destination(); |
+ set_destination(accumulator0()); |
+ Visit(expr->value()); |
+ set_destination(my_destination); |
+ } |
Property* prop = expr->target()->AsProperty(); |
ASSERT_NOT_NULL(prop); |
@@ -544,11 +617,12 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) { |
Handle<String> name = |
Handle<String>::cast(prop->key()->AsLiteral()->handle()); |
- Comment cmnt(masm(), ";; Store(this)"); |
+ Comment cmnt(masm(), ";; Store to this"); |
if (FLAG_print_ir) { |
SmartPointer<char> name_string = name->ToCString(); |
- PrintF("%d: t%d = Store(this, \"%s\", t%d)\n", |
- expr->num(), expr->num(), *name_string, expr->value()->num()); |
+ PrintF("%d: ", expr->num()); |
+ if (!destination().is(no_reg)) PrintF("t%d = ", expr->num()); |
+ PrintF("Store(this, \"%s\", t%d)\n", *name_string, expr->value()->num()); |
} |
EmitThisPropertyStore(name); |
@@ -561,7 +635,21 @@ void FastCodeGenerator::VisitThrow(Throw* expr) { |
void FastCodeGenerator::VisitProperty(Property* expr) { |
- UNREACHABLE(); |
+ ASSERT_NOT_NULL(expr->obj()->AsVariableProxy()); |
+ ASSERT(expr->obj()->AsVariableProxy()->var()->is_this()); |
+ ASSERT(expr->key()->IsPropertyName()); |
+ if (!destination().is(no_reg)) { |
+ Handle<String> name = |
+ Handle<String>::cast(expr->key()->AsLiteral()->handle()); |
+ |
+ Comment cmnt(masm(), ";; Load from this"); |
+ if (FLAG_print_ir) { |
+ SmartPointer<char> name_string = name->ToCString(); |
+ PrintF("%d: t%d = Load(this, \"%s\")\n", |
+ expr->num(), expr->num(), *name_string); |
+ } |
+ EmitThisPropertyLoad(name); |
+ } |
} |
@@ -591,7 +679,26 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { |
void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { |
- UNREACHABLE(); |
+ // We support limited binary operations: bitwise OR only allowed to be |
+ // nested on the left. |
+ ASSERT(expr->op() == Token::BIT_OR); |
+ ASSERT(expr->right()->IsLeaf()); |
+ |
+ { Register my_destination = destination(); |
+ set_destination(accumulator1()); |
+ Visit(expr->left()); |
+ set_destination(accumulator0()); |
+ Visit(expr->right()); |
+ set_destination(my_destination); |
+ } |
+ |
+ Comment cmnt(masm(), ";; BIT_OR"); |
+ if (FLAG_print_ir) { |
+ PrintF("%d: ", expr->num()); |
+ if (!destination().is(no_reg)) PrintF("t%d = ", expr->num()); |
+ PrintF("BIT_OR(t%d, t%d)\n", expr->left()->num(), expr->right()->num()); |
+ } |
+ EmitBitOr(); |
} |