| Index: runtime/vm/intermediate_language_x64.cc
 | 
| ===================================================================
 | 
| --- runtime/vm/intermediate_language_x64.cc	(revision 17245)
 | 
| +++ runtime/vm/intermediate_language_x64.cc	(working copy)
 | 
| @@ -1,4 +1,4 @@
 | 
| -// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 | 
| +// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 | 
|  // for details. All rights reserved. Use of this source code is governed by a
 | 
|  // BSD-style license that can be found in the LICENSE file.
 | 
|  
 | 
| @@ -8,6 +8,7 @@
 | 
|  #include "vm/intermediate_language.h"
 | 
|  
 | 
|  #include "lib/error.h"
 | 
| +#include "vm/dart_entry.h"
 | 
|  #include "vm/flow_graph_compiler.h"
 | 
|  #include "vm/locations.h"
 | 
|  #include "vm/object_store.h"
 | 
| @@ -274,8 +275,8 @@
 | 
|      const intptr_t kNumTemps =  0;
 | 
|      LocationSummary* locs =
 | 
|          new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
 | 
| -    locs->set_in(0, Location::RequiresXmmRegister());
 | 
| -    locs->set_in(1, Location::RequiresXmmRegister());
 | 
| +    locs->set_in(0, Location::RequiresFpuRegister());
 | 
| +    locs->set_in(1, Location::RequiresFpuRegister());
 | 
|      locs->set_out(Location::RequiresRegister());
 | 
|      return locs;
 | 
|    }
 | 
| @@ -338,7 +339,7 @@
 | 
|    const Array& kNoArgumentNames = Array::Handle();
 | 
|    const int kNumArgumentsChecked = 2;
 | 
|  
 | 
| -  const Immediate raw_null =
 | 
| +  const Immediate& raw_null =
 | 
|        Immediate(reinterpret_cast<intptr_t>(Object::null()));
 | 
|    Label check_identity;
 | 
|    __ cmpq(Address(RSP, 0 * kWordSize), raw_null);
 | 
| @@ -525,7 +526,7 @@
 | 
|    __ testq(left, Immediate(kSmiTagMask));
 | 
|    __ j(ZERO, deopt);
 | 
|    // 'left' is not Smi.
 | 
| -  const Immediate raw_null =
 | 
| +  const Immediate& raw_null =
 | 
|        Immediate(reinterpret_cast<intptr_t>(Object::null()));
 | 
|    Label identity_compare;
 | 
|    __ cmpq(right, raw_null);
 | 
| @@ -576,7 +577,7 @@
 | 
|    ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0));
 | 
|    Register left = locs->in(0).reg();
 | 
|    Register right = locs->in(1).reg();
 | 
| -  const Immediate raw_null =
 | 
| +  const Immediate& raw_null =
 | 
|        Immediate(reinterpret_cast<intptr_t>(Object::null()));
 | 
|    Label done, identity_compare, non_null_compare;
 | 
|    __ cmpq(right, raw_null);
 | 
| @@ -661,8 +662,8 @@
 | 
|                                     const LocationSummary& locs,
 | 
|                                     Token::Kind kind,
 | 
