Chromium Code Reviews| Index: runtime/vm/intermediate_language_x64.cc |
| =================================================================== |
| --- runtime/vm/intermediate_language_x64.cc (revision 8478) |
| +++ runtime/vm/intermediate_language_x64.cc (working copy) |
| @@ -242,6 +242,149 @@ |
| } |
| +static Condition TokenKindToSmiCondition(Token::Kind kind) { |
| + switch (kind) { |
| + case Token::kEQ: return EQUAL; |
| + case Token::kNE: return NOT_EQUAL; |
| + case Token::kLT: return LESS; |
| + case Token::kGT: return GREATER; |
| + case Token::kLTE: return LESS_EQUAL; |
| + case Token::kGTE: return GREATER_EQUAL; |
| + default: |
| + UNREACHABLE(); |
| + return OVERFLOW; |
| + } |
| +} |
| + |
| + |
| +static void EmitSmiRelationalOp(FlowGraphCompiler* compiler, |
| + RelationalOpComp* comp) { |
| + Register left = comp->locs()->in(0).reg(); |
| + Register right = comp->locs()->in(1).reg(); |
| + Register result = comp->locs()->out().reg(); |
| + Label* deopt = compiler->AddDeoptStub(comp->cid(), |
| + comp->token_index(), |
| + comp->try_index(), |
| + kDeoptSmiCompareSmis, |
| + left, |
| + right); |
| + __ movq(TMP, left); |
| + __ orq(TMP, right); |
| + __ testq(TMP, Immediate(kSmiTagMask)); |
| + __ j(NOT_ZERO, deopt); |
| + const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
| + const Bool& bool_false = Bool::ZoneHandle(Bool::False()); |
| + Condition condition = TokenKindToSmiCondition(comp->kind()); |
| + |
| + Label done, is_true; |
| + __ cmpq(left, right); |
| + __ j(condition, &is_true); |
| + __ LoadObject(result, bool_false); |
| + __ jmp(&done); |
| + __ Bind(&is_true); |
| + __ LoadObject(result, bool_true); |
| + __ Bind(&done); |
| +} |
| + |
| + |
| +LocationSummary* RelationalOpComp::MakeLocationSummary() const { |
| + if (operands_class_id() == kSmi) { |
| + const intptr_t kNumInputs = 2; |
| + const intptr_t kNumTemps = 0; |
| + LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); |
| + summary->set_in(0, Location::RequiresRegister()); |
| + summary->set_in(1, Location::RequiresRegister()); |
| + summary->set_out(Location::RequiresRegister()); |
| + return summary; |
| + } |
| + if (operands_class_id() == kDouble) { |
| + const intptr_t kNumInputs = 2; |
| + const intptr_t kNumTemps = 1; |
| + LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); |
| + summary->set_in(0, Location::RequiresRegister()); |
| + summary->set_in(1, Location::RequiresRegister()); |
| + summary->set_out(Location::RequiresRegister()); |
| + summary->set_temp(0, Location::RequiresRegister()); |
| + return summary; |
| + } |
| + ASSERT(operands_class_id() == kObject); |
| + return MakeCallSummary(); |
| +} |
| + |
| + |
| + |
| +static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
| + switch (kind) { |
| + case Token::kEQ: return EQUAL; |
| + case Token::kLT: return BELOW; |
| + case Token::kGT: return ABOVE; |
| + case Token::kLTE: return BELOW_EQUAL; |
| + default: |
| + UNREACHABLE(); |
| + return OVERFLOW; |
| + } |
| +} |
| + |
| + |
| +static void EmitDoubleRelationalOp(FlowGraphCompiler* compiler, |
| + RelationalOpComp* comp) { |
| + Register left = comp->locs()->in(0).reg(); |
| + Register right = comp->locs()->in(1).reg(); |
| + Register result = comp->locs()->out().reg(); |
| + // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs. |
| + Register temp = comp->locs()->temp(0).reg(); |
| + Label* deopt = compiler->AddDeoptStub(comp->cid(), |
| + comp->token_index(), |
| + comp->try_index(), |
| + kDeoptDoubleComparison, |
| + left, |
| + right); |
| + compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); |
| + compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); |
| + const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
| + const Bool& bool_false = Bool::ZoneHandle(Bool::False()); |
| + Condition true_condition = TokenKindToDoubleCondition(comp->kind()); |
| + Label is_false, is_true, done; |
| + __ comisd(XMM0, XMM1); |
| + __ j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN -> false; |
| + __ j(true_condition, &is_true, Assembler::kNearJump); |
| + __ Bind(&is_false); |
| + __ LoadObject(result, bool_false); |
| + __ jmp(&done); |
| + __ Bind(&is_true); |
| + __ LoadObject(result, bool_true); |
| + __ Bind(&done); |
| +} |
| + |
| + |
| +void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| + if (operands_class_id() == kSmi) { |
| + EmitSmiRelationalOp(compiler, this); |
| + return; |
| + } |
| + if (operands_class_id() == kDouble) { |
| + EmitDoubleRelationalOp(compiler, this); |
| + return; |
| + } |
| + const String& function_name = |
| + String::ZoneHandle(String::NewSymbol(Token::Str(kind()))); |
| + compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| + cid(), |
| + token_index(), |
| + try_index()); |
| + const intptr_t kNumArguments = 2; |
| + const intptr_t kNumArgsChecked = 2; // Type-feedback. |
| + compiler->GenerateInstanceCall(cid(), |
| + token_index(), |
| + try_index(), |
| + function_name, |
| + kNumArguments, |
| + Array::ZoneHandle(), // No optional arguments. |
| + kNumArgsChecked); |
| + ASSERT(locs()->out().reg() == RAX); |
| +} |
| + |
| + |
| LocationSummary* NativeCallComp::MakeLocationSummary() const { |
| LocationSummary* locs = new LocationSummary(0, 3); |
| locs->set_temp(0, Location::RegisterLocation(RAX)); |
| @@ -864,6 +1007,25 @@ |
| } |
| +LocationSummary* CheckStackOverflowComp::MakeLocationSummary() const { |
| + return LocationSummary::Make(0, Location::NoLocation()); |
| +} |
| + |
| + |
| +void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| + // Generate stack overflow check. |
| + __ movq(TMP, Immediate(Isolate::Current()->stack_limit_address())); |
|
Vyacheslav Egorov (Google)
2012/06/11 12:51:21
I though we can use TMP only in the assembler itse
srdjan
2012/06/11 16:00:50
Yes, unfortunately, we are using TMP outside in se
|
| + __ cmpq(RSP, Address(TMP, 0)); |
| + Label no_stack_overflow; |
| + __ j(ABOVE, &no_stack_overflow, Assembler::kNearJump); |
| + compiler->GenerateCallRuntime(cid(), |
| + token_index(), |
| + try_index(), |
| + kStackOverflowRuntimeEntry); |
| + __ Bind(&no_stack_overflow); |
| +} |
| + |
| + |
| LocationSummary* BinaryOpComp::MakeLocationSummary() const { |
| const intptr_t kNumInputs = 2; |