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

Unified Diff: src/ia32/fast-codegen-ia32.cc

Issue 339082: Initial implementation of top-level compilation of expressions in test... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 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
Index: src/ia32/fast-codegen-ia32.cc
===================================================================
--- src/ia32/fast-codegen-ia32.cc (revision 3182)
+++ src/ia32/fast-codegen-ia32.cc (working copy)
@@ -108,6 +108,39 @@
}
+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);
William Hesse 2009/10/30 12:09:39 Why not Label save; TestAndBranch(source, &save, f
Kevin Millikin (Chromium) 2009/10/30 13:45:53 TestAndBranch destroys source.
+ __ bind(&discard);
+ __ add(Operand(esp), Immediate(kPointerSize));
+ __ jmp(false_label_);
+ break;
+ }
+ case Expression::kTestValue: {
+ Label discard;
+ __ push(source);
+ TestAndBranch(source, &discard, false_label_);
+ __ bind(&discard);
+ __ add(Operand(esp), Immediate(kPointerSize));
+ __ jmp(true_label_);
+ }
+ }
+}
+
+
void FastCodeGenerator::Move(Expression::Context context, Slot* source) {
switch (context) {
case Expression::kUninitialized:
@@ -117,6 +150,12 @@
case Expression::kValue:
__ push(Operand(ebp, SlotOffset(source)));
break;
+ case Expression::kTest: // Fall through.
+ case Expression::kValueTest: // Fall through.
+ case Expression::kTestValue:
+ __ mov(eax, Operand(ebp, SlotOffset(source)));
William Hesse 2009/10/30 12:09:39 This could be optimized if TestAndBranch took an o
Kevin Millikin (Chromium) 2009/10/30 13:45:53 TestAndBranch needs the value in a register to com
+ Move(context, eax);
+ break;
}
}
@@ -130,6 +169,12 @@
case Expression::kValue:
__ push(Immediate(expr->handle()));
break;
+ case Expression::kTest: // Fall through.
+ case Expression::kValueTest: // Fall through.
+ case Expression::kTestValue:
+ __ mov(eax, expr->handle());
+ Move(context, eax);
+ break;
}
}
@@ -145,10 +190,63 @@
case Expression::kValue:
__ mov(Operand(esp, 0), source);
break;
+ case Expression::kTest:
+ ASSERT(!source.is(esp));
+ __ add(Operand(esp), Immediate(kPointerSize));
+ TestAndBranch(source, true_label_, false_label_);
+ break;
+ case Expression::kValueTest: {
+ Label discard;
+ __ mov(Operand(esp, 0), source);
+ TestAndBranch(source, true_label_, &discard);
+ __ bind(&discard);
+ __ add(Operand(esp), Immediate(kPointerSize));
+ __ jmp(false_label_);
+ break;
+ }
+ case Expression::kTestValue: {
+ Label discard;
+ __ mov(Operand(esp, 0), source);
+ TestAndBranch(source, &discard, false_label_);
+ __ bind(&discard);
+ __ add(Operand(esp), Immediate(kPointerSize));
+ __ 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);
+ // Use the shared ToBoolean stub to compile the value in the register into
+ // control flow to the code generator's true and false labels. Perform
+ // the fast checks assumed by the stub.
+ __ cmp(source, Factory::undefined_value()); // The undefined value is false.
+ __ j(equal, false_label);
+ __ cmp(source, Factory::true_value()); // True is true.
+ __ j(equal, true_label);
+ __ cmp(source, Factory::false_value()); // False is false.
+ __ j(equal, false_label);
+ ASSERT_EQ(0, kSmiTag);
+ __ test(source, Operand(source)); // The smi zero is false.
+ __ j(zero, false_label);
+ __ test(source, Immediate(kSmiTagMask)); // All other smis are true.
+ __ j(zero, true_label);
+
+ // Call the stub for all other cases.
+ __ push(source);
+ ToBooleanStub stub;
+ __ CallStub(&stub);
+ __ test(eax, Operand(eax)); // The stub returns nonzero for true.
+ __ j(not_zero, true_label);
+ __ jmp(false_label);
+}
+
+
void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
// Call the runtime to declare the globals.
__ push(esi); // The context is the first argument.
@@ -350,6 +448,28 @@
case Expression::kValue:
if (!result_saved) __ push(eax);
break;
+ case Expression::kTest:
+ if (result_saved) __ pop(eax);
+ TestAndBranch(eax, true_label_, false_label_);
+ break;
+ case Expression::kValueTest: {
+ Label discard;
+ if (!result_saved) __ push(eax);
+ TestAndBranch(eax, true_label_, &discard);
+ __ bind(&discard);
+ __ add(Operand(esp), Immediate(kPointerSize));
+ __ jmp(false_label_);
+ break;
+ }
+ case Expression::kTestValue: {
+ Label discard;
+ if (!result_saved) __ push(eax);
+ TestAndBranch(eax, &discard, false_label_);
+ __ bind(&discard);
+ __ add(Operand(esp), Immediate(kPointerSize));
+ __ jmp(true_label_);
+ break;
+ }
}
}
@@ -424,6 +544,28 @@
case Expression::kValue:
if (!result_saved) __ push(eax);
break;
+ case Expression::kTest:
+ if (result_saved) __ pop(eax);
+ TestAndBranch(eax, true_label_, false_label_);
+ break;
+ case Expression::kValueTest: {
+ Label discard;
+ if (!result_saved) __ push(eax);
+ TestAndBranch(eax, true_label_, &discard);
+ __ bind(&discard);
+ __ add(Operand(esp), Immediate(kPointerSize));
+ __ jmp(false_label_);
+ break;
+ }
+ case Expression::kTestValue: {
+ Label discard;
+ if (!result_saved) __ push(eax);
+ TestAndBranch(eax, &discard, false_label_);
+ __ bind(&discard);
+ __ add(Operand(esp), Immediate(kPointerSize));
+ __ jmp(true_label_);
+ break;
+ }
}
}
@@ -517,6 +659,34 @@
__ mov(eax, Operand(esp, 0));
__ mov(Operand(ebp, SlotOffset(var->slot())), eax);
break;
+ case Expression::kTest:
+ // Case 'if (var = temp) ...'.
+ __ pop(eax);
+ __ mov(Operand(ebp, SlotOffset(var->slot())), eax);
+ TestAndBranch(eax, true_label_, false_label_);
+ break;
+ case Expression::kValueTest: {
+ // Case '(var = temp) || ...' in value context.
+ Label discard;
William Hesse 2009/10/30 12:09:39 Same comment as above, on optimization.
+ __ mov(eax, Operand(esp, 0));
+ __ mov(Operand(ebp, SlotOffset(var->slot())), eax);
+ TestAndBranch(eax, true_label_, &discard);
William Hesse 2009/10/30 12:09:39 Can we give TestAndBranch a fallthrough label, so
Kevin Millikin (Chromium) 2009/10/30 13:45:53 We'd need a global fallthrough to get the whole be
+ __ bind(&discard);
+ __ add(Operand(esp), Immediate(kPointerSize));
+ __ jmp(false_label_);
+ break;
+ }
+ case Expression::kTestValue: {
+ // Case '(var = temp) && ...' in value context.
+ Label discard;
+ __ mov(eax, Operand(esp, 0));
+ __ mov(Operand(ebp, SlotOffset(var->slot())), eax);
+ TestAndBranch(eax, &discard, false_label_);
+ __ bind(&discard);
+ __ add(Operand(esp), Immediate(kPointerSize));
+ __ jmp(true_label_);
+ break;
+ }
}
}
}
@@ -688,90 +858,7 @@
}
-void FastCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) {
- // Compile a short-circuited boolean operation in a non-test context.
+#undef __
- // Compile (e0 || e1) or (e0 && e1) as if it were
- // (let (temp = e0) temp [or !temp, for &&] ? temp : e1).
- Label eval_right, done;
- Label *left_true, *left_false; // Where to branch to if lhs has that value.
- if (expr->op() == Token::OR) {
- left_true = &done;
- left_false = &eval_right;
- } else {
- left_true = &eval_right;
- left_false = &done;
- }
- Expression::Context context = expr->context();
- Expression* left = expr->left();
- Expression* right = expr->right();
-
- // Use the shared ToBoolean stub to find the boolean value of the
- // left-hand subexpression. Load the value into eax to perform some
- // inlined checks assumed by the stub.
-
- // Compile the left-hand value into eax. Put it on the stack if we may
- // need it as the value of the whole expression.
- if (left->AsLiteral() != NULL) {
- __ mov(eax, left->AsLiteral()->handle());
- if (context == Expression::kValue) __ push(eax);
- } else {
- Visit(left);
- ASSERT_EQ(Expression::kValue, left->context());
- switch (context) {
- case Expression::kUninitialized:
- UNREACHABLE();
- case Expression::kEffect:
- // Pop the left-hand value into eax because we will not need it as the
- // final result.
- __ pop(eax);
- break;
- case Expression::kValue:
- // Copy the left-hand value into eax because we may need it as the
- // final result.
- __ mov(eax, Operand(esp, 0));
- break;
- }
- }
- // The left-hand value is in eax. It is also on the stack iff the
- // destination location is value.
-
- // Perform fast checks assumed by the stub.
- __ cmp(eax, Factory::undefined_value()); // The undefined value is false.
- __ j(equal, left_false);
- __ cmp(eax, Factory::true_value()); // True is true.
- __ j(equal, left_true);
- __ cmp(eax, Factory::false_value()); // False is false.
- __ j(equal, left_false);
- ASSERT_EQ(0, kSmiTag);
- __ test(eax, Operand(eax)); // The smi zero is false.
- __ j(zero, left_false);
- __ test(eax, Immediate(kSmiTagMask)); // All other smis are true.
- __ j(zero, left_true);
-
- // Call the stub for all other cases.
- __ push(eax);
- ToBooleanStub stub;
- __ CallStub(&stub);
- __ test(eax, Operand(eax)); // The stub returns nonzero for true.
- if (expr->op() == Token::OR) {
- __ j(not_zero, &done);
- } else {
- __ j(zero, &done);
- }
-
- __ bind(&eval_right);
- // Discard the left-hand value if present on the stack.
- if (context == Expression::kValue) {
- __ add(Operand(esp), Immediate(kPointerSize));
- }
- // Save or discard the right-hand value as needed.
- Visit(right);
- ASSERT_EQ(context, right->context());
-
- __ bind(&done);
-}
-
-
} } // namespace v8::internal

Powered by Google App Engine
This is Rietveld 408576698