|                                     BranchInstr* branch) {
 | 
| -  XmmRegister left = locs.in(0).xmm_reg();
 | 
| -  XmmRegister right = locs.in(1).xmm_reg();
 | 
| +  XmmRegister left = locs.in(0).fpu_reg();
 | 
| +  XmmRegister right = locs.in(1).fpu_reg();
 | 
|  
 | 
|    Condition true_condition = TokenKindToDoubleCondition(kind);
 | 
|    if (branch != NULL) {
 | 
| @@ -764,8 +765,8 @@
 | 
|    if (operands_class_id() == kDoubleCid) {
 | 
|      LocationSummary* summary =
 | 
|          new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
 | 
| -    summary->set_in(0, Location::RequiresXmmRegister());
 | 
| -    summary->set_in(1, Location::RequiresXmmRegister());
 | 
| +    summary->set_in(0, Location::RequiresFpuRegister());
 | 
| +    summary->set_in(1, Location::RequiresFpuRegister());
 | 
|      summary->set_out(Location::RequiresRegister());
 | 
|      return summary;
 | 
|    } else if (operands_class_id() == kSmiCid) {
 | 
| @@ -1015,7 +1016,7 @@
 | 
|                      ? Location::RegisterOrSmiConstant(index())
 | 
|                      : Location::RequiresRegister());
 | 
|    if (representation() == kUnboxedDouble) {
 | 
| -    locs->set_out(Location::RequiresXmmRegister());
 | 
| +    locs->set_out(Location::RequiresFpuRegister());
 | 
|    } else {
 | 
|      locs->set_out(Location::RequiresRegister());
 | 
|    }
 | 
| @@ -1056,12 +1057,12 @@
 | 
|            class_id(), array, Smi::Cast(index.constant()).Value());
 | 
|  
 | 
|    if (representation() == kUnboxedDouble) {
 | 
| -    XmmRegister result = locs()->out().xmm_reg();
 | 
| +    XmmRegister result = locs()->out().fpu_reg();
 | 
|      if (class_id() == kFloat32ArrayCid) {
 | 
|        // Load single precision float.
 | 
|        __ movss(result, element_address);
 | 
|        // Promote to double.
 | 
| -      __ cvtss2sd(result, locs()->out().xmm_reg());
 | 
| +      __ cvtss2sd(result, locs()->out().fpu_reg());
 | 
|      } else {
 | 
|        ASSERT(class_id() == kFloat64ArrayCid);
 | 
|        __ movsd(result, element_address);
 | 
| @@ -1135,11 +1136,11 @@
 | 
|        break;
 | 
|      case kFloat32ArrayCid:
 | 
|        // Need temp register for float-to-double conversion.
 | 
| -      locs->AddTemp(Location::RequiresXmmRegister());
 | 
| +      locs->AddTemp(Location::RequiresFpuRegister());
 | 
|        // Fall through.
 | 
|      case kFloat64ArrayCid:
 | 
|        // TODO(srdjan): Support Float64 constants.
 | 
| -      locs->set_in(2, Location::RequiresXmmRegister());
 | 
| +      locs->set_in(2, Location::RequiresFpuRegister());
 | 
|        break;
 | 
|      default:
 | 
|        UNREACHABLE();
 | 
| @@ -1234,12 +1235,12 @@
 | 
|        }
 | 
|      case kFloat32ArrayCid:
 | 
|        // Convert to single precision.
 | 
| -      __ cvtsd2ss(locs()->temp(0).xmm_reg(), locs()->in(2).xmm_reg());
 | 
| +      __ cvtsd2ss(locs()->temp(0).fpu_reg(), locs()->in(2).fpu_reg());
 | 
|        // Store.
 | 
| -      __ movss(element_address, locs()->temp(0).xmm_reg());
 | 
| +      __ movss(element_address, locs()->temp(0).fpu_reg());
 | 
|        break;
 | 
|      case kFloat64ArrayCid:
 | 
| -      __ movsd(element_address, locs()->in(2).xmm_reg());
 | 
| +      __ movsd(element_address, locs()->in(2).fpu_reg());
 | 
|        break;
 | 
|      default:
 | 
|        UNREACHABLE();
 | 
| @@ -1444,7 +1445,7 @@
 | 
|    Label type_arguments_instantiated;
 | 
|    const intptr_t len = type_arguments().Length();
 | 
|    if (type_arguments().IsRawInstantiatedRaw(len)) {
 | 
| -    const Immediate raw_null =
 | 
| +    const Immediate& raw_null =
 | 
|          Immediate(reinterpret_cast<intptr_t>(Object::null()));
 | 
|      __ cmpq(instantiator_reg, raw_null);
 | 
|      __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump);
 | 
| @@ -1505,7 +1506,7 @@
 | 
|    Label type_arguments_instantiated;
 | 
|    const intptr_t len = type_arguments().Length();
 | 
|    if (type_arguments().IsRawInstantiatedRaw(len)) {
 | 
| -    const Immediate raw_null =
 | 
| +    const Immediate& raw_null =
 | 
|          Immediate(reinterpret_cast<intptr_t>(Object::null()));
 | 
|      __ cmpq(instantiator_reg, raw_null);
 | 
|      __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump);
 | 
| @@ -1519,7 +1520,7 @@
 | 
|      Label type_arguments_uninstantiated;
 | 
|      __ CompareClassId(instantiator_reg, kTypeArgumentsCid);
 | 
|      __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump);
 | 
| -    Immediate arguments_length =
 | 
| +    const Immediate& arguments_length =
 | 
|          Immediate(Smi::RawValue(type_arguments().Length()));
 | 
|      __ cmpq(FieldAddress(instantiator_reg, TypeArguments::length_offset()),
 | 
|          arguments_length);
 | 
| @@ -1559,7 +1560,7 @@
 | 
|    Label done;
 | 
|    const intptr_t len = type_arguments().Length();
 | 
|    if (type_arguments().IsRawInstantiatedRaw(len)) {
 | 
| -    const Immediate raw_null =
 | 
| +    const Immediate& raw_null =
 | 
|          Immediate(reinterpret_cast<intptr_t>(Object::null()));
 | 
|      Label instantiator_not_null;
 | 
|      __ cmpq(instantiator_reg, raw_null);
 | 
| @@ -1585,7 +1586,7 @@
 | 
|      // instantiator will have the wrong class (Null instead of TypeArguments).
 | 
|      __ CompareClassId(instantiator_reg, kTypeArgumentsCid);
 | 
|      __ j(NOT_EQUAL, &done, Assembler::kNearJump);
 | 
| -    Immediate arguments_length =
 | 
| +    const Immediate& arguments_length =
 | 
|          Immediate(Smi::RawValue(type_arguments().Length()));
 | 
|      __ cmpq(FieldAddress(instantiator_reg, TypeArguments::length_offset()),
 | 
|          arguments_length);
 | 
| @@ -2045,7 +2046,7 @@
 | 
|        new LocationSummary(kNumInputs,
 | 
|                            kNumTemps,
 | 
|                            LocationSummary::kCallOnSlowPath);
 | 
| -  summary->set_in(0, Location::RequiresXmmRegister());
 | 
| +  summary->set_in(0, Location::RequiresFpuRegister());
 | 
|    summary->set_out(Location::RequiresRegister());
 | 
|    return summary;
 | 
|  }
 | 
| @@ -2088,7 +2089,7 @@
 | 
|    compiler->AddSlowPathCode(slow_path);
 | 
|  
 | 
|    Register out_reg = locs()->out().reg();
 | 
| -  XmmRegister value = locs()->in(0).xmm_reg();
 | 
| +  XmmRegister value = locs()->in(0).fpu_reg();
 | 
|  
 | 
|    AssemblerMacros::TryAllocate(compiler->assembler(),
 | 
|                                 compiler->double_class(),
 | 
| @@ -2107,7 +2108,7 @@
 | 
|        new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
 | 
|    summary->set_in(0, Location::RequiresRegister());
 | 
|    if (CanDeoptimize()) summary->set_temp(0, Location::RequiresRegister());
 | 
| -  summary->set_out(Location::RequiresXmmRegister());
 | 
| +  summary->set_out(Location::RequiresFpuRegister());
 | 
|    return summary;
 | 
|  }
 | 
|  
 | 
| @@ -2115,7 +2116,7 @@
 | 
|  void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
 | 
|    const intptr_t value_cid = value()->ResultCid();
 | 
|    const Register value = locs()->in(0).reg();
 | 
| -  const XmmRegister result = locs()->out().xmm_reg();
 | 
| +  const XmmRegister result = locs()->out().fpu_reg();
 | 
|  
 | 
|    if (value_cid == kDoubleCid) {
 | 
|      __ movsd(result, FieldAddress(value, Double::value_offset()));
 | 
| @@ -2125,7 +2126,7 @@
 | 
|      __ SmiTag(value);  // Restore input register.
 | 
|    } else {
 | 
|      Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptBinaryDoubleOp);
 | 
| -    compiler->LoadDoubleOrSmiToXmm(result,
 | 
| +    compiler->LoadDoubleOrSmiToFpu(result,
 | 
|                                     value,
 | 
|                                     locs()->temp(0).reg(),
 | 
|                                     deopt);
 | 
| @@ -2138,18 +2139,18 @@
 | 
|    const intptr_t kNumTemps = 0;
 | 
|    LocationSummary* summary =
 | 
|        new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
 | 
| -  summary->set_in(0, Location::RequiresXmmRegister());
 | 
| -  summary->set_in(1, Location::RequiresXmmRegister());
 | 
| +  summary->set_in(0, Location::RequiresFpuRegister());
 | 
| +  summary->set_in(1, Location::RequiresFpuRegister());
 | 
|    summary->set_out(Location::SameAsFirstInput());
 | 
|    return summary;
 | 
|  }
 | 
|  
 | 
|  
 | 
|  void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
 | 
| -  XmmRegister left = locs()->in(0).xmm_reg();
 | 
| -  XmmRegister right = locs()->in(1).xmm_reg();
 | 
| +  XmmRegister left = locs()->in(0).fpu_reg();
 | 
| +  XmmRegister right = locs()->in(1).fpu_reg();
 | 
|  
 | 
| -  ASSERT(locs()->out().xmm_reg() == left);
 | 
| +  ASSERT(locs()->out().fpu_reg() == left);
 | 
|  
 | 
|    switch (op_kind()) {
 | 
|      case Token::kADD: __ addsd(left, right); break;
 | 
| @@ -2166,14 +2167,14 @@
 | 
|    const intptr_t kNumTemps = 0;
 | 
|    LocationSummary* summary =
 | 
|        new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
 | 
| -  summary->set_in(0, Location::RequiresXmmRegister());
 | 
| -  summary->set_out(Location::RequiresXmmRegister());
 | 
| +  summary->set_in(0, Location::RequiresFpuRegister());
 | 
| +  summary->set_out(Location::RequiresFpuRegister());
 | 
|    return summary;
 | 
|  }
 | 
|  
 | 
|  
 | 
|  void MathSqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
 | 
| -  __ sqrtsd(locs()->out().xmm_reg(), locs()->in(0).xmm_reg());
 | 
| +  __ sqrtsd(locs()->out().fpu_reg(), locs()->in(0).fpu_reg());
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -2298,7 +2299,7 @@
 | 
|    const intptr_t kNumTemps = 1;
 | 
|    LocationSummary* result = new LocationSummary(
 | 
|        kNumInputs, kNumTemps, LocationSummary::kNoCall);
 | 
| -  result->set_in(0, Location::RequiresXmmRegister());
 | 
| +  result->set_in(0, Location::RequiresFpuRegister());
 | 
|    result->set_out(Location:: Location::RequiresRegister());
 | 
|    result->set_temp(0, Location::RequiresRegister());
 | 
|    return result;
 | 
| @@ -2308,7 +2309,7 @@
 | 
|  void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
 | 
|    Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptDoubleToSmi);
 | 
