| Index: src/x64/full-codegen-x64.cc
|
| ===================================================================
|
| --- src/x64/full-codegen-x64.cc (revision 5316)
|
| +++ src/x64/full-codegen-x64.cc (working copy)
|
| @@ -253,21 +253,8 @@
|
| case Expression::kTest:
|
| // For simplicity we always test the accumulator register.
|
| if (!reg.is(result_register())) __ movq(result_register(), reg);
|
| - DoTest(context);
|
| + DoTest(true_label_, false_label_, NULL);
|
| break;
|
| -
|
| - case Expression::kValueTest:
|
| - case Expression::kTestValue:
|
| - if (!reg.is(result_register())) __ movq(result_register(), reg);
|
| - switch (location_) {
|
| - case kAccumulator:
|
| - break;
|
| - case kStack:
|
| - __ push(result_register());
|
| - break;
|
| - }
|
| - DoTest(context);
|
| - break;
|
| }
|
| }
|
|
|
| @@ -295,21 +282,8 @@
|
|
|
| case Expression::kTest:
|
| Move(result_register(), slot);
|
| - DoTest(context);
|
| + DoTest(true_label_, false_label_, NULL);
|
| break;
|
| -
|
| - case Expression::kValueTest:
|
| - case Expression::kTestValue:
|
| - Move(result_register(), slot);
|
| - switch (location_) {
|
| - case kAccumulator:
|
| - break;
|
| - case kStack:
|
| - __ push(result_register());
|
| - break;
|
| - }
|
| - DoTest(context);
|
| - break;
|
| }
|
| }
|
|
|
| @@ -334,21 +308,8 @@
|
|
|
| case Expression::kTest:
|
| __ Move(result_register(), lit->handle());
|
| - DoTest(context);
|
| + DoTest(true_label_, false_label_, NULL);
|
| break;
|
| -
|
| - case Expression::kValueTest:
|
| - case Expression::kTestValue:
|
| - __ Move(result_register(), lit->handle());
|
| - switch (location_) {
|
| - case kAccumulator:
|
| - break;
|
| - case kStack:
|
| - __ push(result_register());
|
| - break;
|
| - }
|
| - DoTest(context);
|
| - break;
|
| }
|
| }
|
|
|
| @@ -374,21 +335,8 @@
|
|
|
| case Expression::kTest:
|
| __ pop(result_register());
|
| - DoTest(context);
|
| + DoTest(true_label_, false_label_, NULL);
|
| break;
|
| -
|
| - case Expression::kValueTest:
|
| - case Expression::kTestValue:
|
| - switch (location_) {
|
| - case kAccumulator:
|
| - __ pop(result_register());
|
| - break;
|
| - case kStack:
|
| - __ movq(result_register(), Operand(rsp, 0));
|
| - break;
|
| - }
|
| - DoTest(context);
|
| - break;
|
| }
|
| }
|
|
|
| @@ -422,24 +370,8 @@
|
| case Expression::kTest:
|
| __ Drop(count);
|
| if (!reg.is(result_register())) __ movq(result_register(), reg);
|
| - DoTest(context);
|
| + DoTest(true_label_, false_label_, NULL);
|
| break;
|
| -
|
| - case Expression::kValueTest:
|
| - case Expression::kTestValue:
|
| - switch (location_) {
|
| - case kAccumulator:
|
| - __ Drop(count);
|
| - if (!reg.is(result_register())) __ movq(result_register(), reg);
|
| - break;
|
| - case kStack:
|
| - if (count > 1) __ Drop(count - 1);
|
| - __ movq(result_register(), reg);
|
| - __ movq(Operand(rsp, 0), result_register());
|
| - break;
|
| - }
|
| - DoTest(context);
|
| - break;
|
| }
|
| }
|
|
|
| @@ -465,14 +397,6 @@
|
| *if_true = true_label_;
|
| *if_false = false_label_;
|
| break;
|
| - case Expression::kValueTest:
|
| - *if_true = materialize_true;
|
| - *if_false = false_label_;
|
| - break;
|
| - case Expression::kTestValue:
|
| - *if_true = true_label_;
|
| - *if_false = materialize_false;
|
| - break;
|
| }
|
| }
|
|
|
| @@ -512,32 +436,6 @@
|
|
|
| case Expression::kTest:
|
| break;
|
| -
|
| - case Expression::kValueTest:
|
| - __ bind(materialize_true);
|
| - switch (location_) {
|
| - case kAccumulator:
|
| - __ Move(result_register(), Factory::true_value());
|
| - break;
|
| - case kStack:
|
| - __ Push(Factory::true_value());
|
| - break;
|
| - }
|
| - __ jmp(true_label_);
|
| - break;
|
| -
|
| - case Expression::kTestValue:
|
| - __ bind(materialize_false);
|
| - switch (location_) {
|
| - case kAccumulator:
|
| - __ Move(result_register(), Factory::false_value());
|
| - break;
|
| - case kStack:
|
| - __ Push(Factory::false_value());
|
| - break;
|
| - }
|
| - __ jmp(false_label_);
|
| - break;
|
| }
|
| }
|
|
|
| @@ -567,76 +465,13 @@
|
| case Expression::kTest:
|
| __ jmp(flag ? true_label_ : false_label_);
|
| break;
|
| - case Expression::kTestValue:
|
| - switch (location_) {
|
| - case kAccumulator:
|
| - // If value is false it's needed.
|
| - if (!flag) __ LoadRoot(result_register(), Heap::kFalseValueRootIndex);
|
| - break;
|
| - case kStack:
|
| - // If value is false it's needed.
|
| - if (!flag) __ PushRoot(Heap::kFalseValueRootIndex);
|
| - break;
|
| - }
|
| - __ jmp(flag ? true_label_ : false_label_);
|
| - break;
|
| - case Expression::kValueTest:
|
| - switch (location_) {
|
| - case kAccumulator:
|
| - // If value is true it's needed.
|
| - if (flag) __ LoadRoot(result_register(), Heap::kTrueValueRootIndex);
|
| - break;
|
| - case kStack:
|
| - // If value is true it's needed.
|
| - if (flag) __ PushRoot(Heap::kTrueValueRootIndex);
|
| - break;
|
| - }
|
| - __ jmp(flag ? true_label_ : false_label_);
|
| - break;
|
| }
|
| }
|
|
|
|
|
| -void FullCodeGenerator::DoTest(Expression::Context context) {
|
| - // The value to test is in the accumulator. If the value might be needed
|
| - // on the stack (value/test and test/value contexts with a stack location
|
| - // desired), then the value is already duplicated on the stack.
|
| - ASSERT_NE(NULL, true_label_);
|
| - ASSERT_NE(NULL, false_label_);
|
| -
|
| - // In value/test and test/value expression contexts with stack as the
|
| - // desired location, there is already an extra value on the stack. Use a
|
| - // label to discard it if unneeded.
|
| - Label discard;
|
| - Label* if_true = true_label_;
|
| - Label* if_false = false_label_;
|
| - switch (context) {
|
| - case Expression::kUninitialized:
|
| - case Expression::kEffect:
|
| - case Expression::kValue:
|
| - UNREACHABLE();
|
| - case Expression::kTest:
|
| - break;
|
| - case Expression::kValueTest:
|
| - switch (location_) {
|
| - case kAccumulator:
|
| - break;
|
| - case kStack:
|
| - if_false = &discard;
|
| - break;
|
| - }
|
| - break;
|
| - case Expression::kTestValue:
|
| - switch (location_) {
|
| - case kAccumulator:
|
| - break;
|
| - case kStack:
|
| - if_true = &discard;
|
| - break;
|
| - }
|
| - break;
|
| - }
|
| -
|
| +void FullCodeGenerator::DoTest(Label* if_true,
|
| + Label* if_false,
|
| + Label* fall_through) {
|
| // Emit the inlined tests assumed by the stub.
|
| __ CompareRoot(result_register(), Heap::kUndefinedValueRootIndex);
|
| __ j(equal, if_false);
|
| @@ -650,83 +485,28 @@
|
| Condition is_smi = masm_->CheckSmi(result_register());
|
| __ j(is_smi, if_true);
|
|
|
| - // Save a copy of the value if it may be needed and isn't already saved.
|
| - switch (context) {
|
| - case Expression::kUninitialized:
|
| - case Expression::kEffect:
|
| - case Expression::kValue:
|
| - UNREACHABLE();
|
| - case Expression::kTest:
|
| - break;
|
| - case Expression::kValueTest:
|
| - switch (location_) {
|
| - case kAccumulator:
|
| - __ push(result_register());
|
| - break;
|
| - case kStack:
|
| - break;
|
| - }
|
| - break;
|
| - case Expression::kTestValue:
|
| - switch (location_) {
|
| - case kAccumulator:
|
| - __ push(result_register());
|
| - break;
|
| - case kStack:
|
| - break;
|
| - }
|
| - break;
|
| - }
|
| -
|
| // Call the ToBoolean stub for all other cases.
|
| ToBooleanStub stub;
|
| __ push(result_register());
|
| __ CallStub(&stub);
|
| __ testq(rax, rax);
|
|
|
| - // The stub returns nonzero for true. Complete based on the context.
|
| - switch (context) {
|
| - case Expression::kUninitialized:
|
| - case Expression::kEffect:
|
| - case Expression::kValue:
|
| - UNREACHABLE();
|
| + // The stub returns nonzero for true.
|
| + Split(not_zero, if_true, if_false, fall_through);
|
| +}
|
|
|
| - case Expression::kTest:
|
| - __ j(not_zero, true_label_);
|
| - __ jmp(false_label_);
|
| - break;
|
|
|
| - case Expression::kValueTest:
|
| - switch (location_) {
|
| - case kAccumulator:
|
| - __ j(zero, &discard);
|
| - __ pop(result_register());
|
| - __ jmp(true_label_);
|
| - break;
|
| - case kStack:
|
| - __ j(not_zero, true_label_);
|
| - break;
|
| - }
|
| - __ bind(&discard);
|
| - __ Drop(1);
|
| - __ jmp(false_label_);
|
| - break;
|
| -
|
| - case Expression::kTestValue:
|
| - switch (location_) {
|
| - case kAccumulator:
|
| - __ j(not_zero, &discard);
|
| - __ pop(result_register());
|
| - __ jmp(false_label_);
|
| - break;
|
| - case kStack:
|
| - __ j(zero, false_label_);
|
| - break;
|
| - }
|
| - __ bind(&discard);
|
| - __ Drop(1);
|
| - __ jmp(true_label_);
|
| - break;
|
| +void FullCodeGenerator::Split(Condition cc,
|
| + Label* if_true,
|
| + Label* if_false,
|
| + Label* fall_through) {
|
| + if (if_false == fall_through) {
|
| + __ j(cc, if_true);
|
| + } else if (if_true == fall_through) {
|
| + __ j(NegateCondition(cc), if_false);
|
| + } else {
|
| + __ j(cc, if_true);
|
| + __ jmp(if_false);
|
| }
|
| }
|
|
|
| @@ -1206,7 +986,7 @@
|
| __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
|
| __ movq(rcx, FieldOperand(rdi, JSFunction::kLiteralsOffset));
|
| int literal_offset =
|
| - FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
|
| + FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
|
| __ movq(rbx, FieldOperand(rcx, literal_offset));
|
| __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex);
|
| __ j(not_equal, &materialized);
|
| @@ -1987,8 +1767,7 @@
|
| PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false);
|
|
|
| Condition positive_smi = __ CheckPositiveSmi(rax);
|
| - __ j(positive_smi, if_true);
|
| - __ jmp(if_false);
|
| + Split(positive_smi, if_true, if_false, NULL);
|
|
|
| Apply(context_, if_true, if_false);
|
| }
|
| @@ -2016,8 +1795,7 @@
|
| __ cmpq(rbx, Immediate(FIRST_JS_OBJECT_TYPE));
|
| __ j(below, if_false);
|
| __ cmpq(rbx, Immediate(LAST_JS_OBJECT_TYPE));
|
| - __ j(below_equal, if_true);
|
| - __ jmp(if_false);
|
| + Split(below_equal, if_true, if_false, NULL);
|
|
|
| Apply(context_, if_true, if_false);
|
| }
|
| @@ -2035,8 +1813,7 @@
|
|
|
| __ JumpIfSmi(rax, if_false);
|
| __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rbx);
|
| - __ j(above_equal, if_true);
|
| - __ jmp(if_false);
|
| + Split(above_equal, if_true, if_false, NULL);
|
|
|
| Apply(context_, if_true, if_false);
|
| }
|
| @@ -2056,8 +1833,7 @@
|
| __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
|
| __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
|
| Immediate(1 << Map::kIsUndetectable));
|
| - __ j(not_zero, if_true);
|
| - __ jmp(if_false);
|
| + Split(not_zero, if_true, if_false, NULL);
|
|
|
| Apply(context_, if_true, if_false);
|
| }
|
| @@ -2094,8 +1870,7 @@
|
|
|
| __ JumpIfSmi(rax, if_false);
|
| __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
|
| - __ j(equal, if_true);
|
| - __ jmp(if_false);
|
| + Split(equal, if_true, if_false, NULL);
|
|
|
| Apply(context_, if_true, if_false);
|
| }
|
| @@ -2113,8 +1888,7 @@
|
|
|
| __ JumpIfSmi(rax, if_false);
|
| __ CmpObjectType(rax, JS_ARRAY_TYPE, rbx);
|
| - __ j(equal, if_true);
|
| - __ jmp(if_false);
|
| + Split(equal, if_true, if_false, NULL);
|
|
|
| Apply(context_, if_true, if_false);
|
| }
|
| @@ -2132,8 +1906,7 @@
|
|
|
| __ JumpIfSmi(rax, if_false);
|
| __ CmpObjectType(rax, JS_REGEXP_TYPE, rbx);
|
| - __ j(equal, if_true);
|
| - __ jmp(if_false);
|
| + Split(equal, if_true, if_false, NULL);
|
|
|
| Apply(context_, if_true, if_false);
|
| }
|
| @@ -2162,8 +1935,7 @@
|
| __ bind(&check_frame_marker);
|
| __ SmiCompare(Operand(rax, StandardFrameConstants::kMarkerOffset),
|
| Smi::FromInt(StackFrame::CONSTRUCT));
|
| - __ j(equal, if_true);
|
| - __ jmp(if_false);
|
| + Split(equal, if_true, if_false, NULL);
|
|
|
| Apply(context_, if_true, if_false);
|
| }
|
| @@ -2183,8 +1955,7 @@
|
|
|
| __ pop(rbx);
|
| __ cmpq(rax, rbx);
|
| - __ j(equal, if_true);
|
| - __ jmp(if_false);
|
| + Split(equal, if_true, if_false, NULL);
|
|
|
| Apply(context_, if_true, if_false);
|
| }
|
| @@ -2840,19 +2611,7 @@
|
| break;
|
| }
|
| break;
|
| - case Expression::kTestValue:
|
| - // Value is false so it's needed.
|
| - switch (location_) {
|
| - case kAccumulator:
|
| - __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex);
|
| - break;
|
| - case kStack:
|
| - __ PushRoot(Heap::kUndefinedValueRootIndex);
|
| - break;
|
| - }
|
| - // Fall through.
|
| case Expression::kTest:
|
| - case Expression::kValueTest:
|
| __ jmp(false_label_);
|
| break;
|
| }
|
| @@ -3033,8 +2792,6 @@
|
| break;
|
| case Expression::kValue:
|
| case Expression::kTest:
|
| - case Expression::kValueTest:
|
| - case Expression::kTestValue:
|
| // Save the result on the stack. If we have a named or keyed property
|
| // we store the result under the receiver that is currently on top
|
| // of the stack.
|
| @@ -3138,41 +2895,7 @@
|
| }
|
| }
|
|
|
| -void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
|
| - Comment cmnt(masm_, "[ BinaryOperation");
|
| - switch (expr->op()) {
|
| - case Token::COMMA:
|
| - VisitForEffect(expr->left());
|
| - Visit(expr->right());
|
| - break;
|
|
|
| - case Token::OR:
|
| - case Token::AND:
|
| - EmitLogicalOperation(expr);
|
| - break;
|
| -
|
| - case Token::ADD:
|
| - case Token::SUB:
|
| - case Token::DIV:
|
| - case Token::MOD:
|
| - case Token::MUL:
|
| - case Token::BIT_OR:
|
| - case Token::BIT_AND:
|
| - case Token::BIT_XOR:
|
| - case Token::SHL:
|
| - case Token::SHR:
|
| - case Token::SAR:
|
| - VisitForValue(expr->left(), kStack);
|
| - VisitForValue(expr->right(), kAccumulator);
|
| - EmitBinaryOp(expr->op(), context_);
|
| - break;
|
| -
|
| - default:
|
| - UNREACHABLE();
|
| - }
|
| -}
|
| -
|
| -
|
| void FullCodeGenerator::EmitNullCompare(bool strict,
|
| Register obj,
|
| Register null_const,
|
| @@ -3181,7 +2904,7 @@
|
| Register scratch) {
|
| __ cmpq(obj, null_const);
|
| if (strict) {
|
| - __ j(equal, if_true);
|
| + Split(equal, if_true, if_false, NULL);
|
| } else {
|
| __ j(equal, if_true);
|
| __ CompareRoot(obj, Heap::kUndefinedValueRootIndex);
|
| @@ -3191,9 +2914,8 @@
|
| __ movq(scratch, FieldOperand(obj, HeapObject::kMapOffset));
|
| __ testb(FieldOperand(scratch, Map::kBitFieldOffset),
|
| Immediate(1 << Map::kIsUndetectable));
|
| - __ j(not_zero, if_true);
|
| + Split(not_zero, if_true, if_false, NULL);
|
| }
|
| - __ jmp(if_false);
|
| }
|
|
|
|
|
| @@ -3213,8 +2935,7 @@
|
| VisitForValue(expr->right(), kStack);
|
| __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
|
| __ CompareRoot(rax, Heap::kTrueValueRootIndex);
|
| - __ j(equal, if_true);
|
| - __ jmp(if_false);
|
| + Split(equal, if_true, if_false, NULL);
|
| break;
|
|
|
| case Token::INSTANCEOF: {
|
| @@ -3222,8 +2943,8 @@
|
| InstanceofStub stub;
|
| __ CallStub(&stub);
|
| __ testq(rax, rax);
|
| - __ j(zero, if_true); // The stub returns 0 for true.
|
| - __ jmp(if_false);
|
| + // The stub returns 0 for true.
|
| + Split(zero, if_true, if_false, NULL);
|
| break;
|
| }
|
|
|
| @@ -3291,8 +3012,7 @@
|
| CompareStub stub(cc, strict);
|
| __ CallStub(&stub);
|
| __ testq(rax, rax);
|
| - __ j(cc, if_true);
|
| - __ jmp(if_false);
|
| + Split(cc, if_true, if_false, NULL);
|
| }
|
| }
|
|
|
|
|