| 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
|
|
|