|    Register result = locs()->out().reg();
 | 
| -  XmmRegister value = locs()->in(0).xmm_reg();
 | 
| +  XmmRegister value = locs()->in(0).fpu_reg();
 | 
|    Register temp = locs()->temp(0).reg();
 | 
|  
 | 
|    __ cvttsd2siq(result, value);
 | 
| @@ -2328,22 +2329,22 @@
 | 
|        (recognized_kind() == MethodRecognizer::kDoubleRound) ? 1 : 0;
 | 
|    LocationSummary* result =
 | 
|        new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
 | 
| -  result->set_in(0, Location::RequiresXmmRegister());
 | 
| -  result->set_out(Location::RequiresXmmRegister());
 | 
| +  result->set_in(0, Location::RequiresFpuRegister());
 | 
| +  result->set_out(Location::RequiresFpuRegister());
 | 
|    if (recognized_kind() == MethodRecognizer::kDoubleRound) {
 | 
| -    result->set_temp(0, Location::RequiresXmmRegister());
 | 
| +    result->set_temp(0, Location::RequiresFpuRegister());
 | 
|    }
 | 
|    return result;
 | 
|  }
 | 
|  
 | 
|  
 | 
|  void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
 | 
| -  XmmRegister value = locs()->in(0).xmm_reg();
 | 
