Index: src/arm/fast-codegen-arm.cc |
=================================================================== |
--- src/arm/fast-codegen-arm.cc (revision 3181) |
+++ src/arm/fast-codegen-arm.cc (working copy) |
@@ -117,15 +117,51 @@ |
} |
+void FastCodeGenerator::Move(Expression::Context context, Register source) { |
+ switch (context) { |
+ case Expression::kUninitialized: |
+ UNREACHABLE(); |
+ case Expression::kEffect: |
+ break; |
+ case Expression::kValue: |
+ __ push(source); |
+ break; |
+ case Expression::kTest: |
+ TestAndBranch(source, true_label_, false_label_); |
+ break; |
+ case Expression::kValueTest: { |
+ Label discard; |
+ __ push(source); |
+ TestAndBranch(source, true_label_, &discard); |
+ __ bind(&discard); |
+ __ pop(); |
+ __ jmp(false_label_); |
+ break; |
+ } |
+ case Expression::kTestValue: { |
+ Label discard; |
+ __ push(source); |
+ TestAndBranch(source, &discard, false_label_); |
+ __ bind(&discard); |
+ __ pop(); |
+ __ jmp(true_label_); |
+ } |
+ } |
+} |
+ |
+ |
void FastCodeGenerator::Move(Expression::Context context, Slot* source) { |
switch (context) { |
case Expression::kUninitialized: |
UNREACHABLE(); |
case Expression::kEffect: |
break; |
- case Expression::kValue: |
+ case Expression::kValue: // Fall through. |
+ case Expression::kTest: // Fall through. |
+ case Expression::kValueTest: // Fall through. |
+ case Expression::kTestValue: |
__ ldr(ip, MemOperand(fp, SlotOffset(source))); |
- __ push(ip); |
+ Move(context, ip); |
break; |
} |
} |
@@ -137,9 +173,12 @@ |
UNREACHABLE(); |
case Expression::kEffect: |
break; |
- case Expression::kValue: |
+ case Expression::kValue: // Fall through. |
+ case Expression::kTest: // Fall through. |
+ case Expression::kValueTest: // Fall through. |
+ case Expression::kTestValue: |
__ mov(ip, Operand(expr->handle())); |
- __ push(ip); |
+ Move(context, ip); |
break; |
} |
} |
@@ -156,10 +195,49 @@ |
case Expression::kValue: |
__ str(source, MemOperand(sp)); |
break; |
+ case Expression::kTest: |
+ ASSERT(!source.is(sp)); |
+ __ pop(); |
+ TestAndBranch(source, true_label_, false_label_); |
+ break; |
+ case Expression::kValueTest: { |
+ Label discard; |
+ __ str(source, MemOperand(sp)); |
+ TestAndBranch(source, true_label_, &discard); |
+ __ bind(&discard); |
+ __ pop(); |
+ __ jmp(false_label_); |
+ break; |
+ } |
+ case Expression::kTestValue: { |
+ Label discard; |
+ __ str(source, MemOperand(sp)); |
+ TestAndBranch(source, &discard, false_label_); |
+ __ bind(&discard); |
+ __ pop(); |
+ __ jmp(true_label_); |
+ break; |
+ } |
} |
} |
+void FastCodeGenerator::TestAndBranch(Register source, |
+ Label* true_label, |
+ Label* false_label) { |
+ ASSERT_NE(NULL, true_label); |
+ ASSERT_NE(NULL, false_label); |
+ // Call the runtime to find the boolean value of the source and then |
+ // translate it into control flow to the pair of labels. |
+ __ push(source); |
+ __ CallRuntime(Runtime::kToBool, 1); |
+ __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
+ __ cmp(r0, ip); |
+ __ b(eq, true_label); |
+ __ jmp(false_label); |
+} |
+ |
+ |
void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
// Call the runtime to declare the globals. |
// The context is the first argument. |
@@ -360,6 +438,28 @@ |
case Expression::kValue: |
if (!result_saved) __ push(r0); |
break; |
+ case Expression::kTest: |
+ if (result_saved) __ pop(r0); |
+ TestAndBranch(r0, true_label_, false_label_); |
+ break; |
+ case Expression::kValueTest: { |
+ Label discard; |
+ if (!result_saved) __ push(r0); |
+ TestAndBranch(r0, true_label_, &discard); |
+ __ bind(&discard); |
+ __ pop(); |
+ __ jmp(false_label_); |
+ break; |
+ } |
+ case Expression::kTestValue: { |
+ Label discard; |
+ if (!result_saved) __ push(r0); |
+ TestAndBranch(r0, &discard, false_label_); |
+ __ bind(&discard); |
+ __ pop(); |
+ __ jmp(true_label_); |
+ break; |
+ } |
} |
} |
@@ -437,6 +537,28 @@ |
case Expression::kValue: |
if (!result_saved) __ push(r0); |
break; |
+ case Expression::kTest: |
+ if (result_saved) __ pop(r0); |
+ TestAndBranch(r0, true_label_, false_label_); |
+ break; |
+ case Expression::kValueTest: { |
+ Label discard; |
+ if (!result_saved) __ push(r0); |
+ TestAndBranch(r0, true_label_, &discard); |
+ __ bind(&discard); |
+ __ pop(); |
+ __ jmp(false_label_); |
+ break; |
+ } |
+ case Expression::kTestValue: { |
+ Label discard; |
+ if (!result_saved) __ push(r0); |
+ TestAndBranch(r0, &discard, false_label_); |
+ __ bind(&discard); |
+ __ pop(); |
+ __ jmp(true_label_); |
+ break; |
+ } |
} |
} |
@@ -521,16 +643,44 @@ |
UNREACHABLE(); |
case Expression::kEffect: |
// Case 'var = temp'. Discard right-hand-side temporary. |
- __ pop(ip); |
+ __ pop(r0); |
+ __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); |
break; |
case Expression::kValue: |
// Case 'temp1 <- (var = temp0)'. Preserve right-hand-side |
// temporary on the stack. |
- __ ldr(ip, MemOperand(sp)); |
+ __ ldr(r0, MemOperand(sp)); |
+ __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); |
break; |
+ case Expression::kTest: |
+ // Case 'if (var = temp) ...'. |
+ __ pop(r0); |
+ __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); |
+ TestAndBranch(r0, true_label_, false_label_); |
+ break; |
+ case Expression::kValueTest: { |
+ // Case '(var = temp) || ...' in value context. |
+ Label discard; |
+ __ ldr(r0, MemOperand(sp)); |
+ __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); |
+ TestAndBranch(r0, true_label_, &discard); |
+ __ bind(&discard); |
+ __ pop(); |
+ __ jmp(false_label_); |
+ break; |
+ } |
+ case Expression::kTestValue: { |
+ // Case '(var = temp) && ...' in value context. |
+ Label discard; |
+ __ ldr(r0, MemOperand(sp)); |
+ __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); |
+ TestAndBranch(r0, &discard, false_label_); |
+ __ bind(&discard); |
+ __ pop(); |
+ __ jmp(true_label_); |
+ break; |
+ } |
} |
- // Do the slot assignment. |
- __ str(ip, MemOperand(fp, SlotOffset(var->slot()))); |
} |
} |
} |
@@ -698,52 +848,4 @@ |
} |
-void FastCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) { |
- // Compile a short-circuited boolean operation in a non-test context. |
- |
- // Compile (e0 || e1) as if it were |
- // (let (temp = e0) temp ? temp : e1). |
- // Compile (e0 && e1) as if it were |
- // (let (temp = e0) !temp ? temp : e1). |
- |
- Label done; |
- Expression::Context context = expr->context(); |
- Expression* left = expr->left(); |
- Expression* right = expr->right(); |
- |
- // Call the runtime to find the boolean value of the left-hand |
- // subexpression. Duplicate the value if it may be needed as the final |
- // result. |
- if (left->AsLiteral() != NULL) { |
- __ mov(r0, Operand(left->AsLiteral()->handle())); |
- __ push(r0); |
- if (context == Expression::kValue) __ push(r0); |
- } else { |
- Visit(left); |
- ASSERT_EQ(Expression::kValue, left->context()); |
- if (context == Expression::kValue) { |
- __ ldr(r0, MemOperand(sp)); |
- __ push(r0); |
- } |
- } |
- // The left-hand value is in on top of the stack. It is duplicated on the |
- // stack iff the destination location is value. |
- __ CallRuntime(Runtime::kToBool, 1); |
- if (expr->op() == Token::OR) { |
- __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
- } else { |
- __ LoadRoot(ip, Heap::kFalseValueRootIndex); |
- } |
- __ cmp(r0, ip); |
- __ b(eq, &done); |
- |
- // Discard the left-hand value if present on the stack. |
- if (context == Expression::kValue) __ pop(); |
- // Save or discard the right-hand value as needed. |
- Visit(right); |
- ASSERT_EQ(context, right->context()); |
- |
- __ bind(&done); |
-} |
- |
} } // namespace v8::internal |