| -  XmmRegister result = locs()->out().xmm_reg();
 | 
| +  XmmRegister value = locs()->in(0).fpu_reg();
 | 
| +  XmmRegister result = locs()->out().fpu_reg();
 | 
|    if (recognized_kind() == MethodRecognizer::kDoubleTruncate) {
 | 
|      __ roundsd(result, value,  Assembler::kRoundToZero);
 | 
|    } else {
 | 
| -    XmmRegister temp = locs()->temp(0).xmm_reg();
 | 
| +    XmmRegister temp = locs()->temp(0).fpu_reg();
 | 
|      __ DoubleRound(result, value, temp);
 | 
|    }
 | 
|  }
 | 
| @@ -2582,6 +2583,317 @@
 | 
|    UNIMPLEMENTED();
 | 
|  }
 | 
|  
 | 
| +
 | 
| +LocationSummary* ThrowInstr::MakeLocationSummary() const {
 | 
| +  return new LocationSummary(0, 0, LocationSummary::kCall);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
 | 
| +  compiler->GenerateCallRuntime(token_pos(),
 | 
| +                                kThrowRuntimeEntry,
 | 
| +                                locs());
 | 
| +  __ int3();
 | 
| +}
 | 
| +
 | 
| +
 | 
| +LocationSummary* ReThrowInstr::MakeLocationSummary() const {
 | 
| +  return new LocationSummary(0, 0, LocationSummary::kCall);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
 | 
| +  compiler->GenerateCallRuntime(token_pos(),
 | 
| +                                kReThrowRuntimeEntry,
 | 
| +                                locs());
 | 
| +  __ int3();
 | 
| +}
 | 
| +
 | 
| +
 | 
| +LocationSummary* GotoInstr::MakeLocationSummary() const {
 | 
| +  return new LocationSummary(0, 0, LocationSummary::kNoCall);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
 | 
| +  // Add deoptimization descriptor for deoptimizing instructions
 | 
| +  // that may be inserted before this instruction.
 | 
| +  if (!compiler->is_optimizing()) {
 | 
| +    compiler->AddCurrentDescriptor(PcDescriptors::kDeoptBefore,
 | 
| +                                   GetDeoptId(),
 | 
| +                                   0);  // No token position.
 | 
| +  }
 | 
| +
 | 
| +  if (HasParallelMove()) {
 | 
| +    compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
 | 
| +  }
 | 
| +
 | 
| +  // We can fall through if the successor is the next block in the list.
 | 
| +  // Otherwise, we need a jump.
 | 
| +  if (!compiler->IsNextBlock(successor())) {
 | 
| +    __ jmp(compiler->GetBlockLabel(successor()));
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +
 | 
| +static Condition NegateCondition(Condition condition) {
 | 
| +  switch (condition) {
 | 
| +    case EQUAL:         return NOT_EQUAL;
 | 
| +    case NOT_EQUAL:     return EQUAL;
 | 
| +    case LESS:          return GREATER_EQUAL;
 | 
| +    case LESS_EQUAL:    return GREATER;
 | 
| +    case GREATER:       return LESS_EQUAL;
 | 
| +    case GREATER_EQUAL: return LESS;
 | 
| +    case BELOW:         return ABOVE_EQUAL;
 | 
| +    case BELOW_EQUAL:   return ABOVE;
 | 
| +    case ABOVE:         return BELOW_EQUAL;
 | 
| +    case ABOVE_EQUAL:   return BELOW;
 | 
| +    default:
 | 
| +      OS::Print("Error %d\n", condition);
 | 
| +      UNIMPLEMENTED();
 | 
| +      return EQUAL;
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler,
 | 
| +                                           bool value) {
 | 
| +  if (value && compiler->IsNextBlock(false_successor())) {
 | 
| +    __ jmp(compiler->GetBlockLabel(true_successor()));
 | 
| +  } else if (!value && compiler->IsNextBlock(true_successor())) {
 | 
| +    __ jmp(compiler->GetBlockLabel(false_successor()));
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void ControlInstruction::EmitBranchOnCondition(FlowGraphCompiler* compiler,
 | 
| +                                               Condition true_condition) {
 | 
| +  if (compiler->IsNextBlock(false_successor())) {
 | 
| +    // If the next block is the false successor we will fall through to it.
 | 
| +    __ j(true_condition, compiler->GetBlockLabel(true_successor()));
 | 
| +  } else {
 | 
| +    // If the next block is the true successor we negate comparison and fall
 | 
| +    // through to it.
 | 
| +    ASSERT(compiler->IsNextBlock(true_successor()));
 | 
| +    Condition false_condition = NegateCondition(true_condition);
 | 
| +    __ j(false_condition, compiler->GetBlockLabel(false_successor()));
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +
 | 
| +LocationSummary* CurrentContextInstr::MakeLocationSummary() const {
 | 
| +  return LocationSummary::Make(0,
 | 
| +                               Location::RequiresRegister(),
 | 
| +                               LocationSummary::kNoCall);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void CurrentContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
 | 
| +  __ MoveRegister(locs()->out().reg(), CTX);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +LocationSummary* StrictCompareInstr::MakeLocationSummary() const {
 | 
| +  const intptr_t kNumInputs = 2;
 | 
| +  const intptr_t kNumTemps = 0;
 | 
| +  LocationSummary* locs =
 | 
| +      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
 | 
| +  locs->set_in(0, Location::RegisterOrConstant(left()));
 | 
| +  locs->set_in(1, Location::RegisterOrConstant(right()));
 | 
| +  locs->set_out(Location::RequiresRegister());
 | 
| +  return locs;
 | 
| +}
 | 
| +
 | 
| +
 | 
| +// Special code for numbers (compare values instead of references.)
 | 
| +void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
 | 
| +  ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
 | 
| +  Location left = locs()->in(0);
 | 
| +  Location right = locs()->in(1);
 | 
| +  if (left.IsConstant() && right.IsConstant()) {
 | 
| +    // TODO(vegorov): should be eliminated earlier by constant propagation.
 | 
| +    const bool result = (kind() == Token::kEQ_STRICT) ?
 | 
| +        left.constant().raw() == right.constant().raw() :
 | 
| +        left.constant().raw() != right.constant().raw();
 | 
| +    __ LoadObject(locs()->out().reg(), result ? Bool::True() : Bool::False());
 | 
| +    return;
 | 
| +  }
 | 
| +  if (left.IsConstant()) {
 | 
| +    compiler->EmitEqualityRegConstCompare(right.reg(),
 | 
| +                                          left.constant(),
 | 
| +                                          needs_number_check());
 | 
| +  } else if (right.IsConstant()) {
 | 
| +    compiler->EmitEqualityRegConstCompare(left.reg(),
 | 
| +                                          right.constant(),
 | 
| +                                          needs_number_check());
 | 
| +  } else {
 | 
| +    compiler->EmitEqualityRegRegCompare(left.reg(),
 | 
| +                                       right.reg(),
 | 
| +                                       needs_number_check());
 | 
| +  }
 | 
| +
 | 
| +  Register result = locs()->out().reg();
 | 
| +  Label load_true, done;
 | 
| +  Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL;
 | 
| +  __ j(true_condition, &load_true, Assembler::kNearJump);
 | 
| +  __ LoadObject(result, Bool::False());
 | 
| +  __ jmp(&done, Assembler::kNearJump);
 | 
| +  __ Bind(&load_true);
 | 
| +  __ LoadObject(result, Bool::True());
 | 
| +  __ Bind(&done);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
 | 
| +                                        BranchInstr* branch) {
 | 
| +  ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
 | 
| +  Location left = locs()->in(0);
 | 
| +  Location right = locs()->in(1);
 | 
| +  if (left.IsConstant() && right.IsConstant()) {
 | 
| +    // TODO(vegorov): should be eliminated earlier by constant propagation.
 | 
| +    const bool result = (kind() == Token::kEQ_STRICT) ?
 | 
| +        left.constant().raw() == right.constant().raw() :
 | 
| +        left.constant().raw() != right.constant().raw();
 | 
| +    branch->EmitBranchOnValue(compiler, result);
 | 
| +    return;
 | 
| +  }
 | 
| +  if (left.IsConstant()) {
 | 
| +    compiler->EmitEqualityRegConstCompare(right.reg(),
 | 
| +                                          left.constant(),
 | 
| +                                          needs_number_check());
 | 
| +  } else if (right.IsConstant()) {
 | 
| +    compiler->EmitEqualityRegConstCompare(left.reg(),
 | 
| +                                          right.constant(),
 | 
| +                                          needs_number_check());
 | 
| +  } else {
 | 
| +    compiler->EmitEqualityRegRegCompare(left.reg(),
 | 
| +                                        right.reg(),
 | 
| +                                        needs_number_check());
 | 
| +  }
 | 
| +
 | 
| +  Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL;
 | 
| +  branch->EmitBranchOnCondition(compiler, true_condition);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
 | 
| +  // The arguments to the stub include the closure, as does the arguments
 | 
| +  // descriptor.
 | 
| +  Register temp_reg = locs()->temp(0).reg();
 | 
| +  int argument_count = ArgumentCount();
 | 
| +  const Array& arguments_descriptor =
 | 
| +      Array::ZoneHandle(ArgumentsDescriptor::New(argument_count,
 | 
| +                                                 argument_names()));
 | 
| +  __ LoadObject(temp_reg, arguments_descriptor);
 | 
| +  compiler->GenerateDartCall(deopt_id(),
 | 
| +                             token_pos(),
 | 
| +                             &StubCode::CallClosureFunctionLabel(),
 | 
| +                             PcDescriptors::kOther,
 | 
| +                             locs());
 | 
| +  __ Drop(argument_count);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +LocationSummary* BooleanNegateInstr::MakeLocationSummary() const {
 | 
| +  return LocationSummary::Make(1,
 | 
| +                               Location::RequiresRegister(),
 | 
| +                               LocationSummary::kNoCall);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
 | 
| +  Register value = locs()->in(0).reg();
 | 
| +  Register result = locs()->out().reg();
 | 
| +
 | 
| +  Label done;
 | 
| +  __ LoadObject(result, Bool::True());
 | 
| +  __ CompareRegisters(result, value);
 | 
| +  __ j(NOT_EQUAL, &done, Assembler::kNearJump);
 | 
| +  __ LoadObject(result, Bool::False());
 | 
| +  __ Bind(&done);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +LocationSummary* ChainContextInstr::MakeLocationSummary() const {
 | 
| +  return LocationSummary::Make(1,
 | 
| +                               Location::NoLocation(),
 | 
| +                               LocationSummary::kNoCall);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void ChainContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
 | 
| +  Register context_value = locs()->in(0).reg();
 | 
| +
 | 
| +  // Chain the new context in context_value to its parent in CTX.
 | 
| +  __ StoreIntoObject(context_value,
 | 
| +                     FieldAddress(context_value, Context::parent_offset()),
 | 
| +                     CTX);
 | 
| +  // Set new context as current context.
 | 
| +  __ MoveRegister(CTX, context_value);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +LocationSummary* StoreVMFieldInstr::MakeLocationSummary() const {
 | 
| +  const intptr_t kNumInputs = 2;
 | 
| +  const intptr_t kNumTemps = 0;
 | 
| +  LocationSummary* locs =
 | 
| +      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
 | 
| +  locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister()
 | 
| +                                              : Location::RequiresRegister());
 | 
| +  locs->set_in(1, Location::RequiresRegister());
 | 
| +  return locs;
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void StoreVMFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
 | 
| +  Register value_reg = locs()->in(0).reg();
 | 
| +  Register dest_reg = locs()->in(1).reg();
 | 
| +
 | 
| +  if (value()->NeedsStoreBuffer()) {
 | 
| +    __ StoreIntoObject(dest_reg, FieldAddress(dest_reg, offset_in_bytes()),
 | 
| +                       value_reg);
 | 
| +  } else {
 | 
| +    __ StoreIntoObjectNoBarrier(
 | 
| +        dest_reg, FieldAddress(dest_reg, offset_in_bytes()), value_reg);
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +
 | 
| +LocationSummary* AllocateObjectInstr::MakeLocationSummary() const {
 | 
| +  return MakeCallSummary();
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
 | 
| +  const Class& cls = Class::ZoneHandle(constructor().Owner());
 | 
| +  const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls));
 | 
| +  const ExternalLabel label(cls.ToCString(), stub.EntryPoint());
 | 
| +  compiler->GenerateCall(token_pos(),
 | 
| +                         &label,
 | 
| +                         PcDescriptors::kOther,
 | 
| +                         locs());
 | 
| +  __ Drop(ArgumentCount());  // Discard arguments.
 | 
| +}
 | 
| +
 | 
| +
 | 
| +LocationSummary* CreateClosureInstr::MakeLocationSummary() const {
 | 
| +  return MakeCallSummary();
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void CreateClosureInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
 | 
| +  const Function& closure_function = function();
 | 
| +  ASSERT(!closure_function.IsImplicitStaticClosureFunction());
 | 
| +  const Code& stub = Code::Handle(
 | 
| +      StubCode::GetAllocationStubForClosure(closure_function));
 | 
| +  const ExternalLabel label(closure_function.ToCString(), stub.EntryPoint());
 | 
| +  compiler->GenerateCall(token_pos(),
 | 
| +                         &label,
 | 
| +                         PcDescriptors::kOther,
 | 
| +                         locs());
 | 
| +  __ Drop(2);  // Discard type arguments and receiver.
 | 
| +}
 | 
| +
 | 
|  }  // namespace dart
 | 
|  
 | 
|  #undef __
 | 
| 
 |