| OLD | NEW | 
|     1 // Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file |     1 // Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file | 
|     2 // for details. All rights reserved. Use of this source code is governed by a |     2 // for details. All rights reserved. Use of this source code is governed by a | 
|     3 // BSD-style license that can be found in the LICENSE file. |     3 // BSD-style license that can be found in the LICENSE file. | 
|     4  |     4  | 
|     5 #include "vm/globals.h"  // Needed here to get TARGET_ARCH_ARM64. |     5 #include "vm/globals.h"  // Needed here to get TARGET_ARCH_ARM64. | 
|     6 #if defined(TARGET_ARCH_ARM64) |     6 #if defined(TARGET_ARCH_ARM64) | 
|     7  |     7  | 
|     8 #include "vm/intermediate_language.h" |     8 #include "vm/intermediate_language.h" | 
|     9  |     9  | 
|    10 #include "vm/compiler.h" |    10 #include "vm/compiler.h" | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
|    22 #include "vm/symbols.h" |    22 #include "vm/symbols.h" | 
|    23  |    23  | 
|    24 #define __ compiler->assembler()-> |    24 #define __ compiler->assembler()-> | 
|    25 #define Z (compiler->zone()) |    25 #define Z (compiler->zone()) | 
|    26  |    26  | 
|    27 namespace dart { |    27 namespace dart { | 
|    28  |    28  | 
|    29 // Generic summary for call instructions that have all arguments pushed |    29 // Generic summary for call instructions that have all arguments pushed | 
|    30 // on the stack and return the result in a fixed register R0. |    30 // on the stack and return the result in a fixed register R0. | 
|    31 LocationSummary* Instruction::MakeCallSummary(Zone* zone) { |    31 LocationSummary* Instruction::MakeCallSummary(Zone* zone) { | 
|    32   LocationSummary* result = new(zone) LocationSummary( |    32   LocationSummary* result = | 
|    33       zone, 0, 0, LocationSummary::kCall); |    33       new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); | 
|    34   result->set_out(0, Location::RegisterLocation(R0)); |    34   result->set_out(0, Location::RegisterLocation(R0)); | 
|    35   return result; |    35   return result; | 
|    36 } |    36 } | 
|    37  |    37  | 
|    38  |    38  | 
|    39 LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone, |    39 LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone, | 
|    40                                                         bool opt) const { |    40                                                         bool opt) const { | 
|    41   const intptr_t kNumInputs = 1; |    41   const intptr_t kNumInputs = 1; | 
|    42   const intptr_t kNumTemps = 0; |    42   const intptr_t kNumTemps = 0; | 
|    43   LocationSummary* locs = new(zone) LocationSummary( |    43   LocationSummary* locs = new (zone) | 
|    44       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |    44       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|    45   locs->set_in(0, Location::AnyOrConstant(value())); |    45   locs->set_in(0, Location::AnyOrConstant(value())); | 
|    46   return locs; |    46   return locs; | 
|    47 } |    47 } | 
|    48  |    48  | 
|    49  |    49  | 
|    50 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |    50 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|    51   // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode |    51   // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode | 
|    52   // where PushArgument is handled by BindInstr::EmitNativeCode. |    52   // where PushArgument is handled by BindInstr::EmitNativeCode. | 
|    53   if (compiler->is_optimizing()) { |    53   if (compiler->is_optimizing()) { | 
|    54     Location value = locs()->in(0); |    54     Location value = locs()->in(0); | 
|    55     if (value.IsRegister()) { |    55     if (value.IsRegister()) { | 
|    56       __ Push(value.reg()); |    56       __ Push(value.reg()); | 
|    57     } else if (value.IsConstant()) { |    57     } else if (value.IsConstant()) { | 
|    58       __ PushObject(value.constant()); |    58       __ PushObject(value.constant()); | 
|    59     } else { |    59     } else { | 
|    60       ASSERT(value.IsStackSlot()); |    60       ASSERT(value.IsStackSlot()); | 
|    61       const intptr_t value_offset = value.ToStackSlotOffset(); |    61       const intptr_t value_offset = value.ToStackSlotOffset(); | 
|    62       __ LoadFromOffset(TMP, value.base_reg(), value_offset); |    62       __ LoadFromOffset(TMP, value.base_reg(), value_offset); | 
|    63       __ Push(TMP); |    63       __ Push(TMP); | 
|    64     } |    64     } | 
|    65   } |    65   } | 
|    66 } |    66 } | 
|    67  |    67  | 
|    68  |    68  | 
|    69 LocationSummary* ReturnInstr::MakeLocationSummary(Zone* zone, |    69 LocationSummary* ReturnInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 
|    70                                                   bool opt) const { |  | 
|    71   const intptr_t kNumInputs = 1; |    70   const intptr_t kNumInputs = 1; | 
|    72   const intptr_t kNumTemps = 0; |    71   const intptr_t kNumTemps = 0; | 
|    73   LocationSummary* locs = new(zone) LocationSummary( |    72   LocationSummary* locs = new (zone) | 
|    74       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |    73       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|    75   locs->set_in(0, Location::RegisterLocation(R0)); |    74   locs->set_in(0, Location::RegisterLocation(R0)); | 
|    76   return locs; |    75   return locs; | 
|    77 } |    76 } | 
|    78  |    77  | 
|    79  |    78  | 
|    80 // Attempt optimized compilation at return instruction instead of at the entry. |    79 // Attempt optimized compilation at return instruction instead of at the entry. | 
|    81 // The entry needs to be patchable, no inlined objects are allowed in the area |    80 // The entry needs to be patchable, no inlined objects are allowed in the area | 
|    82 // that will be overwritten by the patch instructions: a branch macro sequence. |    81 // that will be overwritten by the patch instructions: a branch macro sequence. | 
|    83 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |    82 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|    84   const Register result = locs()->in(0).reg(); |    83   const Register result = locs()->in(0).reg(); | 
| (...skipping 21 matching lines...) Expand all  Loading... | 
|   106   __ LeaveDartFrame();  // Disallows constant pool use. |   105   __ LeaveDartFrame();  // Disallows constant pool use. | 
|   107   __ ret(); |   106   __ ret(); | 
|   108   // This ReturnInstr may be emitted out of order by the optimizer. The next |   107   // This ReturnInstr may be emitted out of order by the optimizer. The next | 
|   109   // block may be a target expecting a properly set constant pool pointer. |   108   // block may be a target expecting a properly set constant pool pointer. | 
|   110   __ set_constant_pool_allowed(true); |   109   __ set_constant_pool_allowed(true); | 
|   111 } |   110 } | 
|   112  |   111  | 
|   113  |   112  | 
|   114 static Condition NegateCondition(Condition condition) { |   113 static Condition NegateCondition(Condition condition) { | 
|   115   switch (condition) { |   114   switch (condition) { | 
|   116     case EQ: return NE; |   115     case EQ: | 
|   117     case NE: return EQ; |   116       return NE; | 
|   118     case LT: return GE; |   117     case NE: | 
|   119     case LE: return GT; |   118       return EQ; | 
|   120     case GT: return LE; |   119     case LT: | 
|   121     case GE: return LT; |   120       return GE; | 
|   122     case CC: return CS; |   121     case LE: | 
|   123     case LS: return HI; |   122       return GT; | 
|   124     case HI: return LS; |   123     case GT: | 
|   125     case CS: return CC; |   124       return LE; | 
|   126     case VS: return VC; |   125     case GE: | 
|   127     case VC: return VS; |   126       return LT; | 
 |   127     case CC: | 
 |   128       return CS; | 
 |   129     case LS: | 
 |   130       return HI; | 
 |   131     case HI: | 
 |   132       return LS; | 
 |   133     case CS: | 
 |   134       return CC; | 
 |   135     case VS: | 
 |   136       return VC; | 
 |   137     case VC: | 
 |   138       return VS; | 
|   128     default: |   139     default: | 
|   129       UNREACHABLE(); |   140       UNREACHABLE(); | 
|   130       return EQ; |   141       return EQ; | 
|   131   } |   142   } | 
|   132 } |   143 } | 
|   133  |   144  | 
|   134  |   145  | 
|   135 // Detect pattern when one value is zero and another is a power of 2. |   146 // Detect pattern when one value is zero and another is a power of 2. | 
|   136 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { |   147 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { | 
|   137   return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || |   148   return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || | 
|   138          (Utils::IsPowerOfTwo(v2) && (v1 == 0)); |   149          (Utils::IsPowerOfTwo(v2) && (v1 == 0)); | 
|   139 } |   150 } | 
|   140  |   151  | 
|   141  |   152  | 
|   142 LocationSummary* IfThenElseInstr::MakeLocationSummary(Zone* zone, |   153 LocationSummary* IfThenElseInstr::MakeLocationSummary(Zone* zone, | 
|   143                                                       bool opt) const { |   154                                                       bool opt) const { | 
|   144   comparison()->InitializeLocationSummary(zone, opt); |   155   comparison()->InitializeLocationSummary(zone, opt); | 
|   145   return comparison()->locs(); |   156   return comparison()->locs(); | 
|   146 } |   157 } | 
|   147  |   158  | 
|   148  |   159  | 
|   149 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |   160 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|   150   const Register result = locs()->out(0).reg(); |   161   const Register result = locs()->out(0).reg(); | 
|   151  |   162  | 
|   152   Location left = locs()->in(0); |   163   Location left = locs()->in(0); | 
|   153   Location right = locs()->in(1); |   164   Location right = locs()->in(1); | 
|   154   ASSERT(!left.IsConstant() || !right.IsConstant()); |   165   ASSERT(!left.IsConstant() || !right.IsConstant()); | 
|   155  |   166  | 
|   156   // Emit comparison code. This must not overwrite the result register. |   167   // Emit comparison code. This must not overwrite the result register. | 
|   157   BranchLabels labels = { NULL, NULL, NULL }; |   168   BranchLabels labels = {NULL, NULL, NULL}; | 
|   158   Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); |   169   Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); | 
|   159  |   170  | 
|   160   const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); |   171   const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); | 
|   161  |   172  | 
|   162   intptr_t true_value = if_true_; |   173   intptr_t true_value = if_true_; | 
|   163   intptr_t false_value = if_false_; |   174   intptr_t false_value = if_false_; | 
|   164  |   175  | 
|   165   if (is_power_of_two_kind) { |   176   if (is_power_of_two_kind) { | 
|   166     if (true_value == 0) { |   177     if (true_value == 0) { | 
|   167       // We need to have zero in result on true_condition. |   178       // We need to have zero in result on true_condition. | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
|   179   } |   190   } | 
|   180  |   191  | 
|   181   __ cset(result, true_condition); |   192   __ cset(result, true_condition); | 
|   182  |   193  | 
|   183   if (is_power_of_two_kind) { |   194   if (is_power_of_two_kind) { | 
|   184     const intptr_t shift = |   195     const intptr_t shift = | 
|   185         Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value)); |   196         Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value)); | 
|   186     __ LslImmediate(result, result, shift + kSmiTagSize); |   197     __ LslImmediate(result, result, shift + kSmiTagSize); | 
|   187   } else { |   198   } else { | 
|   188     __ sub(result, result, Operand(1)); |   199     __ sub(result, result, Operand(1)); | 
|   189     const int64_t val = |   200     const int64_t val = Smi::RawValue(true_value) - Smi::RawValue(false_value); | 
|   190         Smi::RawValue(true_value) - Smi::RawValue(false_value); |  | 
|   191     __ AndImmediate(result, result, val); |   201     __ AndImmediate(result, result, val); | 
|   192     if (false_value != 0) { |   202     if (false_value != 0) { | 
|   193       __ AddImmediate(result, result, Smi::RawValue(false_value)); |   203       __ AddImmediate(result, result, Smi::RawValue(false_value)); | 
|   194     } |   204     } | 
|   195   } |   205   } | 
|   196 } |   206 } | 
|   197  |   207  | 
|   198  |   208  | 
|   199 LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone, |   209 LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone, | 
|   200                                                        bool opt) const { |   210                                                        bool opt) const { | 
|   201   const intptr_t kNumInputs = 1; |   211   const intptr_t kNumInputs = 1; | 
|   202   const intptr_t kNumTemps = 0; |   212   const intptr_t kNumTemps = 0; | 
|   203   LocationSummary* summary = new(zone) LocationSummary( |   213   LocationSummary* summary = new (zone) | 
|   204       zone, kNumInputs, kNumTemps, LocationSummary::kCall); |   214       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 
|   205   summary->set_in(0, Location::RegisterLocation(R0));  // Function. |   215   summary->set_in(0, Location::RegisterLocation(R0));  // Function. | 
|   206   summary->set_out(0, Location::RegisterLocation(R0)); |   216   summary->set_out(0, Location::RegisterLocation(R0)); | 
|   207   return summary; |   217   return summary; | 
|   208 } |   218 } | 
|   209  |   219  | 
|   210  |   220  | 
|   211 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |   221 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|   212   // Load arguments descriptor in R4. |   222   // Load arguments descriptor in R4. | 
|   213   int argument_count = ArgumentCount(); |   223   int argument_count = ArgumentCount(); | 
|   214   const Array& arguments_descriptor = |   224   const Array& arguments_descriptor = Array::ZoneHandle( | 
|   215       Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, |   225       ArgumentsDescriptor::New(argument_count, argument_names())); | 
|   216                                                  argument_names())); |  | 
|   217   __ LoadObject(R4, arguments_descriptor); |   226   __ LoadObject(R4, arguments_descriptor); | 
|   218  |   227  | 
|   219   // R4: Arguments descriptor. |   228   // R4: Arguments descriptor. | 
|   220   // R0: Function. |   229   // R0: Function. | 
|   221   ASSERT(locs()->in(0).reg() == R0); |   230   ASSERT(locs()->in(0).reg() == R0); | 
|   222   __ LoadFieldFromOffset(CODE_REG, R0, Function::code_offset()); |   231   __ LoadFieldFromOffset(CODE_REG, R0, Function::code_offset()); | 
|   223   __ LoadFieldFromOffset(R2, R0, Function::entry_point_offset()); |   232   __ LoadFieldFromOffset(R2, R0, Function::entry_point_offset()); | 
|   224  |   233  | 
|   225   // R2: instructions. |   234   // R2: instructions. | 
|   226   // R5: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value). |   235   // R5: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value). | 
|   227   __ LoadImmediate(R5, 0); |   236   __ LoadImmediate(R5, 0); | 
|   228   //?? |   237   //?? | 
|   229   __ blr(R2); |   238   __ blr(R2); | 
|   230   compiler->RecordSafepoint(locs()); |   239   compiler->RecordSafepoint(locs()); | 
|   231   // Marks either the continuation point in unoptimized code or the |   240   // Marks either the continuation point in unoptimized code or the | 
|   232   // deoptimization point in optimized code, after call. |   241   // deoptimization point in optimized code, after call. | 
|   233   const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id()); |   242   const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id()); | 
|   234   if (compiler->is_optimizing()) { |   243   if (compiler->is_optimizing()) { | 
|   235     compiler->AddDeoptIndexAtCall(deopt_id_after); |   244     compiler->AddDeoptIndexAtCall(deopt_id_after); | 
|   236   } |   245   } | 
|   237   // Add deoptimization continuation point after the call and before the |   246   // Add deoptimization continuation point after the call and before the | 
|   238   // arguments are removed. |   247   // arguments are removed. | 
|   239   // In optimized code this descriptor is needed for exception handling. |   248   // In optimized code this descriptor is needed for exception handling. | 
|   240   compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, |   249   compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, | 
|   241                                  deopt_id_after, |  | 
|   242                                  token_pos()); |   250                                  token_pos()); | 
|   243   __ Drop(argument_count); |   251   __ Drop(argument_count); | 
|   244 } |   252 } | 
|   245  |   253  | 
|   246  |   254  | 
|   247 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone, |   255 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone, | 
|   248                                                      bool opt) const { |   256                                                      bool opt) const { | 
|   249   return LocationSummary::Make(zone, |   257   return LocationSummary::Make(zone, 0, Location::RequiresRegister(), | 
|   250                                0, |  | 
|   251                                Location::RequiresRegister(), |  | 
|   252                                LocationSummary::kNoCall); |   258                                LocationSummary::kNoCall); | 
|   253 } |   259 } | 
|   254  |   260  | 
|   255  |   261  | 
|   256 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |   262 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|   257   const Register result = locs()->out(0).reg(); |   263   const Register result = locs()->out(0).reg(); | 
|   258   __ LoadFromOffset(result, FP, local().index() * kWordSize); |   264   __ LoadFromOffset(result, FP, local().index() * kWordSize); | 
|   259 } |   265 } | 
|   260  |   266  | 
|   261  |   267  | 
|   262 LocationSummary* StoreLocalInstr::MakeLocationSummary(Zone* zone, |   268 LocationSummary* StoreLocalInstr::MakeLocationSummary(Zone* zone, | 
|   263                                                       bool opt) const { |   269                                                       bool opt) const { | 
|   264   return LocationSummary::Make(zone, |   270   return LocationSummary::Make(zone, 1, Location::SameAsFirstInput(), | 
|   265                                1, |  | 
|   266                                Location::SameAsFirstInput(), |  | 
|   267                                LocationSummary::kNoCall); |   271                                LocationSummary::kNoCall); | 
|   268 } |   272 } | 
|   269  |   273  | 
|   270  |   274  | 
|   271 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |   275 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|   272   const Register value = locs()->in(0).reg(); |   276   const Register value = locs()->in(0).reg(); | 
|   273   const Register result = locs()->out(0).reg(); |   277   const Register result = locs()->out(0).reg(); | 
|   274   ASSERT(result == value);  // Assert that register assignment is correct. |   278   ASSERT(result == value);  // Assert that register assignment is correct. | 
|   275   __ StoreToOffset(value, FP, local().index() * kWordSize); |   279   __ StoreToOffset(value, FP, local().index() * kWordSize); | 
|   276 } |   280 } | 
|   277  |   281  | 
|   278  |   282  | 
|   279 LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone, |   283 LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone, | 
|   280                                                     bool opt) const { |   284                                                     bool opt) const { | 
|   281   return LocationSummary::Make(zone, |   285   return LocationSummary::Make(zone, 0, Location::RequiresRegister(), | 
|   282                                0, |  | 
|   283                                Location::RequiresRegister(), |  | 
|   284                                LocationSummary::kNoCall); |   286                                LocationSummary::kNoCall); | 
|   285 } |   287 } | 
|   286  |   288  | 
|   287  |   289  | 
|   288 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |   290 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|   289   // The register allocator drops constant definitions that have no uses. |   291   // The register allocator drops constant definitions that have no uses. | 
|   290   if (!locs()->out(0).IsInvalid()) { |   292   if (!locs()->out(0).IsInvalid()) { | 
|   291     const Register result = locs()->out(0).reg(); |   293     const Register result = locs()->out(0).reg(); | 
|   292     __ LoadObject(result, value()); |   294     __ LoadObject(result, value()); | 
|   293   } |   295   } | 
|   294 } |   296 } | 
|   295  |   297  | 
|   296  |   298  | 
|   297 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, |   299 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, | 
|   298                                                            bool opt) const { |   300                                                            bool opt) const { | 
|   299   const intptr_t kNumInputs = 0; |   301   const intptr_t kNumInputs = 0; | 
|   300   const Location out = (representation_ == kUnboxedInt32) ? |   302   const Location out = (representation_ == kUnboxedInt32) | 
|   301       Location::RequiresRegister() : Location::RequiresFpuRegister(); |   303                            ? Location::RequiresRegister() | 
|   302   return LocationSummary::Make(zone, |   304                            : Location::RequiresFpuRegister(); | 
|   303                                kNumInputs, |   305   return LocationSummary::Make(zone, kNumInputs, out, LocationSummary::kNoCall); | 
|   304                                out, |  | 
|   305                                LocationSummary::kNoCall); |  | 
|   306 } |   306 } | 
|   307  |   307  | 
|   308  |   308  | 
|   309 void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |   309 void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|   310   if (!locs()->out(0).IsInvalid()) { |   310   if (!locs()->out(0).IsInvalid()) { | 
|   311     switch (representation_) { |   311     switch (representation_) { | 
|   312       case kUnboxedDouble: |   312       case kUnboxedDouble: | 
|   313         if (Utils::DoublesBitEqual(Double::Cast(value()).value(), 0.0)) { |   313         if (Utils::DoublesBitEqual(Double::Cast(value()).value(), 0.0)) { | 
|   314           const VRegister dst = locs()->out(0).fpu_reg(); |   314           const VRegister dst = locs()->out(0).fpu_reg(); | 
|   315           __ veor(dst, dst, dst); |   315           __ veor(dst, dst, dst); | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
|   327         break; |   327         break; | 
|   328     } |   328     } | 
|   329   } |   329   } | 
|   330 } |   330 } | 
|   331  |   331  | 
|   332  |   332  | 
|   333 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone, |   333 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone, | 
|   334                                                             bool opt) const { |   334                                                             bool opt) const { | 
|   335   const intptr_t kNumInputs = 2; |   335   const intptr_t kNumInputs = 2; | 
|   336   const intptr_t kNumTemps = 0; |   336   const intptr_t kNumTemps = 0; | 
|   337   LocationSummary* summary = new(zone) LocationSummary( |   337   LocationSummary* summary = new (zone) | 
|   338       zone, kNumInputs, kNumTemps, LocationSummary::kCall); |   338       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 
|   339   summary->set_in(0, Location::RegisterLocation(R0));  // Value. |   339   summary->set_in(0, Location::RegisterLocation(R0));  // Value. | 
|   340   summary->set_in(1, Location::RegisterLocation(R1));  // Type arguments. |   340   summary->set_in(1, Location::RegisterLocation(R1));  // Type arguments. | 
|   341   summary->set_out(0, Location::RegisterLocation(R0)); |   341   summary->set_out(0, Location::RegisterLocation(R0)); | 
|   342   return summary; |   342   return summary; | 
|   343 } |   343 } | 
|   344  |   344  | 
|   345  |   345  | 
|   346 LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone, |   346 LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone, | 
|   347                                                          bool opt) const { |   347                                                          bool opt) const { | 
|   348   const intptr_t kNumInputs = 1; |   348   const intptr_t kNumInputs = 1; | 
|   349   const intptr_t kNumTemps = 0; |   349   const intptr_t kNumTemps = 0; | 
|   350   LocationSummary* locs = new(zone) LocationSummary( |   350   LocationSummary* locs = new (zone) | 
|   351       zone, kNumInputs, kNumTemps, LocationSummary::kCall); |   351       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 
|   352   locs->set_in(0, Location::RegisterLocation(R0)); |   352   locs->set_in(0, Location::RegisterLocation(R0)); | 
|   353   locs->set_out(0, Location::RegisterLocation(R0)); |   353   locs->set_out(0, Location::RegisterLocation(R0)); | 
|   354   return locs; |   354   return locs; | 
|   355 } |   355 } | 
|   356  |   356  | 
|   357  |   357  | 
|   358 static void EmitAssertBoolean(Register reg, |   358 static void EmitAssertBoolean(Register reg, | 
|   359                               TokenPosition token_pos, |   359                               TokenPosition token_pos, | 
|   360                               intptr_t deopt_id, |   360                               intptr_t deopt_id, | 
|   361                               LocationSummary* locs, |   361                               LocationSummary* locs, | 
|   362                               FlowGraphCompiler* compiler) { |   362                               FlowGraphCompiler* compiler) { | 
|   363   // Check that the type of the value is allowed in conditional context. |   363   // Check that the type of the value is allowed in conditional context. | 
|   364   // Call the runtime if the object is not bool::true or bool::false. |   364   // Call the runtime if the object is not bool::true or bool::false. | 
|   365   ASSERT(locs->always_calls()); |   365   ASSERT(locs->always_calls()); | 
|   366   Label done; |   366   Label done; | 
|   367  |   367  | 
|   368   if (Isolate::Current()->type_checks()) { |   368   if (Isolate::Current()->type_checks()) { | 
|   369     __ CompareObject(reg, Bool::True()); |   369     __ CompareObject(reg, Bool::True()); | 
|   370     __ b(&done, EQ); |   370     __ b(&done, EQ); | 
|   371     __ CompareObject(reg, Bool::False()); |   371     __ CompareObject(reg, Bool::False()); | 
|   372     __ b(&done, EQ); |   372     __ b(&done, EQ); | 
|   373   } else { |   373   } else { | 
|   374     ASSERT(Isolate::Current()->asserts()); |   374     ASSERT(Isolate::Current()->asserts()); | 
|   375     __ CompareObject(reg, Object::null_instance()); |   375     __ CompareObject(reg, Object::null_instance()); | 
|   376     __ b(&done, NE); |   376     __ b(&done, NE); | 
|   377   } |   377   } | 
|   378  |   378  | 
|   379   __ Push(reg);  // Push the source object. |   379   __ Push(reg);  // Push the source object. | 
|   380   compiler->GenerateRuntimeCall(token_pos, |   380   compiler->GenerateRuntimeCall(token_pos, deopt_id, | 
|   381                                 deopt_id, |   381                                 kNonBoolTypeErrorRuntimeEntry, 1, locs); | 
|   382                                 kNonBoolTypeErrorRuntimeEntry, |  | 
|   383                                 1, |  | 
|   384                                 locs); |  | 
|   385   // We should never return here. |   382   // We should never return here. | 
|   386   __ brk(0); |   383   __ brk(0); | 
|   387   __ Bind(&done); |   384   __ Bind(&done); | 
|   388 } |   385 } | 
|   389  |   386  | 
|   390  |   387  | 
|   391 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |   388 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|   392   const Register obj = locs()->in(0).reg(); |   389   const Register obj = locs()->in(0).reg(); | 
|   393   const Register result = locs()->out(0).reg(); |   390   const Register result = locs()->out(0).reg(); | 
|   394  |   391  | 
|   395   EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); |   392   EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); | 
|   396   ASSERT(obj == result); |   393   ASSERT(obj == result); | 
|   397 } |   394 } | 
|   398  |   395  | 
|   399  |   396  | 
|   400 static Condition TokenKindToSmiCondition(Token::Kind kind) { |   397 static Condition TokenKindToSmiCondition(Token::Kind kind) { | 
|   401   switch (kind) { |   398   switch (kind) { | 
|   402     case Token::kEQ: return EQ; |   399     case Token::kEQ: | 
|   403     case Token::kNE: return NE; |   400       return EQ; | 
|   404     case Token::kLT: return LT; |   401     case Token::kNE: | 
|   405     case Token::kGT: return GT; |   402       return NE; | 
|   406     case Token::kLTE: return LE; |   403     case Token::kLT: | 
|   407     case Token::kGTE: return GE; |   404       return LT; | 
 |   405     case Token::kGT: | 
 |   406       return GT; | 
 |   407     case Token::kLTE: | 
 |   408       return LE; | 
 |   409     case Token::kGTE: | 
 |   410       return GE; | 
|   408     default: |   411     default: | 
|   409       UNREACHABLE(); |   412       UNREACHABLE(); | 
|   410       return VS; |   413       return VS; | 
|   411   } |   414   } | 
|   412 } |   415 } | 
|   413  |   416  | 
|   414  |   417  | 
|   415 static Condition FlipCondition(Condition condition) { |   418 static Condition FlipCondition(Condition condition) { | 
|   416   switch (condition) { |   419   switch (condition) { | 
|   417     case EQ: return EQ; |   420     case EQ: | 
|   418     case NE: return NE; |   421       return EQ; | 
|   419     case LT: return GT; |   422     case NE: | 
|   420     case LE: return GE; |   423       return NE; | 
|   421     case GT: return LT; |   424     case LT: | 
|   422     case GE: return LE; |   425       return GT; | 
|   423     case CC: return HI; |   426     case LE: | 
|   424     case LS: return CS; |   427       return GE; | 
|   425     case HI: return CC; |   428     case GT: | 
|   426     case CS: return LS; |   429       return LT; | 
 |   430     case GE: | 
 |   431       return LE; | 
 |   432     case CC: | 
 |   433       return HI; | 
 |   434     case LS: | 
 |   435       return CS; | 
 |   436     case HI: | 
 |   437       return CC; | 
 |   438     case CS: | 
 |   439       return LS; | 
|   427     default: |   440     default: | 
|   428       UNREACHABLE(); |   441       UNREACHABLE(); | 
|   429       return EQ; |   442       return EQ; | 
|   430   } |   443   } | 
|   431 } |   444 } | 
|   432  |   445  | 
|   433  |   446  | 
|   434 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, |   447 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, | 
|   435                                   Condition true_condition, |   448                                   Condition true_condition, | 
|   436                                   BranchLabels labels) { |   449                                   BranchLabels labels) { | 
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   468     __ CompareRegisters(left.reg(), right.reg()); |   481     __ CompareRegisters(left.reg(), right.reg()); | 
|   469   } |   482   } | 
|   470   return true_condition; |   483   return true_condition; | 
|   471 } |   484 } | 
|   472  |   485  | 
|   473  |   486  | 
|   474 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Zone* zone, |   487 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Zone* zone, | 
|   475                                                            bool opt) const { |   488                                                            bool opt) const { | 
|   476   const intptr_t kNumInputs = 2; |   489   const intptr_t kNumInputs = 2; | 
|   477   if (operation_cid() == kDoubleCid) { |   490   if (operation_cid() == kDoubleCid) { | 
|   478     const intptr_t kNumTemps =  0; |   491     const intptr_t kNumTemps = 0; | 
|   479     LocationSummary* locs = new(zone) LocationSummary( |   492     LocationSummary* locs = new (zone) | 
|   480         zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |   493         LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|   481     locs->set_in(0, Location::RequiresFpuRegister()); |   494     locs->set_in(0, Location::RequiresFpuRegister()); | 
|   482     locs->set_in(1, Location::RequiresFpuRegister()); |   495     locs->set_in(1, Location::RequiresFpuRegister()); | 
|   483     locs->set_out(0, Location::RequiresRegister()); |   496     locs->set_out(0, Location::RequiresRegister()); | 
|   484     return locs; |   497     return locs; | 
|   485   } |   498   } | 
|   486   if (operation_cid() == kSmiCid) { |   499   if (operation_cid() == kSmiCid) { | 
|   487     const intptr_t kNumTemps = 0; |   500     const intptr_t kNumTemps = 0; | 
|   488     LocationSummary* locs = new(zone) LocationSummary( |   501     LocationSummary* locs = new (zone) | 
|   489         zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |   502         LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|   490     locs->set_in(0, Location::RegisterOrConstant(left())); |   503     locs->set_in(0, Location::RegisterOrConstant(left())); | 
|   491     // Only one input can be a constant operand. The case of two constant |   504     // Only one input can be a constant operand. The case of two constant | 
|   492     // operands should be handled by constant propagation. |   505     // operands should be handled by constant propagation. | 
|   493     // Only right can be a stack slot. |   506     // Only right can be a stack slot. | 
|   494     locs->set_in(1, locs->in(0).IsConstant() |   507     locs->set_in(1, locs->in(0).IsConstant() | 
|   495                         ? Location::RequiresRegister() |   508                         ? Location::RequiresRegister() | 
|   496                         : Location::RegisterOrConstant(right())); |   509                         : Location::RegisterOrConstant(right())); | 
|   497     locs->set_out(0, Location::RequiresRegister()); |   510     locs->set_out(0, Location::RequiresRegister()); | 
|   498     return locs; |   511     return locs; | 
|   499   } |   512   } | 
|   500   UNREACHABLE(); |   513   UNREACHABLE(); | 
|   501   return NULL; |   514   return NULL; | 
|   502 } |   515 } | 
|   503  |   516  | 
|   504  |   517  | 
|   505 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |   518 static Condition TokenKindToDoubleCondition(Token::Kind kind) { | 
|   506   switch (kind) { |   519   switch (kind) { | 
|   507     case Token::kEQ: return EQ; |   520     case Token::kEQ: | 
|   508     case Token::kNE: return NE; |   521       return EQ; | 
|   509     case Token::kLT: return LT; |   522     case Token::kNE: | 
|   510     case Token::kGT: return GT; |   523       return NE; | 
|   511     case Token::kLTE: return LE; |   524     case Token::kLT: | 
|   512     case Token::kGTE: return GE; |   525       return LT; | 
 |   526     case Token::kGT: | 
 |   527       return GT; | 
 |   528     case Token::kLTE: | 
 |   529       return LE; | 
 |   530     case Token::kGTE: | 
 |   531       return GE; | 
|   513     default: |   532     default: | 
|   514       UNREACHABLE(); |   533       UNREACHABLE(); | 
|   515       return VS; |   534       return VS; | 
|   516   } |   535   } | 
|   517 } |   536 } | 
|   518  |   537  | 
|   519  |   538  | 
|   520 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |   539 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | 
|   521                                         LocationSummary* locs, |   540                                         LocationSummary* locs, | 
|   522                                         Token::Kind kind) { |   541                                         Token::Kind kind) { | 
| (...skipping 12 matching lines...) Expand all  Loading... | 
|   535   } else { |   554   } else { | 
|   536     ASSERT(operation_cid() == kDoubleCid); |   555     ASSERT(operation_cid() == kDoubleCid); | 
|   537     return EmitDoubleComparisonOp(compiler, locs(), kind()); |   556     return EmitDoubleComparisonOp(compiler, locs(), kind()); | 
|   538   } |   557   } | 
|   539 } |   558 } | 
|   540  |   559  | 
|   541  |   560  | 
|   542 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |   561 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|   543   ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); |   562   ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); | 
|   544   Label is_true, is_false; |   563   Label is_true, is_false; | 
|   545   BranchLabels labels = { &is_true, &is_false, &is_false }; |   564   BranchLabels labels = {&is_true, &is_false, &is_false}; | 
|   546   Condition true_condition = EmitComparisonCode(compiler, labels); |   565   Condition true_condition = EmitComparisonCode(compiler, labels); | 
|   547   if ((operation_cid() == kDoubleCid) && (true_condition != NE)) { |   566   if ((operation_cid() == kDoubleCid) && (true_condition != NE)) { | 
|   548     // Special case for NaN comparison. Result is always false unless |   567     // Special case for NaN comparison. Result is always false unless | 
|   549     // relational operator is !=. |   568     // relational operator is !=. | 
|   550     __ b(&is_false, VS); |   569     __ b(&is_false, VS); | 
|   551   } |   570   } | 
|   552   EmitBranchOnCondition(compiler, true_condition, labels); |   571   EmitBranchOnCondition(compiler, true_condition, labels); | 
|   553   // TODO(zra): instead of branching, use the csel instruction to get |   572   // TODO(zra): instead of branching, use the csel instruction to get | 
|   554   // True or False into result. |   573   // True or False into result. | 
|   555   const Register result = locs()->out(0).reg(); |   574   const Register result = locs()->out(0).reg(); | 
| (...skipping 15 matching lines...) Expand all  Loading... | 
|   571   Condition true_condition = EmitComparisonCode(compiler, labels); |   590   Condition true_condition = EmitComparisonCode(compiler, labels); | 
|   572   if ((operation_cid() == kDoubleCid) && (true_condition != NE)) { |   591   if ((operation_cid() == kDoubleCid) && (true_condition != NE)) { | 
|   573     // Special case for NaN comparison. Result is always false unless |   592     // Special case for NaN comparison. Result is always false unless | 
|   574     // relational operator is !=. |   593     // relational operator is !=. | 
|   575     __ b(labels.false_label, VS); |   594     __ b(labels.false_label, VS); | 
|   576   } |   595   } | 
|   577   EmitBranchOnCondition(compiler, true_condition, labels); |   596   EmitBranchOnCondition(compiler, true_condition, labels); | 
|   578 } |   597 } | 
|   579  |   598  | 
|   580  |   599  | 
|   581 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, |   600 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 
|   582                                                    bool opt) const { |  | 
|   583   const intptr_t kNumInputs = 2; |   601   const intptr_t kNumInputs = 2; | 
|   584   const intptr_t kNumTemps = 0; |   602   const intptr_t kNumTemps = 0; | 
|   585   LocationSummary* locs = new(zone) LocationSummary( |   603   LocationSummary* locs = new (zone) | 
|   586       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |   604       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|   587   locs->set_in(0, Location::RequiresRegister()); |   605   locs->set_in(0, Location::RequiresRegister()); | 
|   588   // Only one input can be a constant operand. The case of two constant |   606   // Only one input can be a constant operand. The case of two constant | 
|   589   // operands should be handled by constant propagation. |   607   // operands should be handled by constant propagation. | 
|   590   locs->set_in(1, Location::RegisterOrConstant(right())); |   608   locs->set_in(1, Location::RegisterOrConstant(right())); | 
|   591   return locs; |   609   return locs; | 
|   592 } |   610 } | 
|   593  |   611  | 
|   594  |   612  | 
|   595 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |   613 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 
|   596                                            BranchLabels labels) { |   614                                            BranchLabels labels) { | 
|   597   const Register left = locs()->in(0).reg(); |   615   const Register left = locs()->in(0).reg(); | 
|   598   Location right = locs()->in(1); |   616   Location right = locs()->in(1); | 
|   599   if (right.IsConstant()) { |   617   if (right.IsConstant()) { | 
|   600     ASSERT(right.constant().IsSmi()); |   618     ASSERT(right.constant().IsSmi()); | 
|   601     const int64_t imm = |   619     const int64_t imm = reinterpret_cast<int64_t>(right.constant().raw()); | 
|   602         reinterpret_cast<int64_t>(right.constant().raw()); |  | 
|   603     __ TestImmediate(left, imm); |   620     __ TestImmediate(left, imm); | 
|   604   } else { |   621   } else { | 
|   605     __ tst(left, Operand(right.reg())); |   622     __ tst(left, Operand(right.reg())); | 
|   606   } |   623   } | 
|   607   Condition true_condition = (kind() == Token::kNE) ? NE : EQ; |   624   Condition true_condition = (kind() == Token::kNE) ? NE : EQ; | 
|   608   return true_condition; |   625   return true_condition; | 
|   609 } |   626 } | 
|   610  |   627  | 
|   611  |   628  | 
|   612 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |   629 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|   613   // Never emitted outside of the BranchInstr. |   630   // Never emitted outside of the BranchInstr. | 
|   614   UNREACHABLE(); |   631   UNREACHABLE(); | 
|   615 } |   632 } | 
|   616  |   633  | 
|   617  |   634  | 
|   618 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, |   635 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 
|   619                                   BranchInstr* branch) { |   636                                   BranchInstr* branch) { | 
|   620   BranchLabels labels = compiler->CreateBranchLabels(branch); |   637   BranchLabels labels = compiler->CreateBranchLabels(branch); | 
|   621   Condition true_condition = EmitComparisonCode(compiler, labels); |   638   Condition true_condition = EmitComparisonCode(compiler, labels); | 
|   622   EmitBranchOnCondition(compiler, true_condition, labels); |   639   EmitBranchOnCondition(compiler, true_condition, labels); | 
|   623 } |   640 } | 
|   624  |   641  | 
|   625  |   642  | 
|   626 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, |   643 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, | 
|   627                                                     bool opt) const { |   644                                                     bool opt) const { | 
|   628   const intptr_t kNumInputs = 1; |   645   const intptr_t kNumInputs = 1; | 
|   629   const intptr_t kNumTemps = 1; |   646   const intptr_t kNumTemps = 1; | 
|   630   LocationSummary* locs = new(zone) LocationSummary( |   647   LocationSummary* locs = new (zone) | 
|   631       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |   648       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|   632   locs->set_in(0, Location::RequiresRegister()); |   649   locs->set_in(0, Location::RequiresRegister()); | 
|   633   locs->set_temp(0, Location::RequiresRegister()); |   650   locs->set_temp(0, Location::RequiresRegister()); | 
|   634   locs->set_out(0, Location::RequiresRegister()); |   651   locs->set_out(0, Location::RequiresRegister()); | 
|   635   return locs; |   652   return locs; | 
|   636 } |   653 } | 
|   637  |   654  | 
|   638  |   655  | 
|   639 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |   656 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 
|   640                                             BranchLabels labels) { |   657                                             BranchLabels labels) { | 
|   641   ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); |   658   ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); | 
|   642   const Register val_reg = locs()->in(0).reg(); |   659   const Register val_reg = locs()->in(0).reg(); | 
|   643   const Register cid_reg = locs()->temp(0).reg(); |   660   const Register cid_reg = locs()->temp(0).reg(); | 
|   644  |   661  | 
|   645   Label* deopt = CanDeoptimize() |   662   Label* deopt = | 
|   646       ? compiler->AddDeoptStub(deopt_id(), |   663       CanDeoptimize() | 
|   647                                ICData::kDeoptTestCids, |   664           ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptTestCids, | 
|   648                                licm_hoisted_ ? ICData::kHoisted : 0) |   665                                    licm_hoisted_ ? ICData::kHoisted : 0) | 
|   649       : NULL; |   666           : NULL; | 
|   650  |   667  | 
|   651   const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; |   668   const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; | 
|   652   const ZoneGrowableArray<intptr_t>& data = cid_results(); |   669   const ZoneGrowableArray<intptr_t>& data = cid_results(); | 
|   653   ASSERT(data[0] == kSmiCid); |   670   ASSERT(data[0] == kSmiCid); | 
|   654   bool result = data[1] == true_result; |   671   bool result = data[1] == true_result; | 
|   655   __ tsti(val_reg, Immediate(kSmiTagMask)); |   672   __ tsti(val_reg, Immediate(kSmiTagMask)); | 
|   656   __ b(result ? labels.true_label : labels.false_label, EQ); |   673   __ b(result ? labels.true_label : labels.false_label, EQ); | 
|   657   __ LoadClassId(cid_reg, val_reg); |   674   __ LoadClassId(cid_reg, val_reg); | 
|   658  |   675  | 
|   659   for (intptr_t i = 2; i < data.length(); i += 2) { |   676   for (intptr_t i = 2; i < data.length(); i += 2) { | 
| (...skipping 21 matching lines...) Expand all  Loading... | 
|   681 void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler, |   698 void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 
|   682                                    BranchInstr* branch) { |   699                                    BranchInstr* branch) { | 
|   683   BranchLabels labels = compiler->CreateBranchLabels(branch); |   700   BranchLabels labels = compiler->CreateBranchLabels(branch); | 
|   684   EmitComparisonCode(compiler, labels); |   701   EmitComparisonCode(compiler, labels); | 
|   685 } |   702 } | 
|   686  |   703  | 
|   687  |   704  | 
|   688 void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |   705 void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|   689   const Register result_reg = locs()->out(0).reg(); |   706   const Register result_reg = locs()->out(0).reg(); | 
|   690   Label is_true, is_false, done; |   707   Label is_true, is_false, done; | 
|   691   BranchLabels labels = { &is_true, &is_false, &is_false }; |   708   BranchLabels labels = {&is_true, &is_false, &is_false}; | 
|   692   EmitComparisonCode(compiler, labels); |   709   EmitComparisonCode(compiler, labels); | 
|   693   // TODO(zra): instead of branching, use the csel instruction to get |   710   // TODO(zra): instead of branching, use the csel instruction to get | 
|   694   // True or False into result. |   711   // True or False into result. | 
|   695   __ Bind(&is_false); |   712   __ Bind(&is_false); | 
|   696   __ LoadObject(result_reg, Bool::False()); |   713   __ LoadObject(result_reg, Bool::False()); | 
|   697   __ b(&done); |   714   __ b(&done); | 
|   698   __ Bind(&is_true); |   715   __ Bind(&is_true); | 
|   699   __ LoadObject(result_reg, Bool::True()); |   716   __ LoadObject(result_reg, Bool::True()); | 
|   700   __ Bind(&done); |   717   __ Bind(&done); | 
|   701 } |   718 } | 
|   702  |   719  | 
|   703  |   720  | 
|   704 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, |   721 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, | 
|   705                                                         bool opt) const { |   722                                                         bool opt) const { | 
|   706   const intptr_t kNumInputs = 2; |   723   const intptr_t kNumInputs = 2; | 
|   707   const intptr_t kNumTemps = 0; |   724   const intptr_t kNumTemps = 0; | 
|   708   if (operation_cid() == kDoubleCid) { |   725   if (operation_cid() == kDoubleCid) { | 
|   709     LocationSummary* summary = new(zone) LocationSummary( |   726     LocationSummary* summary = new (zone) | 
|   710         zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |   727         LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|   711     summary->set_in(0, Location::RequiresFpuRegister()); |   728     summary->set_in(0, Location::RequiresFpuRegister()); | 
|   712     summary->set_in(1, Location::RequiresFpuRegister()); |   729     summary->set_in(1, Location::RequiresFpuRegister()); | 
|   713     summary->set_out(0, Location::RequiresRegister()); |   730     summary->set_out(0, Location::RequiresRegister()); | 
|   714     return summary; |   731     return summary; | 
|   715   } |   732   } | 
|   716   ASSERT(operation_cid() == kSmiCid); |   733   ASSERT(operation_cid() == kSmiCid); | 
|   717   LocationSummary* summary = new(zone) LocationSummary( |   734   LocationSummary* summary = new (zone) | 
|   718       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |   735       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|   719   summary->set_in(0, Location::RegisterOrConstant(left())); |   736   summary->set_in(0, Location::RegisterOrConstant(left())); | 
|   720   // Only one input can be a constant operand. The case of two constant |   737   // Only one input can be a constant operand. The case of two constant | 
|   721   // operands should be handled by constant propagation. |   738   // operands should be handled by constant propagation. | 
|   722   summary->set_in(1, summary->in(0).IsConstant() |   739   summary->set_in(1, summary->in(0).IsConstant() | 
|   723                          ? Location::RequiresRegister() |   740                          ? Location::RequiresRegister() | 
|   724                          : Location::RegisterOrConstant(right())); |   741                          : Location::RegisterOrConstant(right())); | 
|   725   summary->set_out(0, Location::RequiresRegister()); |   742   summary->set_out(0, Location::RequiresRegister()); | 
|   726   return summary; |   743   return summary; | 
|   727 } |   744 } | 
|   728  |   745  | 
|   729  |   746  | 
|   730 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |   747 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 
|   731                                                 BranchLabels labels) { |   748                                                 BranchLabels labels) { | 
|   732   if (operation_cid() == kSmiCid) { |   749   if (operation_cid() == kSmiCid) { | 
|   733     return EmitSmiComparisonOp(compiler, locs(), kind()); |   750     return EmitSmiComparisonOp(compiler, locs(), kind()); | 
|   734   } else { |   751   } else { | 
|   735     ASSERT(operation_cid() == kDoubleCid); |   752     ASSERT(operation_cid() == kDoubleCid); | 
|   736     return EmitDoubleComparisonOp(compiler, locs(), kind()); |   753     return EmitDoubleComparisonOp(compiler, locs(), kind()); | 
|   737   } |   754   } | 
|   738 } |   755 } | 
|   739  |   756  | 
|   740  |   757  | 
|   741 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |   758 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|   742   Label is_true, is_false; |   759   Label is_true, is_false; | 
|   743   BranchLabels labels = { &is_true, &is_false, &is_false }; |   760   BranchLabels labels = {&is_true, &is_false, &is_false}; | 
|   744   Condition true_condition = EmitComparisonCode(compiler, labels); |   761   Condition true_condition = EmitComparisonCode(compiler, labels); | 
|   745   if ((operation_cid() == kDoubleCid) && (true_condition != NE)) { |   762   if ((operation_cid() == kDoubleCid) && (true_condition != NE)) { | 
|   746     // Special case for NaN comparison. Result is always false unless |   763     // Special case for NaN comparison. Result is always false unless | 
|   747     // relational operator is !=. |   764     // relational operator is !=. | 
|   748     __ b(&is_false, VS); |   765     __ b(&is_false, VS); | 
|   749   } |   766   } | 
|   750   EmitBranchOnCondition(compiler, true_condition, labels); |   767   EmitBranchOnCondition(compiler, true_condition, labels); | 
|   751   // TODO(zra): instead of branching, use the csel instruction to get |   768   // TODO(zra): instead of branching, use the csel instruction to get | 
|   752   // True or False into result. |   769   // True or False into result. | 
|   753   const Register result = locs()->out(0).reg(); |   770   const Register result = locs()->out(0).reg(); | 
| (...skipping 27 matching lines...) Expand all  Loading... | 
|   781  |   798  | 
|   782  |   799  | 
|   783 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |   800 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|   784   SetupNative(); |   801   SetupNative(); | 
|   785   const Register result = locs()->out(0).reg(); |   802   const Register result = locs()->out(0).reg(); | 
|   786  |   803  | 
|   787   // Push the result place holder initialized to NULL. |   804   // Push the result place holder initialized to NULL. | 
|   788   __ PushObject(Object::null_object()); |   805   __ PushObject(Object::null_object()); | 
|   789   // Pass a pointer to the first argument in R2. |   806   // Pass a pointer to the first argument in R2. | 
|   790   if (!function().HasOptionalParameters()) { |   807   if (!function().HasOptionalParameters()) { | 
|   791     __ AddImmediate(R2, FP, (kParamEndSlotFromFp + |   808     __ AddImmediate( | 
|   792                              function().NumParameters()) * kWordSize); |   809         R2, FP, (kParamEndSlotFromFp + function().NumParameters()) * kWordSize); | 
|   793   } else { |   810   } else { | 
|   794     __ AddImmediate(R2, FP, kFirstLocalSlotFromFp * kWordSize); |   811     __ AddImmediate(R2, FP, kFirstLocalSlotFromFp * kWordSize); | 
|   795   } |   812   } | 
|   796   // Compute the effective address. When running under the simulator, |   813   // Compute the effective address. When running under the simulator, | 
|   797   // this is a redirection address that forces the simulator to call |   814   // this is a redirection address that forces the simulator to call | 
|   798   // into the runtime system. |   815   // into the runtime system. | 
|   799   uword entry; |   816   uword entry; | 
|   800   const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); |   817   const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); | 
|   801   const StubEntry* stub_entry; |   818   const StubEntry* stub_entry; | 
|   802   if (link_lazily()) { |   819   if (link_lazily()) { | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
|   813     } else { |   830     } else { | 
|   814       // In the case of non bootstrap native methods the CallNativeCFunction |   831       // In the case of non bootstrap native methods the CallNativeCFunction | 
|   815       // stub generates the redirection address when running under the simulator |   832       // stub generates the redirection address when running under the simulator | 
|   816       // and hence we do not change 'entry' here. |   833       // and hence we do not change 'entry' here. | 
|   817       stub_entry = StubCode::CallNativeCFunction_entry(); |   834       stub_entry = StubCode::CallNativeCFunction_entry(); | 
|   818     } |   835     } | 
|   819   } |   836   } | 
|   820   __ LoadImmediate(R1, argc_tag); |   837   __ LoadImmediate(R1, argc_tag); | 
|   821   ExternalLabel label(entry); |   838   ExternalLabel label(entry); | 
|   822   __ LoadNativeEntry(R5, &label); |   839   __ LoadNativeEntry(R5, &label); | 
|   823   compiler->GenerateCall(token_pos(), |   840   compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther, | 
|   824                          *stub_entry, |  | 
|   825                          RawPcDescriptors::kOther, |  | 
|   826                          locs()); |   841                          locs()); | 
|   827   __ Pop(result); |   842   __ Pop(result); | 
|   828 } |   843 } | 
|   829  |   844  | 
|   830  |   845  | 
|   831 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary( |   846 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary( | 
|   832     Zone* zone, bool opt) const { |   847     Zone* zone, | 
 |   848     bool opt) const { | 
|   833   const intptr_t kNumInputs = 1; |   849   const intptr_t kNumInputs = 1; | 
|   834   // TODO(fschneider): Allow immediate operands for the char code. |   850   // TODO(fschneider): Allow immediate operands for the char code. | 
|   835   return LocationSummary::Make(zone, |   851   return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), | 
|   836                                kNumInputs, |  | 
|   837                                Location::RequiresRegister(), |  | 
|   838                                LocationSummary::kNoCall); |   852                                LocationSummary::kNoCall); | 
|   839 } |   853 } | 
|   840  |   854  | 
|   841  |   855  | 
|   842 void OneByteStringFromCharCodeInstr::EmitNativeCode( |   856 void OneByteStringFromCharCodeInstr::EmitNativeCode( | 
|   843     FlowGraphCompiler* compiler) { |   857     FlowGraphCompiler* compiler) { | 
|   844   ASSERT(compiler->is_optimizing()); |   858   ASSERT(compiler->is_optimizing()); | 
|   845   const Register char_code = locs()->in(0).reg(); |   859   const Register char_code = locs()->in(0).reg(); | 
|   846   const Register result = locs()->out(0).reg(); |   860   const Register result = locs()->out(0).reg(); | 
|   847  |   861  | 
|   848   __ ldr(result, Address(THR, Thread::predefined_symbols_address_offset())); |   862   __ ldr(result, Address(THR, Thread::predefined_symbols_address_offset())); | 
|   849   __ AddImmediate( |   863   __ AddImmediate(result, result, | 
|   850       result, result, Symbols::kNullCharCodeSymbolOffset * kWordSize); |   864                   Symbols::kNullCharCodeSymbolOffset * kWordSize); | 
|   851   __ SmiUntag(TMP, char_code);  // Untag to use scaled adress mode. |   865   __ SmiUntag(TMP, char_code);  // Untag to use scaled adress mode. | 
|   852   __ ldr(result, Address(result, TMP, UXTX, Address::Scaled)); |   866   __ ldr(result, Address(result, TMP, UXTX, Address::Scaled)); | 
|   853 } |   867 } | 
|   854  |   868  | 
|   855  |   869  | 
|   856 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Zone* zone, |   870 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Zone* zone, | 
|   857                                                             bool opt) const { |   871                                                             bool opt) const { | 
|   858   const intptr_t kNumInputs = 1; |   872   const intptr_t kNumInputs = 1; | 
|   859   return LocationSummary::Make(zone, |   873   return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), | 
|   860                                kNumInputs, |  | 
|   861                                Location::RequiresRegister(), |  | 
|   862                                LocationSummary::kNoCall); |   874                                LocationSummary::kNoCall); | 
|   863 } |   875 } | 
|   864  |   876  | 
|   865  |   877  | 
|   866 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |   878 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|   867   ASSERT(cid_ == kOneByteStringCid); |   879   ASSERT(cid_ == kOneByteStringCid); | 
|   868   const Register str = locs()->in(0).reg(); |   880   const Register str = locs()->in(0).reg(); | 
|   869   const Register result = locs()->out(0).reg(); |   881   const Register result = locs()->out(0).reg(); | 
|   870   __ LoadFieldFromOffset(result, str, String::length_offset()); |   882   __ LoadFieldFromOffset(result, str, String::length_offset()); | 
|   871   __ ldr(TMP, FieldAddress(str, OneByteString::data_offset()), kUnsignedByte); |   883   __ ldr(TMP, FieldAddress(str, OneByteString::data_offset()), kUnsignedByte); | 
|   872   __ CompareImmediate(result, Smi::RawValue(1)); |   884   __ CompareImmediate(result, Smi::RawValue(1)); | 
|   873   __ LoadImmediate(result, -1); |   885   __ LoadImmediate(result, -1); | 
|   874   __ csel(result, TMP, result, EQ); |   886   __ csel(result, TMP, result, EQ); | 
|   875   __ SmiTag(result); |   887   __ SmiTag(result); | 
|   876 } |   888 } | 
|   877  |   889  | 
|   878  |   890  | 
|   879 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone, |   891 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone, | 
|   880                                                              bool opt) const { |   892                                                              bool opt) const { | 
|   881   const intptr_t kNumInputs = 1; |   893   const intptr_t kNumInputs = 1; | 
|   882   const intptr_t kNumTemps = 0; |   894   const intptr_t kNumTemps = 0; | 
|   883   LocationSummary* summary = new(zone) LocationSummary( |   895   LocationSummary* summary = new (zone) | 
|   884       zone, kNumInputs, kNumTemps, LocationSummary::kCall); |   896       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 
|   885   summary->set_in(0, Location::RegisterLocation(R0)); |   897   summary->set_in(0, Location::RegisterLocation(R0)); | 
|   886   summary->set_out(0, Location::RegisterLocation(R0)); |   898   summary->set_out(0, Location::RegisterLocation(R0)); | 
|   887   return summary; |   899   return summary; | 
|   888 } |   900 } | 
|   889  |   901  | 
|   890  |   902  | 
|   891 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |   903 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|   892   const Register array = locs()->in(0).reg(); |   904   const Register array = locs()->in(0).reg(); | 
|   893   __ Push(array); |   905   __ Push(array); | 
|   894   const int kNumberOfArguments = 1; |   906   const int kNumberOfArguments = 1; | 
|   895   const Array& kNoArgumentNames = Object::null_array(); |   907   const Array& kNoArgumentNames = Object::null_array(); | 
|   896   compiler->GenerateStaticCall(deopt_id(), |   908   compiler->GenerateStaticCall(deopt_id(), token_pos(), CallFunction(), | 
|   897                                token_pos(), |   909                                kNumberOfArguments, kNoArgumentNames, locs(), | 
|   898                                CallFunction(), |  | 
|   899                                kNumberOfArguments, |  | 
|   900                                kNoArgumentNames, |  | 
|   901                                locs(), |  | 
|   902                                ICData::Handle()); |   910                                ICData::Handle()); | 
|   903   ASSERT(locs()->out(0).reg() == R0); |   911   ASSERT(locs()->out(0).reg() == R0); | 
|   904 } |   912 } | 
|   905  |   913  | 
|   906  |   914  | 
|   907 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(Zone* zone, |   915 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(Zone* zone, | 
|   908                                                         bool opt) const { |   916                                                         bool opt) const { | 
|   909   const intptr_t kNumInputs = 1; |   917   const intptr_t kNumInputs = 1; | 
|   910   return LocationSummary::Make(zone, |   918   return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), | 
|   911                                kNumInputs, |  | 
|   912                                Location::RequiresRegister(), |  | 
|   913                                LocationSummary::kNoCall); |   919                                LocationSummary::kNoCall); | 
|   914 } |   920 } | 
|   915  |   921  | 
|   916  |   922  | 
|   917 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |   923 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|   918   const Register obj = locs()->in(0).reg(); |   924   const Register obj = locs()->in(0).reg(); | 
|   919   const Register result = locs()->out(0).reg(); |   925   const Register result = locs()->out(0).reg(); | 
|   920   if (object()->definition()->representation() == kUntagged) { |   926   if (object()->definition()->representation() == kUntagged) { | 
|   921     __ LoadFromOffset(result, obj, offset()); |   927     __ LoadFromOffset(result, obj, offset()); | 
|   922   } else { |   928   } else { | 
|   923     ASSERT(object()->definition()->representation() == kTagged); |   929     ASSERT(object()->definition()->representation() == kTagged); | 
|   924     __ LoadFieldFromOffset(result, obj, offset()); |   930     __ LoadFieldFromOffset(result, obj, offset()); | 
|   925   } |   931   } | 
|   926 } |   932 } | 
|   927  |   933  | 
|   928  |   934  | 
|   929 LocationSummary* LoadClassIdInstr::MakeLocationSummary(Zone* zone, |   935 LocationSummary* LoadClassIdInstr::MakeLocationSummary(Zone* zone, | 
|   930                                                        bool opt) const { |   936                                                        bool opt) const { | 
|   931   const intptr_t kNumInputs = 1; |   937   const intptr_t kNumInputs = 1; | 
|   932   return LocationSummary::Make(zone, |   938   return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), | 
|   933                                kNumInputs, |  | 
|   934                                Location::RequiresRegister(), |  | 
|   935                                LocationSummary::kNoCall); |   939                                LocationSummary::kNoCall); | 
|   936 } |   940 } | 
|   937  |   941  | 
|   938  |   942  | 
|   939 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |   943 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|   940   const Register object = locs()->in(0).reg(); |   944   const Register object = locs()->in(0).reg(); | 
|   941   const Register result = locs()->out(0).reg(); |   945   const Register result = locs()->out(0).reg(); | 
|   942   const AbstractType& value_type = *this->object()->Type()->ToAbstractType(); |   946   const AbstractType& value_type = *this->object()->Type()->ToAbstractType(); | 
|   943   if (CompileType::Smi().IsAssignableTo(value_type) || |   947   if (CompileType::Smi().IsAssignableTo(value_type) || | 
|   944       value_type.IsTypeParameter()) { |   948       value_type.IsTypeParameter()) { | 
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1024 } |  1028 } | 
|  1025  |  1029  | 
|  1026  |  1030  | 
|  1027 static bool CanBeImmediateIndex(Value* value, intptr_t cid, bool is_external) { |  1031 static bool CanBeImmediateIndex(Value* value, intptr_t cid, bool is_external) { | 
|  1028   ConstantInstr* constant = value->definition()->AsConstant(); |  1032   ConstantInstr* constant = value->definition()->AsConstant(); | 
|  1029   if ((constant == NULL) || !constant->value().IsSmi()) { |  1033   if ((constant == NULL) || !constant->value().IsSmi()) { | 
|  1030     return false; |  1034     return false; | 
|  1031   } |  1035   } | 
|  1032   const int64_t index = Smi::Cast(constant->value()).AsInt64Value(); |  1036   const int64_t index = Smi::Cast(constant->value()).AsInt64Value(); | 
|  1033   const intptr_t scale = Instance::ElementSizeFor(cid); |  1037   const intptr_t scale = Instance::ElementSizeFor(cid); | 
|  1034   const int64_t offset = index * scale + |  1038   const int64_t offset = | 
 |  1039       index * scale + | 
|  1035       (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag)); |  1040       (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag)); | 
|  1036   if (!Utils::IsInt(32, offset)) { |  1041   if (!Utils::IsInt(32, offset)) { | 
|  1037     return false; |  1042     return false; | 
|  1038   } |  1043   } | 
|  1039   return Address::CanHoldOffset(static_cast<int32_t>(offset), |  1044   return Address::CanHoldOffset(static_cast<int32_t>(offset), Address::Offset, | 
|  1040                                 Address::Offset, |  | 
|  1041                                 Address::OperandSizeFor(cid)); |  1045                                 Address::OperandSizeFor(cid)); | 
|  1042 } |  1046 } | 
|  1043  |  1047  | 
|  1044  |  1048  | 
|  1045 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone, |  1049 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone, | 
|  1046                                                        bool opt) const { |  1050                                                        bool opt) const { | 
|  1047   const intptr_t kNumInputs = 2; |  1051   const intptr_t kNumInputs = 2; | 
|  1048   const intptr_t kNumTemps = aligned() ? 0 : 1; |  1052   const intptr_t kNumTemps = aligned() ? 0 : 1; | 
|  1049   LocationSummary* locs = new(zone) LocationSummary( |  1053   LocationSummary* locs = new (zone) | 
|  1050       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  1054       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  1051   locs->set_in(0, Location::RequiresRegister()); |  1055   locs->set_in(0, Location::RequiresRegister()); | 
|  1052   if (CanBeImmediateIndex(index(), class_id(), IsExternal())) { |  1056   if (CanBeImmediateIndex(index(), class_id(), IsExternal())) { | 
|  1053     locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); |  1057     locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); | 
|  1054   } else { |  1058   } else { | 
|  1055     locs->set_in(1, Location::RequiresRegister()); |  1059     locs->set_in(1, Location::RequiresRegister()); | 
|  1056   } |  1060   } | 
|  1057   if ((representation() == kUnboxedDouble)    || |  1061   if ((representation() == kUnboxedDouble) || | 
|  1058       (representation() == kUnboxedFloat32x4) || |  1062       (representation() == kUnboxedFloat32x4) || | 
|  1059       (representation() == kUnboxedInt32x4)   || |  1063       (representation() == kUnboxedInt32x4) || | 
|  1060       (representation() == kUnboxedFloat64x2)) { |  1064       (representation() == kUnboxedFloat64x2)) { | 
|  1061     locs->set_out(0, Location::RequiresFpuRegister()); |  1065     locs->set_out(0, Location::RequiresFpuRegister()); | 
|  1062   } else { |  1066   } else { | 
|  1063     locs->set_out(0, Location::RequiresRegister()); |  1067     locs->set_out(0, Location::RequiresRegister()); | 
|  1064   } |  1068   } | 
|  1065   if (!aligned()) { |  1069   if (!aligned()) { | 
|  1066     locs->set_temp(0, Location::RequiresRegister()); |  1070     locs->set_temp(0, Location::RequiresRegister()); | 
|  1067   } |  1071   } | 
|  1068   return locs; |  1072   return locs; | 
|  1069 } |  1073 } | 
|  1070  |  1074  | 
|  1071  |  1075  | 
|  1072 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  1076 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  1073   // The array register points to the backing store for external arrays. |  1077   // The array register points to the backing store for external arrays. | 
|  1074   const Register array = locs()->in(0).reg(); |  1078   const Register array = locs()->in(0).reg(); | 
|  1075   const Location index = locs()->in(1); |  1079   const Location index = locs()->in(1); | 
|  1076   const Register address = aligned() ? kNoRegister : locs()->temp(0).reg(); |  1080   const Register address = aligned() ? kNoRegister : locs()->temp(0).reg(); | 
|  1077  |  1081  | 
|  1078   Address element_address(TMP);  // Bad address. |  1082   Address element_address(TMP);  // Bad address. | 
|  1079   if (aligned()) { |  1083   if (aligned()) { | 
|  1080     element_address = index.IsRegister() |  1084     element_address = | 
|  1081         ? __ ElementAddressForRegIndex(true,  // Load. |  1085         index.IsRegister() | 
|  1082                                        IsExternal(), class_id(), index_scale(), |  1086             ? __ ElementAddressForRegIndex(true,  // Load. | 
|  1083                                        array, index.reg()) |  1087                                            IsExternal(), class_id(), | 
|  1084         : __ ElementAddressForIntIndex( |  1088                                            index_scale(), array, index.reg()) | 
|  1085               IsExternal(), class_id(), index_scale(), |  1089             : __ ElementAddressForIntIndex(IsExternal(), class_id(), | 
|  1086               array, Smi::Cast(index.constant()).Value()); |  1090                                            index_scale(), array, | 
 |  1091                                            Smi::Cast(index.constant()).Value()); | 
|  1087     // Warning: element_address may use register TMP as base. |  1092     // Warning: element_address may use register TMP as base. | 
|  1088   } else { |  1093   } else { | 
|  1089     if (index.IsRegister()) { |  1094     if (index.IsRegister()) { | 
|  1090       __ LoadElementAddressForRegIndex(address, |  1095       __ LoadElementAddressForRegIndex(address, | 
|  1091                                        true,  // Load. |  1096                                        true,  // Load. | 
|  1092                                        IsExternal(), class_id(), index_scale(), |  1097                                        IsExternal(), class_id(), index_scale(), | 
|  1093                                        array, index.reg()); |  1098                                        array, index.reg()); | 
|  1094     } else { |  1099     } else { | 
|  1095       __ LoadElementAddressForIntIndex(address, |  1100       __ LoadElementAddressForIntIndex(address, IsExternal(), class_id(), | 
|  1096                                        IsExternal(), class_id(), index_scale(), |  1101                                        index_scale(), array, | 
|  1097                                        array, |  | 
|  1098                                        Smi::Cast(index.constant()).Value()); |  1102                                        Smi::Cast(index.constant()).Value()); | 
|  1099     } |  1103     } | 
|  1100   } |  1104   } | 
|  1101  |  1105  | 
|  1102   if ((representation() == kUnboxedDouble)    || |  1106   if ((representation() == kUnboxedDouble) || | 
|  1103       (representation() == kUnboxedFloat32x4) || |  1107       (representation() == kUnboxedFloat32x4) || | 
|  1104       (representation() == kUnboxedInt32x4)   || |  1108       (representation() == kUnboxedInt32x4) || | 
|  1105       (representation() == kUnboxedFloat64x2)) { |  1109       (representation() == kUnboxedFloat64x2)) { | 
|  1106     const VRegister result = locs()->out(0).fpu_reg(); |  1110     const VRegister result = locs()->out(0).fpu_reg(); | 
|  1107     switch (class_id()) { |  1111     switch (class_id()) { | 
|  1108       ASSERT(aligned()); |  1112       ASSERT(aligned()); | 
|  1109       case kTypedDataFloat32ArrayCid: |  1113       case kTypedDataFloat32ArrayCid: | 
|  1110         // Load single precision float. |  1114         // Load single precision float. | 
|  1111         __ fldrs(result, element_address); |  1115         __ fldrs(result, element_address); | 
|  1112         break; |  1116         break; | 
|  1113       case kTypedDataFloat64ArrayCid: |  1117       case kTypedDataFloat64ArrayCid: | 
|  1114         // Load double precision float. |  1118         // Load double precision float. | 
| (...skipping 25 matching lines...) Expand all  Loading... | 
|  1140       case kTypedDataUint32ArrayCid: |  1144       case kTypedDataUint32ArrayCid: | 
|  1141         ASSERT(representation() == kUnboxedUint32); |  1145         ASSERT(representation() == kUnboxedUint32); | 
|  1142         if (aligned()) { |  1146         if (aligned()) { | 
|  1143           __ ldr(result, element_address, kUnsignedWord); |  1147           __ ldr(result, element_address, kUnsignedWord); | 
|  1144         } else { |  1148         } else { | 
|  1145           __ LoadUnaligned(result, address, TMP, kUnsignedWord); |  1149           __ LoadUnaligned(result, address, TMP, kUnsignedWord); | 
|  1146         } |  1150         } | 
|  1147         break; |  1151         break; | 
|  1148       default: |  1152       default: | 
|  1149         UNREACHABLE(); |  1153         UNREACHABLE(); | 
|  1150       } |  1154     } | 
|  1151     return; |  1155     return; | 
|  1152   } |  1156   } | 
|  1153  |  1157  | 
|  1154   ASSERT(representation() == kTagged); |  1158   ASSERT(representation() == kTagged); | 
|  1155   const Register result = locs()->out(0).reg(); |  1159   const Register result = locs()->out(0).reg(); | 
|  1156   switch (class_id()) { |  1160   switch (class_id()) { | 
|  1157     case kTypedDataInt8ArrayCid: |  1161     case kTypedDataInt8ArrayCid: | 
|  1158       ASSERT(index_scale() == 1); |  1162       ASSERT(index_scale() == 1); | 
|  1159       __ ldr(result, element_address, kByte); |  1163       __ ldr(result, element_address, kByte); | 
|  1160       __ SmiTag(result); |  1164       __ SmiTag(result); | 
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1193       __ ldr(result, element_address); |  1197       __ ldr(result, element_address); | 
|  1194       break; |  1198       break; | 
|  1195   } |  1199   } | 
|  1196 } |  1200 } | 
|  1197  |  1201  | 
|  1198  |  1202  | 
|  1199 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone, |  1203 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone, | 
|  1200                                                          bool opt) const { |  1204                                                          bool opt) const { | 
|  1201   const intptr_t kNumInputs = 2; |  1205   const intptr_t kNumInputs = 2; | 
|  1202   const intptr_t kNumTemps = 0; |  1206   const intptr_t kNumTemps = 0; | 
|  1203   LocationSummary* summary = new(zone) LocationSummary( |  1207   LocationSummary* summary = new (zone) | 
|  1204       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  1208       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  1205   summary->set_in(0, Location::RequiresRegister()); |  1209   summary->set_in(0, Location::RequiresRegister()); | 
|  1206   summary->set_in(1, Location::RequiresRegister()); |  1210   summary->set_in(1, Location::RequiresRegister()); | 
|  1207   summary->set_out(0, Location::RequiresRegister()); |  1211   summary->set_out(0, Location::RequiresRegister()); | 
|  1208   return summary; |  1212   return summary; | 
|  1209 } |  1213 } | 
|  1210  |  1214  | 
|  1211  |  1215  | 
|  1212 void LoadCodeUnitsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  1216 void LoadCodeUnitsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  1213   // The string register points to the backing store for external strings. |  1217   // The string register points to the backing store for external strings. | 
|  1214   const Register str = locs()->in(0).reg(); |  1218   const Register str = locs()->in(0).reg(); | 
|  1215   const Location index = locs()->in(1); |  1219   const Location index = locs()->in(1); | 
|  1216  |  1220  | 
|  1217   Address element_address = __ ElementAddressForRegIndex( |  1221   Address element_address = __ ElementAddressForRegIndex( | 
|  1218         true,  IsExternal(), class_id(), index_scale(), str, index.reg()); |  1222       true, IsExternal(), class_id(), index_scale(), str, index.reg()); | 
|  1219   // Warning: element_address may use register TMP as base. |  1223   // Warning: element_address may use register TMP as base. | 
|  1220  |  1224  | 
|  1221   Register result = locs()->out(0).reg(); |  1225   Register result = locs()->out(0).reg(); | 
|  1222   switch (class_id()) { |  1226   switch (class_id()) { | 
|  1223     case kOneByteStringCid: |  1227     case kOneByteStringCid: | 
|  1224     case kExternalOneByteStringCid: |  1228     case kExternalOneByteStringCid: | 
|  1225       switch (element_count()) { |  1229       switch (element_count()) { | 
|  1226         case 1: __ ldr(result, element_address, kUnsignedByte); break; |  1230         case 1: | 
|  1227         case 2: __ ldr(result, element_address, kUnsignedHalfword); break; |  1231           __ ldr(result, element_address, kUnsignedByte); | 
|  1228         case 4: __ ldr(result, element_address, kUnsignedWord); break; |  1232           break; | 
|  1229         default: UNREACHABLE(); |  1233         case 2: | 
 |  1234           __ ldr(result, element_address, kUnsignedHalfword); | 
 |  1235           break; | 
 |  1236         case 4: | 
 |  1237           __ ldr(result, element_address, kUnsignedWord); | 
 |  1238           break; | 
 |  1239         default: | 
 |  1240           UNREACHABLE(); | 
|  1230       } |  1241       } | 
|  1231       __ SmiTag(result); |  1242       __ SmiTag(result); | 
|  1232       break; |  1243       break; | 
|  1233     case kTwoByteStringCid: |  1244     case kTwoByteStringCid: | 
|  1234     case kExternalTwoByteStringCid: |  1245     case kExternalTwoByteStringCid: | 
|  1235       switch (element_count()) { |  1246       switch (element_count()) { | 
|  1236         case 1: __ ldr(result, element_address, kUnsignedHalfword); break; |  1247         case 1: | 
|  1237         case 2: __ ldr(result, element_address, kUnsignedWord); break; |  1248           __ ldr(result, element_address, kUnsignedHalfword); | 
|  1238         default: UNREACHABLE(); |  1249           break; | 
 |  1250         case 2: | 
 |  1251           __ ldr(result, element_address, kUnsignedWord); | 
 |  1252           break; | 
 |  1253         default: | 
 |  1254           UNREACHABLE(); | 
|  1239       } |  1255       } | 
|  1240       __ SmiTag(result); |  1256       __ SmiTag(result); | 
|  1241       break; |  1257       break; | 
|  1242     default: |  1258     default: | 
|  1243       UNREACHABLE(); |  1259       UNREACHABLE(); | 
|  1244       break; |  1260       break; | 
|  1245   } |  1261   } | 
|  1246 } |  1262 } | 
|  1247  |  1263  | 
|  1248  |  1264  | 
|  1249 Representation StoreIndexedInstr::RequiredInputRepresentation( |  1265 Representation StoreIndexedInstr::RequiredInputRepresentation( | 
|  1250     intptr_t idx) const { |  1266     intptr_t idx) const { | 
|  1251   // Array can be a Dart object or a pointer to external data. |  1267   // Array can be a Dart object or a pointer to external data. | 
|  1252   if (idx == 0)  return kNoRepresentation;  // Flexible input representation. |  1268   if (idx == 0) return kNoRepresentation;  // Flexible input representation. | 
|  1253   if (idx == 1) return kTagged;  // Index is a smi. |  1269   if (idx == 1) return kTagged;            // Index is a smi. | 
|  1254   ASSERT(idx == 2); |  1270   ASSERT(idx == 2); | 
|  1255   switch (class_id_) { |  1271   switch (class_id_) { | 
|  1256     case kArrayCid: |  1272     case kArrayCid: | 
|  1257     case kOneByteStringCid: |  1273     case kOneByteStringCid: | 
|  1258     case kTypedDataInt8ArrayCid: |  1274     case kTypedDataInt8ArrayCid: | 
|  1259     case kTypedDataUint8ArrayCid: |  1275     case kTypedDataUint8ArrayCid: | 
|  1260     case kExternalTypedDataUint8ArrayCid: |  1276     case kExternalTypedDataUint8ArrayCid: | 
|  1261     case kTypedDataUint8ClampedArrayCid: |  1277     case kTypedDataUint8ClampedArrayCid: | 
|  1262     case kExternalTypedDataUint8ClampedArrayCid: |  1278     case kExternalTypedDataUint8ClampedArrayCid: | 
|  1263     case kTypedDataInt16ArrayCid: |  1279     case kTypedDataInt16ArrayCid: | 
| (...skipping 16 matching lines...) Expand all  Loading... | 
|  1280       UNREACHABLE(); |  1296       UNREACHABLE(); | 
|  1281       return kTagged; |  1297       return kTagged; | 
|  1282   } |  1298   } | 
|  1283 } |  1299 } | 
|  1284  |  1300  | 
|  1285  |  1301  | 
|  1286 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone, |  1302 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone, | 
|  1287                                                         bool opt) const { |  1303                                                         bool opt) const { | 
|  1288   const intptr_t kNumInputs = 3; |  1304   const intptr_t kNumInputs = 3; | 
|  1289   const intptr_t kNumTemps = aligned() ? 0 : 2; |  1305   const intptr_t kNumTemps = aligned() ? 0 : 2; | 
|  1290   LocationSummary* locs = new(zone) LocationSummary( |  1306   LocationSummary* locs = new (zone) | 
|  1291       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  1307       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  1292   locs->set_in(0, Location::RequiresRegister()); |  1308   locs->set_in(0, Location::RequiresRegister()); | 
|  1293   if (CanBeImmediateIndex(index(), class_id(), IsExternal())) { |  1309   if (CanBeImmediateIndex(index(), class_id(), IsExternal())) { | 
|  1294     locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); |  1310     locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); | 
|  1295   } else { |  1311   } else { | 
|  1296     locs->set_in(1, Location::WritableRegister()); |  1312     locs->set_in(1, Location::WritableRegister()); | 
|  1297   } |  1313   } | 
|  1298   switch (class_id()) { |  1314   switch (class_id()) { | 
|  1299     case kArrayCid: |  1315     case kArrayCid: | 
|  1300       locs->set_in(2, ShouldEmitStoreBarrier() |  1316       locs->set_in(2, ShouldEmitStoreBarrier() | 
|  1301                         ? Location::WritableRegister() |  1317                           ? Location::WritableRegister() | 
|  1302                         : Location::RegisterOrConstant(value())); |  1318                           : Location::RegisterOrConstant(value())); | 
|  1303       break; |  1319       break; | 
|  1304     case kExternalTypedDataUint8ArrayCid: |  1320     case kExternalTypedDataUint8ArrayCid: | 
|  1305     case kExternalTypedDataUint8ClampedArrayCid: |  1321     case kExternalTypedDataUint8ClampedArrayCid: | 
|  1306     case kTypedDataInt8ArrayCid: |  1322     case kTypedDataInt8ArrayCid: | 
|  1307     case kTypedDataUint8ArrayCid: |  1323     case kTypedDataUint8ArrayCid: | 
|  1308     case kTypedDataUint8ClampedArrayCid: |  1324     case kTypedDataUint8ClampedArrayCid: | 
|  1309     case kOneByteStringCid: |  1325     case kOneByteStringCid: | 
|  1310     case kTypedDataInt16ArrayCid: |  1326     case kTypedDataInt16ArrayCid: | 
|  1311     case kTypedDataUint16ArrayCid: |  1327     case kTypedDataUint16ArrayCid: | 
|  1312     case kTypedDataInt32ArrayCid: |  1328     case kTypedDataInt32ArrayCid: | 
| (...skipping 23 matching lines...) Expand all  Loading... | 
|  1336  |  1352  | 
|  1337 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  1353 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  1338   // The array register points to the backing store for external arrays. |  1354   // The array register points to the backing store for external arrays. | 
|  1339   const Register array = locs()->in(0).reg(); |  1355   const Register array = locs()->in(0).reg(); | 
|  1340   const Location index = locs()->in(1); |  1356   const Location index = locs()->in(1); | 
|  1341   const Register address = aligned() ? kNoRegister : locs()->temp(0).reg(); |  1357   const Register address = aligned() ? kNoRegister : locs()->temp(0).reg(); | 
|  1342   const Register scratch = aligned() ? kNoRegister : locs()->temp(1).reg(); |  1358   const Register scratch = aligned() ? kNoRegister : locs()->temp(1).reg(); | 
|  1343  |  1359  | 
|  1344   Address element_address(TMP);  // Bad address. |  1360   Address element_address(TMP);  // Bad address. | 
|  1345   if (aligned()) { |  1361   if (aligned()) { | 
|  1346     element_address = index.IsRegister() |  1362     element_address = | 
|  1347       ? __ ElementAddressForRegIndex(false,  // Store. |  1363         index.IsRegister() | 
|  1348                                      IsExternal(), class_id(), index_scale(), |  1364             ? __ ElementAddressForRegIndex(false,  // Store. | 
|  1349                                      array, index.reg()) |  1365                                            IsExternal(), class_id(), | 
|  1350       : __ ElementAddressForIntIndex( |  1366                                            index_scale(), array, index.reg()) | 
|  1351             IsExternal(), class_id(), index_scale(), |  1367             : __ ElementAddressForIntIndex(IsExternal(), class_id(), | 
|  1352             array, Smi::Cast(index.constant()).Value()); |  1368                                            index_scale(), array, | 
 |  1369                                            Smi::Cast(index.constant()).Value()); | 
|  1353   } else { |  1370   } else { | 
|  1354     if (index.IsRegister()) { |  1371     if (index.IsRegister()) { | 
|  1355       __ LoadElementAddressForRegIndex(address, |  1372       __ LoadElementAddressForRegIndex(address, | 
|  1356                                        false,  // Store. |  1373                                        false,  // Store. | 
|  1357                                        IsExternal(), class_id(), index_scale(), |  1374                                        IsExternal(), class_id(), index_scale(), | 
|  1358                                        array, index.reg()); |  1375                                        array, index.reg()); | 
|  1359     } else { |  1376     } else { | 
|  1360       __ LoadElementAddressForIntIndex(address, |  1377       __ LoadElementAddressForIntIndex(address, IsExternal(), class_id(), | 
|  1361                                        IsExternal(), class_id(), index_scale(), |  1378                                        index_scale(), array, | 
|  1362                                        array, |  | 
|  1363                                        Smi::Cast(index.constant()).Value()); |  1379                                        Smi::Cast(index.constant()).Value()); | 
|  1364     } |  1380     } | 
|  1365   } |  1381   } | 
|  1366  |  1382  | 
|  1367   switch (class_id()) { |  1383   switch (class_id()) { | 
|  1368     case kArrayCid: |  1384     case kArrayCid: | 
|  1369       ASSERT(aligned()); |  1385       ASSERT(aligned()); | 
|  1370       if (ShouldEmitStoreBarrier()) { |  1386       if (ShouldEmitStoreBarrier()) { | 
|  1371         const Register value = locs()->in(2).reg(); |  1387         const Register value = locs()->in(2).reg(); | 
|  1372         __ StoreIntoObject(array, element_address, value); |  1388         __ StoreIntoObject(array, element_address, value); | 
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1405           value = 0xFF; |  1421           value = 0xFF; | 
|  1406         } else if (value < 0) { |  1422         } else if (value < 0) { | 
|  1407           value = 0; |  1423           value = 0; | 
|  1408         } |  1424         } | 
|  1409         __ LoadImmediate(TMP, static_cast<int8_t>(value)); |  1425         __ LoadImmediate(TMP, static_cast<int8_t>(value)); | 
|  1410         __ str(TMP, element_address, kUnsignedByte); |  1426         __ str(TMP, element_address, kUnsignedByte); | 
|  1411       } else { |  1427       } else { | 
|  1412         const Register value = locs()->in(2).reg(); |  1428         const Register value = locs()->in(2).reg(); | 
|  1413         __ CompareImmediate(value, 0x1FE);  // Smi value and smi 0xFF. |  1429         __ CompareImmediate(value, 0x1FE);  // Smi value and smi 0xFF. | 
|  1414         // Clamp to 0x00 or 0xFF respectively. |  1430         // Clamp to 0x00 or 0xFF respectively. | 
|  1415         __ csetm(TMP, GT);  // TMP = value > 0x1FE ? -1 : 0. |  1431         __ csetm(TMP, GT);             // TMP = value > 0x1FE ? -1 : 0. | 
|  1416         __ csel(TMP, value, TMP, LS);  // TMP = value in range ? value : TMP. |  1432         __ csel(TMP, value, TMP, LS);  // TMP = value in range ? value : TMP. | 
|  1417         __ SmiUntag(TMP); |  1433         __ SmiUntag(TMP); | 
|  1418         __ str(TMP, element_address, kUnsignedByte); |  1434         __ str(TMP, element_address, kUnsignedByte); | 
|  1419       } |  1435       } | 
|  1420       break; |  1436       break; | 
|  1421     } |  1437     } | 
|  1422     case kTypedDataInt16ArrayCid: |  1438     case kTypedDataInt16ArrayCid: | 
|  1423     case kTypedDataUint16ArrayCid: { |  1439     case kTypedDataUint16ArrayCid: { | 
|  1424       const Register value = locs()->in(2).reg(); |  1440       const Register value = locs()->in(2).reg(); | 
|  1425       __ SmiUntag(TMP, value); |  1441       __ SmiUntag(TMP, value); | 
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1485 } |  1501 } | 
|  1486  |  1502  | 
|  1487  |  1503  | 
|  1488 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Zone* zone, |  1504 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Zone* zone, | 
|  1489                                                            bool opt) const { |  1505                                                            bool opt) const { | 
|  1490   const intptr_t kNumInputs = 1; |  1506   const intptr_t kNumInputs = 1; | 
|  1491  |  1507  | 
|  1492   const intptr_t value_cid = value()->Type()->ToCid(); |  1508   const intptr_t value_cid = value()->Type()->ToCid(); | 
|  1493   const intptr_t field_cid = field().guarded_cid(); |  1509   const intptr_t field_cid = field().guarded_cid(); | 
|  1494  |  1510  | 
|  1495   const bool emit_full_guard = |  1511   const bool emit_full_guard = !opt || (field_cid == kIllegalCid); | 
|  1496       !opt || (field_cid == kIllegalCid); |  | 
|  1497  |  1512  | 
|  1498   const bool needs_value_cid_temp_reg = emit_full_guard || |  1513   const bool needs_value_cid_temp_reg = | 
|  1499       ((value_cid == kDynamicCid) && (field_cid != kSmiCid)); |  1514       emit_full_guard || ((value_cid == kDynamicCid) && (field_cid != kSmiCid)); | 
|  1500  |  1515  | 
|  1501   const bool needs_field_temp_reg = emit_full_guard; |  1516   const bool needs_field_temp_reg = emit_full_guard; | 
|  1502  |  1517  | 
|  1503   intptr_t num_temps = 0; |  1518   intptr_t num_temps = 0; | 
|  1504   if (needs_value_cid_temp_reg) { |  1519   if (needs_value_cid_temp_reg) { | 
|  1505     num_temps++; |  1520     num_temps++; | 
|  1506   } |  1521   } | 
|  1507   if (needs_field_temp_reg) { |  1522   if (needs_field_temp_reg) { | 
|  1508     num_temps++; |  1523     num_temps++; | 
|  1509   } |  1524   } | 
|  1510  |  1525  | 
|  1511   LocationSummary* summary = new(zone) LocationSummary( |  1526   LocationSummary* summary = new (zone) | 
|  1512       zone, kNumInputs, num_temps, LocationSummary::kNoCall); |  1527       LocationSummary(zone, kNumInputs, num_temps, LocationSummary::kNoCall); | 
|  1513   summary->set_in(0, Location::RequiresRegister()); |  1528   summary->set_in(0, Location::RequiresRegister()); | 
|  1514  |  1529  | 
|  1515   for (intptr_t i = 0; i < num_temps; i++) { |  1530   for (intptr_t i = 0; i < num_temps; i++) { | 
|  1516     summary->set_temp(i, Location::RequiresRegister()); |  1531     summary->set_temp(i, Location::RequiresRegister()); | 
|  1517   } |  1532   } | 
|  1518  |  1533  | 
|  1519   return summary; |  1534   return summary; | 
|  1520 } |  1535 } | 
|  1521  |  1536  | 
|  1522  |  1537  | 
|  1523 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  1538 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  1524   ASSERT(sizeof(classid_t) == kInt32Size); |  1539   ASSERT(sizeof(classid_t) == kInt32Size); | 
|  1525   const intptr_t value_cid = value()->Type()->ToCid(); |  1540   const intptr_t value_cid = value()->Type()->ToCid(); | 
|  1526   const intptr_t field_cid = field().guarded_cid(); |  1541   const intptr_t field_cid = field().guarded_cid(); | 
|  1527   const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; |  1542   const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; | 
|  1528  |  1543  | 
|  1529   if (field_cid == kDynamicCid) { |  1544   if (field_cid == kDynamicCid) { | 
|  1530     if (Compiler::IsBackgroundCompilation()) { |  1545     if (Compiler::IsBackgroundCompilation()) { | 
|  1531       // Field state changed while compiling. |  1546       // Field state changed while compiling. | 
|  1532       Compiler::AbortBackgroundCompilation(deopt_id(), |  1547       Compiler::AbortBackgroundCompilation( | 
 |  1548           deopt_id(), | 
|  1533           "GuardFieldClassInstr: field state changed while compiling"); |  1549           "GuardFieldClassInstr: field state changed while compiling"); | 
|  1534     } |  1550     } | 
|  1535     ASSERT(!compiler->is_optimizing()); |  1551     ASSERT(!compiler->is_optimizing()); | 
|  1536     return;  // Nothing to emit. |  1552     return;  // Nothing to emit. | 
|  1537   } |  1553   } | 
|  1538  |  1554  | 
|  1539   const bool emit_full_guard = |  1555   const bool emit_full_guard = | 
|  1540       !compiler->is_optimizing() || (field_cid == kIllegalCid); |  1556       !compiler->is_optimizing() || (field_cid == kIllegalCid); | 
|  1541  |  1557  | 
|  1542   const bool needs_value_cid_temp_reg = emit_full_guard || |  1558   const bool needs_value_cid_temp_reg = | 
|  1543       ((value_cid == kDynamicCid) && (field_cid != kSmiCid)); |  1559       emit_full_guard || ((value_cid == kDynamicCid) && (field_cid != kSmiCid)); | 
|  1544  |  1560  | 
|  1545   const bool needs_field_temp_reg = emit_full_guard; |  1561   const bool needs_field_temp_reg = emit_full_guard; | 
|  1546  |  1562  | 
|  1547   const Register value_reg = locs()->in(0).reg(); |  1563   const Register value_reg = locs()->in(0).reg(); | 
|  1548  |  1564  | 
|  1549   const Register value_cid_reg = needs_value_cid_temp_reg ? |  1565   const Register value_cid_reg = | 
|  1550       locs()->temp(0).reg() : kNoRegister; |  1566       needs_value_cid_temp_reg ? locs()->temp(0).reg() : kNoRegister; | 
|  1551  |  1567  | 
|  1552   const Register field_reg = needs_field_temp_reg ? |  1568   const Register field_reg = needs_field_temp_reg | 
|  1553       locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister; |  1569                                  ? locs()->temp(locs()->temp_count() - 1).reg() | 
 |  1570                                  : kNoRegister; | 
|  1554  |  1571  | 
|  1555   Label ok, fail_label; |  1572   Label ok, fail_label; | 
|  1556  |  1573  | 
|  1557   Label* deopt = compiler->is_optimizing() ? |  1574   Label* deopt = | 
|  1558       compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL; |  1575       compiler->is_optimizing() | 
 |  1576           ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) | 
 |  1577           : NULL; | 
|  1559  |  1578  | 
|  1560   Label* fail = (deopt != NULL) ? deopt : &fail_label; |  1579   Label* fail = (deopt != NULL) ? deopt : &fail_label; | 
|  1561  |  1580  | 
|  1562   if (emit_full_guard) { |  1581   if (emit_full_guard) { | 
|  1563     __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); |  1582     __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); | 
|  1564  |  1583  | 
|  1565     FieldAddress field_cid_operand( |  1584     FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset(), | 
|  1566         field_reg, Field::guarded_cid_offset(), kUnsignedWord); |  1585                                    kUnsignedWord); | 
|  1567     FieldAddress field_nullability_operand( |  1586     FieldAddress field_nullability_operand( | 
|  1568         field_reg, Field::is_nullable_offset(), kUnsignedWord); |  1587         field_reg, Field::is_nullable_offset(), kUnsignedWord); | 
|  1569  |  1588  | 
|  1570     if (value_cid == kDynamicCid) { |  1589     if (value_cid == kDynamicCid) { | 
|  1571       LoadValueCid(compiler, value_cid_reg, value_reg); |  1590       LoadValueCid(compiler, value_cid_reg, value_reg); | 
|  1572       Label skip_length_check; |  1591       Label skip_length_check; | 
|  1573       __ ldr(TMP, field_cid_operand, kUnsignedWord); |  1592       __ ldr(TMP, field_cid_operand, kUnsignedWord); | 
|  1574       __ CompareRegisters(value_cid_reg, TMP); |  1593       __ CompareRegisters(value_cid_reg, TMP); | 
|  1575       __ b(&ok, EQ); |  1594       __ b(&ok, EQ); | 
|  1576       __ ldr(TMP, field_nullability_operand, kUnsignedWord); |  1595       __ ldr(TMP, field_nullability_operand, kUnsignedWord); | 
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1610       if (deopt == NULL) { |  1629       if (deopt == NULL) { | 
|  1611         ASSERT(!compiler->is_optimizing()); |  1630         ASSERT(!compiler->is_optimizing()); | 
|  1612         __ b(&ok); |  1631         __ b(&ok); | 
|  1613       } |  1632       } | 
|  1614     } |  1633     } | 
|  1615  |  1634  | 
|  1616     if (deopt == NULL) { |  1635     if (deopt == NULL) { | 
|  1617       ASSERT(!compiler->is_optimizing()); |  1636       ASSERT(!compiler->is_optimizing()); | 
|  1618       __ Bind(fail); |  1637       __ Bind(fail); | 
|  1619  |  1638  | 
|  1620       __ LoadFieldFromOffset( |  1639       __ LoadFieldFromOffset(TMP, field_reg, Field::guarded_cid_offset(), | 
|  1621           TMP, field_reg, Field::guarded_cid_offset(), kUnsignedWord); |  1640                              kUnsignedWord); | 
|  1622       __ CompareImmediate(TMP, kDynamicCid); |  1641       __ CompareImmediate(TMP, kDynamicCid); | 
|  1623       __ b(&ok, EQ); |  1642       __ b(&ok, EQ); | 
|  1624  |  1643  | 
|  1625       __ Push(field_reg); |  1644       __ Push(field_reg); | 
|  1626       __ Push(value_reg); |  1645       __ Push(value_reg); | 
|  1627       __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2); |  1646       __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2); | 
|  1628       __ Drop(2);  // Drop the field and the value. |  1647       __ Drop(2);  // Drop the field and the value. | 
|  1629     } |  1648     } | 
|  1630   } else { |  1649   } else { | 
|  1631     ASSERT(compiler->is_optimizing()); |  1650     ASSERT(compiler->is_optimizing()); | 
| (...skipping 24 matching lines...) Expand all  Loading... | 
|  1656   } |  1675   } | 
|  1657   __ Bind(&ok); |  1676   __ Bind(&ok); | 
|  1658 } |  1677 } | 
|  1659  |  1678  | 
|  1660  |  1679  | 
|  1661 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Zone* zone, |  1680 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Zone* zone, | 
|  1662                                                             bool opt) const { |  1681                                                             bool opt) const { | 
|  1663   const intptr_t kNumInputs = 1; |  1682   const intptr_t kNumInputs = 1; | 
|  1664   if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) { |  1683   if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) { | 
|  1665     const intptr_t kNumTemps = 3; |  1684     const intptr_t kNumTemps = 3; | 
|  1666     LocationSummary* summary = new(zone) LocationSummary( |  1685     LocationSummary* summary = new (zone) | 
|  1667         zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  1686         LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  1668     summary->set_in(0, Location::RequiresRegister()); |  1687     summary->set_in(0, Location::RequiresRegister()); | 
|  1669     // We need temporaries for field object, length offset and expected length. |  1688     // We need temporaries for field object, length offset and expected length. | 
|  1670     summary->set_temp(0, Location::RequiresRegister()); |  1689     summary->set_temp(0, Location::RequiresRegister()); | 
|  1671     summary->set_temp(1, Location::RequiresRegister()); |  1690     summary->set_temp(1, Location::RequiresRegister()); | 
|  1672     summary->set_temp(2, Location::RequiresRegister()); |  1691     summary->set_temp(2, Location::RequiresRegister()); | 
|  1673     return summary; |  1692     return summary; | 
|  1674   } else { |  1693   } else { | 
|  1675     LocationSummary* summary = new(zone) LocationSummary( |  1694     LocationSummary* summary = new (zone) | 
|  1676         zone, kNumInputs, 0, LocationSummary::kNoCall); |  1695         LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); | 
|  1677     summary->set_in(0, Location::RequiresRegister()); |  1696     summary->set_in(0, Location::RequiresRegister()); | 
|  1678     return summary; |  1697     return summary; | 
|  1679   } |  1698   } | 
|  1680   UNREACHABLE(); |  1699   UNREACHABLE(); | 
|  1681 } |  1700 } | 
|  1682  |  1701  | 
|  1683  |  1702  | 
|  1684 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  1703 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  1685   if (field().guarded_list_length() == Field::kNoFixedLength) { |  1704   if (field().guarded_list_length() == Field::kNoFixedLength) { | 
|  1686     if (Compiler::IsBackgroundCompilation()) { |  1705     if (Compiler::IsBackgroundCompilation()) { | 
|  1687       // Field state changed while compiling. |  1706       // Field state changed while compiling. | 
|  1688       Compiler::AbortBackgroundCompilation(deopt_id(), |  1707       Compiler::AbortBackgroundCompilation( | 
 |  1708           deopt_id(), | 
|  1689           "GuardFieldLengthInstr: field state changed while compiling"); |  1709           "GuardFieldLengthInstr: field state changed while compiling"); | 
|  1690     } |  1710     } | 
|  1691     ASSERT(!compiler->is_optimizing()); |  1711     ASSERT(!compiler->is_optimizing()); | 
|  1692     return;  // Nothing to emit. |  1712     return;  // Nothing to emit. | 
|  1693   } |  1713   } | 
|  1694  |  1714  | 
|  1695   Label* deopt = compiler->is_optimizing() ? |  1715   Label* deopt = | 
|  1696       compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL; |  1716       compiler->is_optimizing() | 
 |  1717           ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) | 
 |  1718           : NULL; | 
|  1697  |  1719  | 
|  1698   const Register value_reg = locs()->in(0).reg(); |  1720   const Register value_reg = locs()->in(0).reg(); | 
|  1699  |  1721  | 
|  1700   if (!compiler->is_optimizing() || |  1722   if (!compiler->is_optimizing() || | 
|  1701       (field().guarded_list_length() == Field::kUnknownFixedLength)) { |  1723       (field().guarded_list_length() == Field::kUnknownFixedLength)) { | 
|  1702     const Register field_reg = locs()->temp(0).reg(); |  1724     const Register field_reg = locs()->temp(0).reg(); | 
|  1703     const Register offset_reg = locs()->temp(1).reg(); |  1725     const Register offset_reg = locs()->temp(1).reg(); | 
|  1704     const Register length_reg = locs()->temp(2).reg(); |  1726     const Register length_reg = locs()->temp(2).reg(); | 
|  1705  |  1727  | 
|  1706     Label ok; |  1728     Label ok; | 
|  1707  |  1729  | 
|  1708     __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); |  1730     __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); | 
|  1709  |  1731  | 
|  1710     __ ldr(offset_reg, |  1732     __ ldr(offset_reg, | 
|  1711            FieldAddress(field_reg, |  1733            FieldAddress(field_reg, | 
|  1712                         Field::guarded_list_length_in_object_offset_offset()), |  1734                         Field::guarded_list_length_in_object_offset_offset()), | 
|  1713            kByte); |  1735            kByte); | 
|  1714     __ ldr(length_reg, FieldAddress(field_reg, |  1736     __ ldr(length_reg, | 
|  1715         Field::guarded_list_length_offset())); |  1737            FieldAddress(field_reg, Field::guarded_list_length_offset())); | 
|  1716  |  1738  | 
|  1717     __ tst(offset_reg, Operand(offset_reg)); |  1739     __ tst(offset_reg, Operand(offset_reg)); | 
|  1718     __ b(&ok, MI); |  1740     __ b(&ok, MI); | 
|  1719  |  1741  | 
|  1720     // Load the length from the value. GuardFieldClass already verified that |  1742     // Load the length from the value. GuardFieldClass already verified that | 
|  1721     // value's class matches guarded class id of the field. |  1743     // value's class matches guarded class id of the field. | 
|  1722     // offset_reg contains offset already corrected by -kHeapObjectTag that is |  1744     // offset_reg contains offset already corrected by -kHeapObjectTag that is | 
|  1723     // why we use Address instead of FieldAddress. |  1745     // why we use Address instead of FieldAddress. | 
|  1724     __ ldr(TMP, Address(value_reg, offset_reg)); |  1746     __ ldr(TMP, Address(value_reg, offset_reg)); | 
|  1725     __ CompareRegisters(length_reg, TMP); |  1747     __ CompareRegisters(length_reg, TMP); | 
|  1726  |  1748  | 
|  1727     if (deopt == NULL) { |  1749     if (deopt == NULL) { | 
|  1728       __ b(&ok, EQ); |  1750       __ b(&ok, EQ); | 
|  1729  |  1751  | 
|  1730       __ Push(field_reg); |  1752       __ Push(field_reg); | 
|  1731       __ Push(value_reg); |  1753       __ Push(value_reg); | 
|  1732       __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2); |  1754       __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2); | 
|  1733       __ Drop(2);  // Drop the field and the value. |  1755       __ Drop(2);  // Drop the field and the value. | 
|  1734     } else { |  1756     } else { | 
|  1735       __ b(deopt, NE); |  1757       __ b(deopt, NE); | 
|  1736     } |  1758     } | 
|  1737  |  1759  | 
|  1738     __ Bind(&ok); |  1760     __ Bind(&ok); | 
|  1739   } else { |  1761   } else { | 
|  1740     ASSERT(compiler->is_optimizing()); |  1762     ASSERT(compiler->is_optimizing()); | 
|  1741     ASSERT(field().guarded_list_length() >= 0); |  1763     ASSERT(field().guarded_list_length() >= 0); | 
|  1742     ASSERT(field().guarded_list_length_in_object_offset() != |  1764     ASSERT(field().guarded_list_length_in_object_offset() != | 
|  1743         Field::kUnknownLengthOffset); |  1765            Field::kUnknownLengthOffset); | 
|  1744  |  1766  | 
|  1745     __ ldr(TMP, FieldAddress(value_reg, |  1767     __ ldr(TMP, FieldAddress(value_reg, | 
|  1746                             field().guarded_list_length_in_object_offset())); |  1768                              field().guarded_list_length_in_object_offset())); | 
|  1747     __ CompareImmediate(TMP, Smi::RawValue(field().guarded_list_length())); |  1769     __ CompareImmediate(TMP, Smi::RawValue(field().guarded_list_length())); | 
|  1748     __ b(deopt, NE); |  1770     __ b(deopt, NE); | 
|  1749   } |  1771   } | 
|  1750 } |  1772 } | 
|  1751  |  1773  | 
|  1752  |  1774  | 
|  1753 class BoxAllocationSlowPath : public SlowPathCode { |  1775 class BoxAllocationSlowPath : public SlowPathCode { | 
|  1754  public: |  1776  public: | 
|  1755   BoxAllocationSlowPath(Instruction* instruction, |  1777   BoxAllocationSlowPath(Instruction* instruction, | 
|  1756                         const Class& cls, |  1778                         const Class& cls, | 
|  1757                         Register result) |  1779                         Register result) | 
|  1758       : instruction_(instruction), |  1780       : instruction_(instruction), cls_(cls), result_(result) {} | 
|  1759         cls_(cls), |  | 
|  1760         result_(result) { } |  | 
|  1761  |  1781  | 
|  1762   virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |  1782   virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  1763     if (Assembler::EmittingComments()) { |  1783     if (Assembler::EmittingComments()) { | 
|  1764       __ Comment("%s slow path allocation of %s", |  1784       __ Comment("%s slow path allocation of %s", instruction_->DebugName(), | 
|  1765                  instruction_->DebugName(), |  | 
|  1766                  String::Handle(cls_.ScrubbedName()).ToCString()); |  1785                  String::Handle(cls_.ScrubbedName()).ToCString()); | 
|  1767     } |  1786     } | 
|  1768     __ Bind(entry_label()); |  1787     __ Bind(entry_label()); | 
|  1769     const Code& stub = Code::ZoneHandle(compiler->zone(), |  1788     const Code& stub = Code::ZoneHandle( | 
|  1770         StubCode::GetAllocationStubForClass(cls_)); |  1789         compiler->zone(), StubCode::GetAllocationStubForClass(cls_)); | 
|  1771     const StubEntry stub_entry(stub); |  1790     const StubEntry stub_entry(stub); | 
|  1772  |  1791  | 
|  1773     LocationSummary* locs = instruction_->locs(); |  1792     LocationSummary* locs = instruction_->locs(); | 
|  1774  |  1793  | 
|  1775     locs->live_registers()->Remove(Location::RegisterLocation(result_)); |  1794     locs->live_registers()->Remove(Location::RegisterLocation(result_)); | 
|  1776  |  1795  | 
|  1777     compiler->SaveLiveRegisters(locs); |  1796     compiler->SaveLiveRegisters(locs); | 
|  1778     compiler->GenerateCall(TokenPosition::kNoSource,  // No token position. |  1797     compiler->GenerateCall(TokenPosition::kNoSource,  // No token position. | 
|  1779                            stub_entry, |  1798                            stub_entry, RawPcDescriptors::kOther, locs); | 
|  1780                            RawPcDescriptors::kOther, |  | 
|  1781                            locs); |  | 
|  1782     compiler->AddStubCallTarget(stub); |  1799     compiler->AddStubCallTarget(stub); | 
|  1783     __ mov(result_, R0); |  1800     __ mov(result_, R0); | 
|  1784     compiler->RestoreLiveRegisters(locs); |  1801     compiler->RestoreLiveRegisters(locs); | 
|  1785     __ b(exit_label()); |  1802     __ b(exit_label()); | 
|  1786   } |  1803   } | 
|  1787  |  1804  | 
|  1788   static void Allocate(FlowGraphCompiler* compiler, |  1805   static void Allocate(FlowGraphCompiler* compiler, | 
|  1789                        Instruction* instruction, |  1806                        Instruction* instruction, | 
|  1790                        const Class& cls, |  1807                        const Class& cls, | 
|  1791                        Register result, |  1808                        Register result, | 
| (...skipping 21 matching lines...) Expand all  Loading... | 
|  1813                              StoreInstanceFieldInstr* instruction, |  1830                              StoreInstanceFieldInstr* instruction, | 
|  1814                              Register box_reg, |  1831                              Register box_reg, | 
|  1815                              const Class& cls, |  1832                              const Class& cls, | 
|  1816                              Register instance_reg, |  1833                              Register instance_reg, | 
|  1817                              intptr_t offset, |  1834                              intptr_t offset, | 
|  1818                              Register temp) { |  1835                              Register temp) { | 
|  1819   Label done; |  1836   Label done; | 
|  1820   __ LoadFieldFromOffset(box_reg, instance_reg, offset); |  1837   __ LoadFieldFromOffset(box_reg, instance_reg, offset); | 
|  1821   __ CompareObject(box_reg, Object::null_object()); |  1838   __ CompareObject(box_reg, Object::null_object()); | 
|  1822   __ b(&done, NE); |  1839   __ b(&done, NE); | 
|  1823   BoxAllocationSlowPath::Allocate( |  1840   BoxAllocationSlowPath::Allocate(compiler, instruction, cls, box_reg, temp); | 
|  1824       compiler, instruction, cls, box_reg, temp); |  | 
|  1825   __ mov(temp, box_reg); |  1841   __ mov(temp, box_reg); | 
|  1826   __ StoreIntoObjectOffset(instance_reg, offset, temp); |  1842   __ StoreIntoObjectOffset(instance_reg, offset, temp); | 
|  1827   __ Bind(&done); |  1843   __ Bind(&done); | 
|  1828 } |  1844 } | 
|  1829  |  1845  | 
|  1830  |  1846  | 
|  1831 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone, |  1847 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone, | 
|  1832                                                               bool opt) const { |  1848                                                               bool opt) const { | 
|  1833   const intptr_t kNumInputs = 2; |  1849   const intptr_t kNumInputs = 2; | 
|  1834   const intptr_t kNumTemps = |  1850   const intptr_t kNumTemps = | 
|  1835       (IsUnboxedStore() && opt) ? 2 : |  1851       (IsUnboxedStore() && opt) ? 2 : ((IsPotentialUnboxedStore()) ? 2 : 0); | 
|  1836           ((IsPotentialUnboxedStore()) ? 2 : 0); |  1852   LocationSummary* summary = new (zone) | 
|  1837   LocationSummary* summary = new(zone) LocationSummary( |  1853       LocationSummary(zone, kNumInputs, kNumTemps, | 
|  1838       zone, kNumInputs, kNumTemps, |  1854                       ((IsUnboxedStore() && opt && is_initialization()) || | 
|  1839           ((IsUnboxedStore() && opt && is_initialization()) || |  1855                        IsPotentialUnboxedStore()) | 
|  1840            IsPotentialUnboxedStore()) |  1856                           ? LocationSummary::kCallOnSlowPath | 
|  1841           ? LocationSummary::kCallOnSlowPath |  1857                           : LocationSummary::kNoCall); | 
|  1842           : LocationSummary::kNoCall); |  | 
|  1843  |  1858  | 
|  1844   summary->set_in(0, Location::RequiresRegister()); |  1859   summary->set_in(0, Location::RequiresRegister()); | 
|  1845   if (IsUnboxedStore() && opt) { |  1860   if (IsUnboxedStore() && opt) { | 
|  1846     summary->set_in(1, Location::RequiresFpuRegister()); |  1861     summary->set_in(1, Location::RequiresFpuRegister()); | 
|  1847     summary->set_temp(0, Location::RequiresRegister()); |  1862     summary->set_temp(0, Location::RequiresRegister()); | 
|  1848     summary->set_temp(1, Location::RequiresRegister()); |  1863     summary->set_temp(1, Location::RequiresRegister()); | 
|  1849   } else if (IsPotentialUnboxedStore()) { |  1864   } else if (IsPotentialUnboxedStore()) { | 
|  1850       summary->set_in(1, ShouldEmitStoreBarrier() |  1865     summary->set_in(1, ShouldEmitStoreBarrier() ? Location::WritableRegister() | 
|  1851           ? Location::WritableRegister() |  1866                                                 : Location::RequiresRegister()); | 
|  1852           :  Location::RequiresRegister()); |  1867     summary->set_temp(0, Location::RequiresRegister()); | 
|  1853       summary->set_temp(0, Location::RequiresRegister()); |  1868     summary->set_temp(1, Location::RequiresRegister()); | 
|  1854       summary->set_temp(1, Location::RequiresRegister()); |  | 
|  1855   } else { |  1869   } else { | 
|  1856     summary->set_in(1, ShouldEmitStoreBarrier() |  1870     summary->set_in(1, ShouldEmitStoreBarrier() | 
|  1857                        ? Location::WritableRegister() |  1871                            ? Location::WritableRegister() | 
|  1858                        : Location::RegisterOrConstant(value())); |  1872                            : Location::RegisterOrConstant(value())); | 
|  1859   } |  1873   } | 
|  1860   return summary; |  1874   return summary; | 
|  1861 } |  1875 } | 
|  1862  |  1876  | 
|  1863  |  1877  | 
|  1864 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  1878 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  1865   ASSERT(sizeof(classid_t) == kInt32Size); |  1879   ASSERT(sizeof(classid_t) == kInt32Size); | 
|  1866   Label skip_store; |  1880   Label skip_store; | 
|  1867  |  1881  | 
|  1868   const Register instance_reg = locs()->in(0).reg(); |  1882   const Register instance_reg = locs()->in(0).reg(); | 
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1931     Label store_float32x4; |  1945     Label store_float32x4; | 
|  1932     Label store_float64x2; |  1946     Label store_float64x2; | 
|  1933  |  1947  | 
|  1934     __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); |  1948     __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); | 
|  1935  |  1949  | 
|  1936     __ LoadFieldFromOffset(temp2, temp, Field::is_nullable_offset(), |  1950     __ LoadFieldFromOffset(temp2, temp, Field::is_nullable_offset(), | 
|  1937                            kUnsignedWord); |  1951                            kUnsignedWord); | 
|  1938     __ CompareImmediate(temp2, kNullCid); |  1952     __ CompareImmediate(temp2, kNullCid); | 
|  1939     __ b(&store_pointer, EQ); |  1953     __ b(&store_pointer, EQ); | 
|  1940  |  1954  | 
|  1941     __ LoadFromOffset( |  1955     __ LoadFromOffset(temp2, temp, Field::kind_bits_offset() - kHeapObjectTag, | 
|  1942         temp2, temp, Field::kind_bits_offset() - kHeapObjectTag, |  1956                       kUnsignedByte); | 
|  1943         kUnsignedByte); |  | 
|  1944     __ tsti(temp2, Immediate(1 << Field::kUnboxingCandidateBit)); |  1957     __ tsti(temp2, Immediate(1 << Field::kUnboxingCandidateBit)); | 
|  1945     __ b(&store_pointer, EQ); |  1958     __ b(&store_pointer, EQ); | 
|  1946  |  1959  | 
|  1947     __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), |  1960     __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), | 
|  1948                            kUnsignedWord); |  1961                            kUnsignedWord); | 
|  1949     __ CompareImmediate(temp2, kDoubleCid); |  1962     __ CompareImmediate(temp2, kDoubleCid); | 
|  1950     __ b(&store_double, EQ); |  1963     __ b(&store_double, EQ); | 
|  1951  |  1964  | 
|  1952     __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), |  1965     __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), | 
|  1953                            kUnsignedWord); |  1966                            kUnsignedWord); | 
|  1954     __ CompareImmediate(temp2, kFloat32x4Cid); |  1967     __ CompareImmediate(temp2, kFloat32x4Cid); | 
|  1955     __ b(&store_float32x4, EQ); |  1968     __ b(&store_float32x4, EQ); | 
|  1956  |  1969  | 
|  1957     __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), |  1970     __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), | 
|  1958                            kUnsignedWord); |  1971                            kUnsignedWord); | 
|  1959     __ CompareImmediate(temp2, kFloat64x2Cid); |  1972     __ CompareImmediate(temp2, kFloat64x2Cid); | 
|  1960     __ b(&store_float64x2, EQ); |  1973     __ b(&store_float64x2, EQ); | 
|  1961  |  1974  | 
|  1962     // Fall through. |  1975     // Fall through. | 
|  1963     __ b(&store_pointer); |  1976     __ b(&store_pointer); | 
|  1964  |  1977  | 
|  1965     if (!compiler->is_optimizing()) { |  1978     if (!compiler->is_optimizing()) { | 
|  1966         locs()->live_registers()->Add(locs()->in(0)); |  1979       locs()->live_registers()->Add(locs()->in(0)); | 
|  1967         locs()->live_registers()->Add(locs()->in(1)); |  1980       locs()->live_registers()->Add(locs()->in(1)); | 
|  1968     } |  1981     } | 
|  1969  |  1982  | 
|  1970     { |  1983     { | 
|  1971       __ Bind(&store_double); |  1984       __ Bind(&store_double); | 
|  1972       EnsureMutableBox(compiler, |  1985       EnsureMutableBox(compiler, this, temp, compiler->double_class(), | 
|  1973                        this, |  1986                        instance_reg, offset_in_bytes_, temp2); | 
|  1974                        temp, |  | 
|  1975                        compiler->double_class(), |  | 
|  1976                        instance_reg, |  | 
|  1977                        offset_in_bytes_, |  | 
|  1978                        temp2); |  | 
|  1979       __ LoadDFieldFromOffset(VTMP, value_reg, Double::value_offset()); |  1987       __ LoadDFieldFromOffset(VTMP, value_reg, Double::value_offset()); | 
|  1980       __ StoreDFieldToOffset(VTMP, temp, Double::value_offset()); |  1988       __ StoreDFieldToOffset(VTMP, temp, Double::value_offset()); | 
|  1981       __ b(&skip_store); |  1989       __ b(&skip_store); | 
|  1982     } |  1990     } | 
|  1983  |  1991  | 
|  1984     { |  1992     { | 
|  1985       __ Bind(&store_float32x4); |  1993       __ Bind(&store_float32x4); | 
|  1986       EnsureMutableBox(compiler, |  1994       EnsureMutableBox(compiler, this, temp, compiler->float32x4_class(), | 
|  1987                        this, |  1995                        instance_reg, offset_in_bytes_, temp2); | 
|  1988                        temp, |  | 
|  1989                        compiler->float32x4_class(), |  | 
|  1990                        instance_reg, |  | 
|  1991                        offset_in_bytes_, |  | 
|  1992                        temp2); |  | 
|  1993       __ LoadQFieldFromOffset(VTMP, value_reg, Float32x4::value_offset()); |  1996       __ LoadQFieldFromOffset(VTMP, value_reg, Float32x4::value_offset()); | 
|  1994       __ StoreQFieldToOffset(VTMP, temp, Float32x4::value_offset()); |  1997       __ StoreQFieldToOffset(VTMP, temp, Float32x4::value_offset()); | 
|  1995       __ b(&skip_store); |  1998       __ b(&skip_store); | 
|  1996     } |  1999     } | 
|  1997  |  2000  | 
|  1998     { |  2001     { | 
|  1999       __ Bind(&store_float64x2); |  2002       __ Bind(&store_float64x2); | 
|  2000       EnsureMutableBox(compiler, |  2003       EnsureMutableBox(compiler, this, temp, compiler->float64x2_class(), | 
|  2001                        this, |  2004                        instance_reg, offset_in_bytes_, temp2); | 
|  2002                        temp, |  | 
|  2003                        compiler->float64x2_class(), |  | 
|  2004                        instance_reg, |  | 
|  2005                        offset_in_bytes_, |  | 
|  2006                        temp2); |  | 
|  2007       __ LoadQFieldFromOffset(VTMP, value_reg, Float64x2::value_offset()); |  2005       __ LoadQFieldFromOffset(VTMP, value_reg, Float64x2::value_offset()); | 
|  2008       __ StoreQFieldToOffset(VTMP, temp, Float64x2::value_offset()); |  2006       __ StoreQFieldToOffset(VTMP, temp, Float64x2::value_offset()); | 
|  2009       __ b(&skip_store); |  2007       __ b(&skip_store); | 
|  2010     } |  2008     } | 
|  2011  |  2009  | 
|  2012     __ Bind(&store_pointer); |  2010     __ Bind(&store_pointer); | 
|  2013   } |  2011   } | 
|  2014  |  2012  | 
|  2015   if (ShouldEmitStoreBarrier()) { |  2013   if (ShouldEmitStoreBarrier()) { | 
|  2016     const Register value_reg = locs()->in(1).reg(); |  2014     const Register value_reg = locs()->in(1).reg(); | 
|  2017     __ StoreIntoObjectOffset( |  2015     __ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, value_reg, | 
|  2018         instance_reg, offset_in_bytes_, value_reg, CanValueBeSmi()); |  2016                              CanValueBeSmi()); | 
|  2019   } else { |  2017   } else { | 
|  2020     if (locs()->in(1).IsConstant()) { |  2018     if (locs()->in(1).IsConstant()) { | 
|  2021       __ StoreIntoObjectOffsetNoBarrier( |  2019       __ StoreIntoObjectOffsetNoBarrier(instance_reg, offset_in_bytes_, | 
|  2022           instance_reg, offset_in_bytes_, locs()->in(1).constant()); |  2020                                         locs()->in(1).constant()); | 
|  2023     } else { |  2021     } else { | 
|  2024       const Register value_reg = locs()->in(1).reg(); |  2022       const Register value_reg = locs()->in(1).reg(); | 
|  2025       __ StoreIntoObjectOffsetNoBarrier( |  2023       __ StoreIntoObjectOffsetNoBarrier(instance_reg, offset_in_bytes_, | 
|  2026           instance_reg, offset_in_bytes_, value_reg); |  2024                                         value_reg); | 
|  2027     } |  2025     } | 
|  2028   } |  2026   } | 
|  2029   __ Bind(&skip_store); |  2027   __ Bind(&skip_store); | 
|  2030 } |  2028 } | 
|  2031  |  2029  | 
|  2032  |  2030  | 
|  2033 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(Zone* zone, |  2031 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(Zone* zone, | 
|  2034                                                            bool opt) const { |  2032                                                            bool opt) const { | 
|  2035   const intptr_t kNumInputs = 1; |  2033   const intptr_t kNumInputs = 1; | 
|  2036   const intptr_t kNumTemps = 0; |  2034   const intptr_t kNumTemps = 0; | 
|  2037   LocationSummary* summary = new(zone) LocationSummary( |  2035   LocationSummary* summary = new (zone) | 
|  2038       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  2036       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  2039   summary->set_in(0, Location::RequiresRegister()); |  2037   summary->set_in(0, Location::RequiresRegister()); | 
|  2040   summary->set_out(0, Location::RequiresRegister()); |  2038   summary->set_out(0, Location::RequiresRegister()); | 
|  2041   return summary; |  2039   return summary; | 
|  2042 } |  2040 } | 
|  2043  |  2041  | 
|  2044  |  2042  | 
|  2045 // When the parser is building an implicit static getter for optimization, |  2043 // When the parser is building an implicit static getter for optimization, | 
|  2046 // it can generate a function body where deoptimization ids do not line up |  2044 // it can generate a function body where deoptimization ids do not line up | 
|  2047 // with the unoptimized code. |  2045 // with the unoptimized code. | 
|  2048 // |  2046 // | 
|  2049 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. |  2047 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. | 
|  2050 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  2048 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  2051   const Register field = locs()->in(0).reg(); |  2049   const Register field = locs()->in(0).reg(); | 
|  2052   const Register result = locs()->out(0).reg(); |  2050   const Register result = locs()->out(0).reg(); | 
|  2053   __ LoadFieldFromOffset(result, field, Field::static_value_offset()); |  2051   __ LoadFieldFromOffset(result, field, Field::static_value_offset()); | 
|  2054 } |  2052 } | 
|  2055  |  2053  | 
|  2056  |  2054  | 
|  2057 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Zone* zone, |  2055 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Zone* zone, | 
|  2058                                                             bool opt) const { |  2056                                                             bool opt) const { | 
|  2059   LocationSummary* locs = new(zone) LocationSummary( |  2057   LocationSummary* locs = | 
|  2060       zone, 1, 1, LocationSummary::kNoCall); |  2058       new (zone) LocationSummary(zone, 1, 1, LocationSummary::kNoCall); | 
|  2061   locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() |  2059   locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() | 
|  2062                                               : Location::RequiresRegister()); |  2060                                               : Location::RequiresRegister()); | 
|  2063   locs->set_temp(0, Location::RequiresRegister()); |  2061   locs->set_temp(0, Location::RequiresRegister()); | 
|  2064   return locs; |  2062   return locs; | 
|  2065 } |  2063 } | 
|  2066  |  2064  | 
|  2067  |  2065  | 
|  2068 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  2066 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  2069   const Register value = locs()->in(0).reg(); |  2067   const Register value = locs()->in(0).reg(); | 
|  2070   const Register temp = locs()->temp(0).reg(); |  2068   const Register temp = locs()->temp(0).reg(); | 
|  2071  |  2069  | 
|  2072   __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); |  2070   __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); | 
|  2073   if (this->value()->NeedsStoreBuffer()) { |  2071   if (this->value()->NeedsStoreBuffer()) { | 
|  2074     __ StoreIntoObjectOffset( |  2072     __ StoreIntoObjectOffset(temp, Field::static_value_offset(), value, | 
|  2075         temp, Field::static_value_offset(), value, CanValueBeSmi()); |  2073                              CanValueBeSmi()); | 
|  2076   } else { |  2074   } else { | 
|  2077     __ StoreIntoObjectOffsetNoBarrier(temp, |  2075     __ StoreIntoObjectOffsetNoBarrier(temp, Field::static_value_offset(), | 
|  2078                                       Field::static_value_offset(), |  | 
|  2079                                       value); |  2076                                       value); | 
|  2080   } |  2077   } | 
|  2081 } |  2078 } | 
|  2082  |  2079  | 
|  2083  |  2080  | 
|  2084 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone, |  2081 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone, | 
|  2085                                                       bool opt) const { |  2082                                                       bool opt) const { | 
|  2086   const intptr_t kNumInputs = 2; |  2083   const intptr_t kNumInputs = 2; | 
|  2087   const intptr_t kNumTemps = 0; |  2084   const intptr_t kNumTemps = 0; | 
|  2088   LocationSummary* summary = new(zone) LocationSummary( |  2085   LocationSummary* summary = new (zone) | 
|  2089       zone, kNumInputs, kNumTemps, LocationSummary::kCall); |  2086       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 
|  2090   summary->set_in(0, Location::RegisterLocation(R0)); |  2087   summary->set_in(0, Location::RegisterLocation(R0)); | 
|  2091   summary->set_in(1, Location::RegisterLocation(R1)); |  2088   summary->set_in(1, Location::RegisterLocation(R1)); | 
|  2092   summary->set_out(0, Location::RegisterLocation(R0)); |  2089   summary->set_out(0, Location::RegisterLocation(R0)); | 
|  2093   return summary; |  2090   return summary; | 
|  2094 } |  2091 } | 
|  2095  |  2092  | 
|  2096  |  2093  | 
|  2097 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  2094 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  2098   ASSERT(locs()->in(0).reg() == R0);  // Value. |  2095   ASSERT(locs()->in(0).reg() == R0);  // Value. | 
|  2099   ASSERT(locs()->in(1).reg() == R1);  // Instantiator type arguments. |  2096   ASSERT(locs()->in(1).reg() == R1);  // Instantiator type arguments. | 
|  2100  |  2097  | 
|  2101   compiler->GenerateInstanceOf(token_pos(), |  2098   compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), negate_result(), | 
|  2102                                deopt_id(), |  | 
|  2103                                type(), |  | 
|  2104                                negate_result(), |  | 
|  2105                                locs()); |  2099                                locs()); | 
|  2106   ASSERT(locs()->out(0).reg() == R0); |  2100   ASSERT(locs()->out(0).reg() == R0); | 
|  2107 } |  2101 } | 
|  2108  |  2102  | 
|  2109  |  2103  | 
|  2110 LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone, |  2104 LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone, | 
|  2111                                                        bool opt) const { |  2105                                                        bool opt) const { | 
|  2112   const intptr_t kNumInputs = 2; |  2106   const intptr_t kNumInputs = 2; | 
|  2113   const intptr_t kNumTemps = 0; |  2107   const intptr_t kNumTemps = 0; | 
|  2114   LocationSummary* locs = new(zone) LocationSummary( |  2108   LocationSummary* locs = new (zone) | 
|  2115       zone, kNumInputs, kNumTemps, LocationSummary::kCall); |  2109       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 
|  2116   locs->set_in(kElementTypePos, Location::RegisterLocation(R1)); |  2110   locs->set_in(kElementTypePos, Location::RegisterLocation(R1)); | 
|  2117   locs->set_in(kLengthPos, Location::RegisterLocation(R2)); |  2111   locs->set_in(kLengthPos, Location::RegisterLocation(R2)); | 
|  2118   locs->set_out(0, Location::RegisterLocation(R0)); |  2112   locs->set_out(0, Location::RegisterLocation(R0)); | 
|  2119   return locs; |  2113   return locs; | 
|  2120 } |  2114 } | 
|  2121  |  2115  | 
|  2122  |  2116  | 
|  2123 // Inlines array allocation for known constant values. |  2117 // Inlines array allocation for known constant values. | 
|  2124 static void InlineArrayAllocation(FlowGraphCompiler* compiler, |  2118 static void InlineArrayAllocation(FlowGraphCompiler* compiler, | 
|  2125                                    intptr_t num_elements, |  2119                                   intptr_t num_elements, | 
|  2126                                    Label* slow_path, |  2120                                   Label* slow_path, | 
|  2127                                    Label* done) { |  2121                                   Label* done) { | 
|  2128   const int kInlineArraySize = 12;  // Same as kInlineInstanceSize. |  2122   const int kInlineArraySize = 12;  // Same as kInlineInstanceSize. | 
|  2129   const Register kLengthReg = R2; |  2123   const Register kLengthReg = R2; | 
|  2130   const Register kElemTypeReg = R1; |  2124   const Register kElemTypeReg = R1; | 
|  2131   const intptr_t instance_size = Array::InstanceSize(num_elements); |  2125   const intptr_t instance_size = Array::InstanceSize(num_elements); | 
|  2132  |  2126  | 
|  2133   __ TryAllocateArray(kArrayCid, instance_size, slow_path, |  2127   __ TryAllocateArray(kArrayCid, instance_size, slow_path, | 
|  2134                       R0,  // instance |  2128                       R0,  // instance | 
|  2135                       R3,  // end address |  2129                       R3,  // end address | 
|  2136                       R6, |  2130                       R6, R8); | 
|  2137                       R8); |  | 
|  2138   // R0: new object start as a tagged pointer. |  2131   // R0: new object start as a tagged pointer. | 
|  2139   // R3: new object end address. |  2132   // R3: new object end address. | 
|  2140  |  2133  | 
|  2141   // Store the type argument field. |  2134   // Store the type argument field. | 
|  2142   __ StoreIntoObjectNoBarrier(R0, |  2135   __ StoreIntoObjectNoBarrier( | 
|  2143                               FieldAddress(R0, Array::type_arguments_offset()), |  2136       R0, FieldAddress(R0, Array::type_arguments_offset()), kElemTypeReg); | 
|  2144                               kElemTypeReg); |  | 
|  2145  |  2137  | 
|  2146   // Set the length field. |  2138   // Set the length field. | 
|  2147   __ StoreIntoObjectNoBarrier(R0, |  2139   __ StoreIntoObjectNoBarrier(R0, FieldAddress(R0, Array::length_offset()), | 
|  2148                               FieldAddress(R0, Array::length_offset()), |  | 
|  2149                               kLengthReg); |  2140                               kLengthReg); | 
|  2150  |  2141  | 
|  2151   // TODO(zra): Use stp once added. |  2142   // TODO(zra): Use stp once added. | 
|  2152   // Initialize all array elements to raw_null. |  2143   // Initialize all array elements to raw_null. | 
|  2153   // R0: new object start as a tagged pointer. |  2144   // R0: new object start as a tagged pointer. | 
|  2154   // R3: new object end address. |  2145   // R3: new object end address. | 
|  2155   // R8: iterator which initially points to the start of the variable |  2146   // R8: iterator which initially points to the start of the variable | 
|  2156   // data area to be initialized. |  2147   // data area to be initialized. | 
|  2157   // R6: null |  2148   // R6: null | 
|  2158   if (num_elements > 0) { |  2149   if (num_elements > 0) { | 
| (...skipping 22 matching lines...) Expand all  Loading... | 
|  2181  |  2172  | 
|  2182  |  2173  | 
|  2183 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  2174 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  2184   const Register kLengthReg = R2; |  2175   const Register kLengthReg = R2; | 
|  2185   const Register kElemTypeReg = R1; |  2176   const Register kElemTypeReg = R1; | 
|  2186   const Register kResultReg = R0; |  2177   const Register kResultReg = R0; | 
|  2187  |  2178  | 
|  2188   ASSERT(locs()->in(kElementTypePos).reg() == kElemTypeReg); |  2179   ASSERT(locs()->in(kElementTypePos).reg() == kElemTypeReg); | 
|  2189   ASSERT(locs()->in(kLengthPos).reg() == kLengthReg); |  2180   ASSERT(locs()->in(kLengthPos).reg() == kLengthReg); | 
|  2190  |  2181  | 
|  2191   if (compiler->is_optimizing() && |  2182   if (compiler->is_optimizing() && !FLAG_precompiled_mode && | 
|  2192       !FLAG_precompiled_mode && |  | 
|  2193       num_elements()->BindsToConstant() && |  2183       num_elements()->BindsToConstant() && | 
|  2194       num_elements()->BoundConstant().IsSmi()) { |  2184       num_elements()->BoundConstant().IsSmi()) { | 
|  2195     const intptr_t length = Smi::Cast(num_elements()->BoundConstant()).Value(); |  2185     const intptr_t length = Smi::Cast(num_elements()->BoundConstant()).Value(); | 
|  2196     if ((length >= 0) && (length <= Array::kMaxElements)) { |  2186     if ((length >= 0) && (length <= Array::kMaxElements)) { | 
|  2197       Label slow_path, done; |  2187       Label slow_path, done; | 
|  2198       InlineArrayAllocation(compiler, length, &slow_path, &done); |  2188       InlineArrayAllocation(compiler, length, &slow_path, &done); | 
|  2199       __ Bind(&slow_path); |  2189       __ Bind(&slow_path); | 
|  2200       __ PushObject(Object::null_object());  // Make room for the result. |  2190       __ PushObject(Object::null_object());  // Make room for the result. | 
|  2201       __ Push(kLengthReg);  // length. |  2191       __ Push(kLengthReg);                   // length. | 
|  2202       __ Push(kElemTypeReg); |  2192       __ Push(kElemTypeReg); | 
|  2203       compiler->GenerateRuntimeCall(token_pos(), |  2193       compiler->GenerateRuntimeCall(token_pos(), deopt_id(), | 
|  2204                                     deopt_id(), |  2194                                     kAllocateArrayRuntimeEntry, 2, locs()); | 
|  2205                                     kAllocateArrayRuntimeEntry, |  | 
|  2206                                     2, |  | 
|  2207                                     locs()); |  | 
|  2208       __ Drop(2); |  2195       __ Drop(2); | 
|  2209       __ Pop(kResultReg); |  2196       __ Pop(kResultReg); | 
|  2210       __ Bind(&done); |  2197       __ Bind(&done); | 
|  2211       return; |  2198       return; | 
|  2212     } |  2199     } | 
|  2213   } |  2200   } | 
|  2214   const Code& stub = Code::ZoneHandle(compiler->zone(), |  2201   const Code& stub = Code::ZoneHandle(compiler->zone(), | 
|  2215                                       StubCode::AllocateArray_entry()->code()); |  2202                                       StubCode::AllocateArray_entry()->code()); | 
|  2216   compiler->AddStubCallTarget(stub); |  2203   compiler->AddStubCallTarget(stub); | 
|  2217   compiler->GenerateCall(token_pos(), |  2204   compiler->GenerateCall(token_pos(), *StubCode::AllocateArray_entry(), | 
|  2218                          *StubCode::AllocateArray_entry(), |  2205                          RawPcDescriptors::kOther, locs()); | 
|  2219                          RawPcDescriptors::kOther, |  | 
|  2220                          locs()); |  | 
|  2221   ASSERT(locs()->out(0).reg() == kResultReg); |  2206   ASSERT(locs()->out(0).reg() == kResultReg); | 
|  2222 } |  2207 } | 
|  2223  |  2208  | 
|  2224  |  2209  | 
|  2225 LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone, |  2210 LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone, | 
|  2226                                                      bool opt) const { |  2211                                                      bool opt) const { | 
|  2227   const intptr_t kNumInputs = 1; |  2212   const intptr_t kNumInputs = 1; | 
|  2228   const intptr_t kNumTemps = |  2213   const intptr_t kNumTemps = | 
|  2229       (IsUnboxedLoad() && opt) ? 1 : |  2214       (IsUnboxedLoad() && opt) ? 1 : ((IsPotentialUnboxedLoad()) ? 1 : 0); | 
|  2230           ((IsPotentialUnboxedLoad()) ? 1 : 0); |  2215   LocationSummary* locs = new (zone) LocationSummary( | 
|  2231   LocationSummary* locs = new(zone) LocationSummary( |  2216       zone, kNumInputs, kNumTemps, (opt && !IsPotentialUnboxedLoad()) | 
|  2232       zone, kNumInputs, kNumTemps, |  2217                                        ? LocationSummary::kNoCall | 
|  2233       (opt && !IsPotentialUnboxedLoad()) |  2218                                        : LocationSummary::kCallOnSlowPath); | 
|  2234           ? LocationSummary::kNoCall |  | 
|  2235           : LocationSummary::kCallOnSlowPath); |  | 
|  2236  |  2219  | 
|  2237   locs->set_in(0, Location::RequiresRegister()); |  2220   locs->set_in(0, Location::RequiresRegister()); | 
|  2238  |  2221  | 
|  2239   if (IsUnboxedLoad() && opt) { |  2222   if (IsUnboxedLoad() && opt) { | 
|  2240     locs->set_temp(0, Location::RequiresRegister()); |  2223     locs->set_temp(0, Location::RequiresRegister()); | 
|  2241   } else if (IsPotentialUnboxedLoad()) { |  2224   } else if (IsPotentialUnboxedLoad()) { | 
|  2242     locs->set_temp(0, Location::RequiresRegister()); |  2225     locs->set_temp(0, Location::RequiresRegister()); | 
|  2243   } |  2226   } | 
|  2244   locs->set_out(0, Location::RequiresRegister()); |  2227   locs->set_out(0, Location::RequiresRegister()); | 
|  2245   return locs; |  2228   return locs; | 
| (...skipping 30 matching lines...) Expand all  Loading... | 
|  2276   if (IsPotentialUnboxedLoad()) { |  2259   if (IsPotentialUnboxedLoad()) { | 
|  2277     const Register temp = locs()->temp(0).reg(); |  2260     const Register temp = locs()->temp(0).reg(); | 
|  2278  |  2261  | 
|  2279     Label load_pointer; |  2262     Label load_pointer; | 
|  2280     Label load_double; |  2263     Label load_double; | 
|  2281     Label load_float32x4; |  2264     Label load_float32x4; | 
|  2282     Label load_float64x2; |  2265     Label load_float64x2; | 
|  2283  |  2266  | 
|  2284     __ LoadObject(result_reg, Field::ZoneHandle(field()->Original())); |  2267     __ LoadObject(result_reg, Field::ZoneHandle(field()->Original())); | 
|  2285  |  2268  | 
|  2286     FieldAddress field_cid_operand( |  2269     FieldAddress field_cid_operand(result_reg, Field::guarded_cid_offset(), | 
|  2287         result_reg, Field::guarded_cid_offset(), kUnsignedWord); |  2270                                    kUnsignedWord); | 
|  2288     FieldAddress field_nullability_operand( |  2271     FieldAddress field_nullability_operand( | 
|  2289         result_reg, Field::is_nullable_offset(), kUnsignedWord); |  2272         result_reg, Field::is_nullable_offset(), kUnsignedWord); | 
|  2290  |  2273  | 
|  2291     __ ldr(temp, field_nullability_operand, kUnsignedWord); |  2274     __ ldr(temp, field_nullability_operand, kUnsignedWord); | 
|  2292     __ CompareImmediate(temp, kNullCid); |  2275     __ CompareImmediate(temp, kNullCid); | 
|  2293     __ b(&load_pointer, EQ); |  2276     __ b(&load_pointer, EQ); | 
|  2294  |  2277  | 
|  2295     __ ldr(temp, field_cid_operand, kUnsignedWord); |  2278     __ ldr(temp, field_cid_operand, kUnsignedWord); | 
|  2296     __ CompareImmediate(temp, kDoubleCid); |  2279     __ CompareImmediate(temp, kDoubleCid); | 
|  2297     __ b(&load_double, EQ); |  2280     __ b(&load_double, EQ); | 
|  2298  |  2281  | 
|  2299     __ ldr(temp, field_cid_operand, kUnsignedWord); |  2282     __ ldr(temp, field_cid_operand, kUnsignedWord); | 
|  2300     __ CompareImmediate(temp, kFloat32x4Cid); |  2283     __ CompareImmediate(temp, kFloat32x4Cid); | 
|  2301     __ b(&load_float32x4, EQ); |  2284     __ b(&load_float32x4, EQ); | 
|  2302  |  2285  | 
|  2303     __ ldr(temp, field_cid_operand, kUnsignedWord); |  2286     __ ldr(temp, field_cid_operand, kUnsignedWord); | 
|  2304     __ CompareImmediate(temp, kFloat64x2Cid); |  2287     __ CompareImmediate(temp, kFloat64x2Cid); | 
|  2305     __ b(&load_float64x2, EQ); |  2288     __ b(&load_float64x2, EQ); | 
|  2306  |  2289  | 
|  2307     // Fall through. |  2290     // Fall through. | 
|  2308     __ b(&load_pointer); |  2291     __ b(&load_pointer); | 
|  2309  |  2292  | 
|  2310     if (!compiler->is_optimizing()) { |  2293     if (!compiler->is_optimizing()) { | 
|  2311       locs()->live_registers()->Add(locs()->in(0)); |  2294       locs()->live_registers()->Add(locs()->in(0)); | 
|  2312     } |  2295     } | 
|  2313  |  2296  | 
|  2314     { |  2297     { | 
|  2315       __ Bind(&load_double); |  2298       __ Bind(&load_double); | 
|  2316       BoxAllocationSlowPath::Allocate(compiler, |  2299       BoxAllocationSlowPath::Allocate(compiler, this, compiler->double_class(), | 
|  2317                                       this, |  2300                                       result_reg, temp); | 
|  2318                                       compiler->double_class(), |  | 
|  2319                                       result_reg, |  | 
|  2320                                       temp); |  | 
|  2321       __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes()); |  2301       __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes()); | 
|  2322       __ LoadDFieldFromOffset(VTMP, temp, Double::value_offset()); |  2302       __ LoadDFieldFromOffset(VTMP, temp, Double::value_offset()); | 
|  2323       __ StoreDFieldToOffset(VTMP, result_reg, Double::value_offset()); |  2303       __ StoreDFieldToOffset(VTMP, result_reg, Double::value_offset()); | 
|  2324       __ b(&done); |  2304       __ b(&done); | 
|  2325     } |  2305     } | 
|  2326  |  2306  | 
|  2327     { |  2307     { | 
|  2328       __ Bind(&load_float32x4); |  2308       __ Bind(&load_float32x4); | 
|  2329       BoxAllocationSlowPath::Allocate(compiler, |  2309       BoxAllocationSlowPath::Allocate( | 
|  2330                                       this, |  2310           compiler, this, compiler->float32x4_class(), result_reg, temp); | 
|  2331                                       compiler->float32x4_class(), |  | 
|  2332                                       result_reg, |  | 
|  2333                                       temp); |  | 
|  2334       __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes()); |  2311       __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes()); | 
|  2335       __ LoadQFieldFromOffset(VTMP, temp, Float32x4::value_offset()); |  2312       __ LoadQFieldFromOffset(VTMP, temp, Float32x4::value_offset()); | 
|  2336       __ StoreQFieldToOffset(VTMP, result_reg, Float32x4::value_offset()); |  2313       __ StoreQFieldToOffset(VTMP, result_reg, Float32x4::value_offset()); | 
|  2337       __ b(&done); |  2314       __ b(&done); | 
|  2338     } |  2315     } | 
|  2339  |  2316  | 
|  2340     { |  2317     { | 
|  2341       __ Bind(&load_float64x2); |  2318       __ Bind(&load_float64x2); | 
|  2342       BoxAllocationSlowPath::Allocate(compiler, |  2319       BoxAllocationSlowPath::Allocate( | 
|  2343                                       this, |  2320           compiler, this, compiler->float64x2_class(), result_reg, temp); | 
|  2344                                       compiler->float64x2_class(), |  | 
|  2345                                       result_reg, |  | 
|  2346                                       temp); |  | 
|  2347       __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes()); |  2321       __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes()); | 
|  2348       __ LoadQFieldFromOffset(VTMP, temp, Float64x2::value_offset()); |  2322       __ LoadQFieldFromOffset(VTMP, temp, Float64x2::value_offset()); | 
|  2349       __ StoreQFieldToOffset(VTMP, result_reg, Float64x2::value_offset()); |  2323       __ StoreQFieldToOffset(VTMP, result_reg, Float64x2::value_offset()); | 
|  2350       __ b(&done); |  2324       __ b(&done); | 
|  2351     } |  2325     } | 
|  2352  |  2326  | 
|  2353     __ Bind(&load_pointer); |  2327     __ Bind(&load_pointer); | 
|  2354   } |  2328   } | 
|  2355   __ LoadFieldFromOffset(result_reg, instance_reg, offset_in_bytes()); |  2329   __ LoadFieldFromOffset(result_reg, instance_reg, offset_in_bytes()); | 
|  2356   __ Bind(&done); |  2330   __ Bind(&done); | 
|  2357 } |  2331 } | 
|  2358  |  2332  | 
|  2359  |  2333  | 
|  2360 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone, |  2334 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone, | 
|  2361                                                            bool opt) const { |  2335                                                            bool opt) const { | 
|  2362   const intptr_t kNumInputs = 1; |  2336   const intptr_t kNumInputs = 1; | 
|  2363   const intptr_t kNumTemps = 0; |  2337   const intptr_t kNumTemps = 0; | 
|  2364   LocationSummary* locs = new(zone) LocationSummary( |  2338   LocationSummary* locs = new (zone) | 
|  2365       zone, kNumInputs, kNumTemps, LocationSummary::kCall); |  2339       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 
|  2366   locs->set_in(0, Location::RegisterLocation(R0)); |  2340   locs->set_in(0, Location::RegisterLocation(R0)); | 
|  2367   locs->set_out(0, Location::RegisterLocation(R0)); |  2341   locs->set_out(0, Location::RegisterLocation(R0)); | 
|  2368   return locs; |  2342   return locs; | 
|  2369 } |  2343 } | 
|  2370  |  2344  | 
|  2371  |  2345  | 
|  2372 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  2346 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  2373   const Register instantiator_reg = locs()->in(0).reg(); |  2347   const Register instantiator_reg = locs()->in(0).reg(); | 
|  2374   const Register result_reg = locs()->out(0).reg(); |  2348   const Register result_reg = locs()->out(0).reg(); | 
|  2375  |  2349  | 
|  2376   // 'instantiator_reg' is the instantiator TypeArguments object (or null). |  2350   // 'instantiator_reg' is the instantiator TypeArguments object (or null). | 
|  2377   // A runtime call to instantiate the type is required. |  2351   // A runtime call to instantiate the type is required. | 
|  2378   __ PushObject(Object::null_object());  // Make room for the result. |  2352   __ PushObject(Object::null_object());  // Make room for the result. | 
|  2379   __ PushObject(type()); |  2353   __ PushObject(type()); | 
|  2380   __ Push(instantiator_reg);  // Push instantiator type arguments. |  2354   __ Push(instantiator_reg);  // Push instantiator type arguments. | 
|  2381   compiler->GenerateRuntimeCall(token_pos(), |  2355   compiler->GenerateRuntimeCall(token_pos(), deopt_id(), | 
|  2382                                 deopt_id(), |  2356                                 kInstantiateTypeRuntimeEntry, 2, locs()); | 
|  2383                                 kInstantiateTypeRuntimeEntry, |  2357   __ Drop(2);          // Drop instantiator and uninstantiated type. | 
|  2384                                 2, |  | 
|  2385                                 locs()); |  | 
|  2386   __ Drop(2);  // Drop instantiator and uninstantiated type. |  | 
|  2387   __ Pop(result_reg);  // Pop instantiated type. |  2358   __ Pop(result_reg);  // Pop instantiated type. | 
|  2388   ASSERT(instantiator_reg == result_reg); |  2359   ASSERT(instantiator_reg == result_reg); | 
|  2389 } |  2360 } | 
|  2390  |  2361  | 
|  2391  |  2362  | 
|  2392 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( |  2363 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( | 
|  2393     Zone* zone, bool opt) const { |  2364     Zone* zone, | 
 |  2365     bool opt) const { | 
|  2394   const intptr_t kNumInputs = 1; |  2366   const intptr_t kNumInputs = 1; | 
|  2395   const intptr_t kNumTemps = 0; |  2367   const intptr_t kNumTemps = 0; | 
|  2396   LocationSummary* locs = new(zone) LocationSummary( |  2368   LocationSummary* locs = new (zone) | 
|  2397       zone, kNumInputs, kNumTemps, LocationSummary::kCall); |  2369       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 
|  2398   locs->set_in(0, Location::RegisterLocation(R0)); |  2370   locs->set_in(0, Location::RegisterLocation(R0)); | 
|  2399   locs->set_out(0, Location::RegisterLocation(R0)); |  2371   locs->set_out(0, Location::RegisterLocation(R0)); | 
|  2400   return locs; |  2372   return locs; | 
|  2401 } |  2373 } | 
|  2402  |  2374  | 
|  2403  |  2375  | 
|  2404 void InstantiateTypeArgumentsInstr::EmitNativeCode( |  2376 void InstantiateTypeArgumentsInstr::EmitNativeCode( | 
|  2405     FlowGraphCompiler* compiler) { |  2377     FlowGraphCompiler* compiler) { | 
|  2406   const Register instantiator_reg = locs()->in(0).reg(); |  2378   const Register instantiator_reg = locs()->in(0).reg(); | 
|  2407   const Register result_reg = locs()->out(0).reg(); |  2379   const Register result_reg = locs()->out(0).reg(); | 
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  2439   __ Bind(&found); |  2411   __ Bind(&found); | 
|  2440   __ LoadFromOffset(R0, R2, 1 * kWordSize);  // Cached instantiated args. |  2412   __ LoadFromOffset(R0, R2, 1 * kWordSize);  // Cached instantiated args. | 
|  2441   __ b(&type_arguments_instantiated); |  2413   __ b(&type_arguments_instantiated); | 
|  2442  |  2414  | 
|  2443   __ Bind(&slow_case); |  2415   __ Bind(&slow_case); | 
|  2444   // Instantiate non-null type arguments. |  2416   // Instantiate non-null type arguments. | 
|  2445   // A runtime call to instantiate the type arguments is required. |  2417   // A runtime call to instantiate the type arguments is required. | 
|  2446   __ PushObject(Object::null_object());  // Make room for the result. |  2418   __ PushObject(Object::null_object());  // Make room for the result. | 
|  2447   __ PushObject(type_arguments()); |  2419   __ PushObject(type_arguments()); | 
|  2448   __ Push(instantiator_reg);  // Push instantiator type arguments. |  2420   __ Push(instantiator_reg);  // Push instantiator type arguments. | 
|  2449   compiler->GenerateRuntimeCall(token_pos(), |  2421   compiler->GenerateRuntimeCall(token_pos(), deopt_id(), | 
|  2450                                 deopt_id(), |  2422                                 kInstantiateTypeArgumentsRuntimeEntry, 2, | 
|  2451                                 kInstantiateTypeArgumentsRuntimeEntry, |  | 
|  2452                                 2, |  | 
|  2453                                 locs()); |  2423                                 locs()); | 
|  2454   __ Drop(2);  // Drop instantiator and uninstantiated type arguments. |  2424   __ Drop(2);          // Drop instantiator and uninstantiated type arguments. | 
|  2455   __ Pop(result_reg);  // Pop instantiated type arguments. |  2425   __ Pop(result_reg);  // Pop instantiated type arguments. | 
|  2456   __ Bind(&type_arguments_instantiated); |  2426   __ Bind(&type_arguments_instantiated); | 
|  2457 } |  2427 } | 
|  2458  |  2428  | 
|  2459  |  2429  | 
|  2460 LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary( |  2430 LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary( | 
|  2461     Zone* zone, |  2431     Zone* zone, | 
|  2462     bool opt) const { |  2432     bool opt) const { | 
|  2463   ASSERT(opt); |  2433   ASSERT(opt); | 
|  2464   const intptr_t kNumInputs = 0; |  2434   const intptr_t kNumInputs = 0; | 
|  2465   const intptr_t kNumTemps = 3; |  2435   const intptr_t kNumTemps = 3; | 
|  2466   LocationSummary* locs = new(zone) LocationSummary( |  2436   LocationSummary* locs = new (zone) LocationSummary( | 
|  2467       zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |  2437       zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 
|  2468   locs->set_temp(0, Location::RegisterLocation(R1)); |  2438   locs->set_temp(0, Location::RegisterLocation(R1)); | 
|  2469   locs->set_temp(1, Location::RegisterLocation(R2)); |  2439   locs->set_temp(1, Location::RegisterLocation(R2)); | 
|  2470   locs->set_temp(2, Location::RegisterLocation(R3)); |  2440   locs->set_temp(2, Location::RegisterLocation(R3)); | 
|  2471   locs->set_out(0, Location::RegisterLocation(R0)); |  2441   locs->set_out(0, Location::RegisterLocation(R0)); | 
|  2472   return locs; |  2442   return locs; | 
|  2473 } |  2443 } | 
|  2474  |  2444  | 
|  2475  |  2445  | 
|  2476 class AllocateContextSlowPath : public SlowPathCode { |  2446 class AllocateContextSlowPath : public SlowPathCode { | 
|  2477  public: |  2447  public: | 
|  2478   explicit AllocateContextSlowPath( |  2448   explicit AllocateContextSlowPath( | 
|  2479       AllocateUninitializedContextInstr* instruction) |  2449       AllocateUninitializedContextInstr* instruction) | 
|  2480       : instruction_(instruction) { } |  2450       : instruction_(instruction) {} | 
|  2481  |  2451  | 
|  2482   virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |  2452   virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  2483     __ Comment("AllocateContextSlowPath"); |  2453     __ Comment("AllocateContextSlowPath"); | 
|  2484     __ Bind(entry_label()); |  2454     __ Bind(entry_label()); | 
|  2485  |  2455  | 
|  2486     LocationSummary* locs = instruction_->locs(); |  2456     LocationSummary* locs = instruction_->locs(); | 
|  2487     locs->live_registers()->Remove(locs->out(0)); |  2457     locs->live_registers()->Remove(locs->out(0)); | 
|  2488  |  2458  | 
|  2489     compiler->SaveLiveRegisters(locs); |  2459     compiler->SaveLiveRegisters(locs); | 
|  2490  |  2460  | 
|  2491     __ LoadImmediate(R1, instruction_->num_context_variables()); |  2461     __ LoadImmediate(R1, instruction_->num_context_variables()); | 
|  2492     const Code& stub = Code::ZoneHandle( |  2462     const Code& stub = Code::ZoneHandle( | 
|  2493         compiler->zone(), StubCode::AllocateContext_entry()->code()); |  2463         compiler->zone(), StubCode::AllocateContext_entry()->code()); | 
|  2494     compiler->AddStubCallTarget(stub); |  2464     compiler->AddStubCallTarget(stub); | 
|  2495     compiler->GenerateCall(instruction_->token_pos(), |  2465     compiler->GenerateCall(instruction_->token_pos(), | 
|  2496                            *StubCode::AllocateContext_entry(), |  2466                            *StubCode::AllocateContext_entry(), | 
|  2497                            RawPcDescriptors::kOther, |  2467                            RawPcDescriptors::kOther, locs); | 
|  2498                            locs); |  | 
|  2499     ASSERT(instruction_->locs()->out(0).reg() == R0); |  2468     ASSERT(instruction_->locs()->out(0).reg() == R0); | 
|  2500     compiler->RestoreLiveRegisters(instruction_->locs()); |  2469     compiler->RestoreLiveRegisters(instruction_->locs()); | 
|  2501     __ b(exit_label()); |  2470     __ b(exit_label()); | 
|  2502   } |  2471   } | 
|  2503  |  2472  | 
|  2504  private: |  2473  private: | 
|  2505   AllocateUninitializedContextInstr* instruction_; |  2474   AllocateUninitializedContextInstr* instruction_; | 
|  2506 }; |  2475 }; | 
|  2507  |  2476  | 
|  2508  |  2477  | 
|  2509  |  | 
|  2510 void AllocateUninitializedContextInstr::EmitNativeCode( |  2478 void AllocateUninitializedContextInstr::EmitNativeCode( | 
|  2511     FlowGraphCompiler* compiler) { |  2479     FlowGraphCompiler* compiler) { | 
|  2512   Register temp0 = locs()->temp(0).reg(); |  2480   Register temp0 = locs()->temp(0).reg(); | 
|  2513   Register temp1 = locs()->temp(1).reg(); |  2481   Register temp1 = locs()->temp(1).reg(); | 
|  2514   Register temp2 = locs()->temp(2).reg(); |  2482   Register temp2 = locs()->temp(2).reg(); | 
|  2515   Register result = locs()->out(0).reg(); |  2483   Register result = locs()->out(0).reg(); | 
|  2516   // Try allocate the object. |  2484   // Try allocate the object. | 
|  2517   AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); |  2485   AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); | 
|  2518   compiler->AddSlowPathCode(slow_path); |  2486   compiler->AddSlowPathCode(slow_path); | 
|  2519   intptr_t instance_size = Context::InstanceSize(num_context_variables()); |  2487   intptr_t instance_size = Context::InstanceSize(num_context_variables()); | 
|  2520  |  2488  | 
|  2521   __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(), |  2489   __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(), | 
|  2522                       result,  // instance |  2490                       result,  // instance | 
|  2523                       temp0, |  2491                       temp0, temp1, temp2); | 
|  2524                       temp1, |  | 
|  2525                       temp2); |  | 
|  2526  |  2492  | 
|  2527   // Setup up number of context variables field. |  2493   // Setup up number of context variables field. | 
|  2528   __ LoadImmediate(temp0, num_context_variables()); |  2494   __ LoadImmediate(temp0, num_context_variables()); | 
|  2529   __ str(temp0, FieldAddress(result, Context::num_variables_offset())); |  2495   __ str(temp0, FieldAddress(result, Context::num_variables_offset())); | 
|  2530  |  2496  | 
|  2531   __ Bind(slow_path->exit_label()); |  2497   __ Bind(slow_path->exit_label()); | 
|  2532 } |  2498 } | 
|  2533  |  2499  | 
|  2534  |  2500  | 
|  2535 LocationSummary* AllocateContextInstr::MakeLocationSummary(Zone* zone, |  2501 LocationSummary* AllocateContextInstr::MakeLocationSummary(Zone* zone, | 
|  2536                                                            bool opt) const { |  2502                                                            bool opt) const { | 
|  2537   const intptr_t kNumInputs = 0; |  2503   const intptr_t kNumInputs = 0; | 
|  2538   const intptr_t kNumTemps = 1; |  2504   const intptr_t kNumTemps = 1; | 
|  2539   LocationSummary* locs = new(zone) LocationSummary( |  2505   LocationSummary* locs = new (zone) | 
|  2540       zone, kNumInputs, kNumTemps, LocationSummary::kCall); |  2506       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 
|  2541   locs->set_temp(0, Location::RegisterLocation(R1)); |  2507   locs->set_temp(0, Location::RegisterLocation(R1)); | 
|  2542   locs->set_out(0, Location::RegisterLocation(R0)); |  2508   locs->set_out(0, Location::RegisterLocation(R0)); | 
|  2543   return locs; |  2509   return locs; | 
|  2544 } |  2510 } | 
|  2545  |  2511  | 
|  2546  |  2512  | 
|  2547 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  2513 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  2548   ASSERT(locs()->temp(0).reg() == R1); |  2514   ASSERT(locs()->temp(0).reg() == R1); | 
|  2549   ASSERT(locs()->out(0).reg() == R0); |  2515   ASSERT(locs()->out(0).reg() == R0); | 
|  2550  |  2516  | 
|  2551   __ LoadImmediate(R1, num_context_variables()); |  2517   __ LoadImmediate(R1, num_context_variables()); | 
|  2552   compiler->GenerateCall(token_pos(), |  2518   compiler->GenerateCall(token_pos(), *StubCode::AllocateContext_entry(), | 
|  2553                          *StubCode::AllocateContext_entry(), |  2519                          RawPcDescriptors::kOther, locs()); | 
|  2554                          RawPcDescriptors::kOther, |  | 
|  2555                          locs()); |  | 
|  2556 } |  2520 } | 
|  2557  |  2521  | 
|  2558 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone, |  2522 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone, | 
|  2559                                                            bool opt) const { |  2523                                                            bool opt) const { | 
|  2560   const intptr_t kNumInputs = 1; |  2524   const intptr_t kNumInputs = 1; | 
|  2561   const intptr_t kNumTemps = 1; |  2525   const intptr_t kNumTemps = 1; | 
|  2562   LocationSummary* locs = new(zone) LocationSummary( |  2526   LocationSummary* locs = new (zone) | 
|  2563       zone, kNumInputs, kNumTemps, LocationSummary::kCall); |  2527       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 
|  2564   locs->set_in(0, Location::RegisterLocation(R0)); |  2528   locs->set_in(0, Location::RegisterLocation(R0)); | 
|  2565   locs->set_temp(0, Location::RegisterLocation(R1)); |  2529   locs->set_temp(0, Location::RegisterLocation(R1)); | 
|  2566   return locs; |  2530   return locs; | 
|  2567 } |  2531 } | 
|  2568  |  2532  | 
|  2569  |  2533  | 
|  2570 void InitStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  2534 void InitStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  2571   Register field = locs()->in(0).reg(); |  2535   Register field = locs()->in(0).reg(); | 
|  2572   Register temp = locs()->temp(0).reg(); |  2536   Register temp = locs()->temp(0).reg(); | 
|  2573   Label call_runtime, no_call; |  2537   Label call_runtime, no_call; | 
|  2574  |  2538  | 
|  2575   __ ldr(temp, FieldAddress(field, Field::static_value_offset())); |  2539   __ ldr(temp, FieldAddress(field, Field::static_value_offset())); | 
|  2576   __ CompareObject(temp, Object::sentinel()); |  2540   __ CompareObject(temp, Object::sentinel()); | 
|  2577   __ b(&call_runtime, EQ); |  2541   __ b(&call_runtime, EQ); | 
|  2578  |  2542  | 
|  2579   __ CompareObject(temp, Object::transition_sentinel()); |  2543   __ CompareObject(temp, Object::transition_sentinel()); | 
|  2580   __ b(&no_call, NE); |  2544   __ b(&no_call, NE); | 
|  2581  |  2545  | 
|  2582   __ Bind(&call_runtime); |  2546   __ Bind(&call_runtime); | 
|  2583   __ PushObject(Object::null_object());  // Make room for (unused) result. |  2547   __ PushObject(Object::null_object());  // Make room for (unused) result. | 
|  2584   __ Push(field); |  2548   __ Push(field); | 
|  2585   compiler->GenerateRuntimeCall(token_pos(), |  2549   compiler->GenerateRuntimeCall(token_pos(), deopt_id(), | 
|  2586                                 deopt_id(), |  2550                                 kInitStaticFieldRuntimeEntry, 1, locs()); | 
|  2587                                 kInitStaticFieldRuntimeEntry, |  | 
|  2588                                 1, |  | 
|  2589                                 locs()); |  | 
|  2590   __ Drop(2);  // Remove argument and result placeholder. |  2551   __ Drop(2);  // Remove argument and result placeholder. | 
|  2591   __ Bind(&no_call); |  2552   __ Bind(&no_call); | 
|  2592 } |  2553 } | 
|  2593  |  2554  | 
|  2594  |  2555  | 
|  2595 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone, |  2556 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone, | 
|  2596                                                         bool opt) const { |  2557                                                         bool opt) const { | 
|  2597   const intptr_t kNumInputs = 1; |  2558   const intptr_t kNumInputs = 1; | 
|  2598   const intptr_t kNumTemps = 0; |  2559   const intptr_t kNumTemps = 0; | 
|  2599   LocationSummary* locs = new(zone) LocationSummary( |  2560   LocationSummary* locs = new (zone) | 
|  2600       zone, kNumInputs, kNumTemps, LocationSummary::kCall); |  2561       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 
|  2601   locs->set_in(0, Location::RegisterLocation(R0)); |  2562   locs->set_in(0, Location::RegisterLocation(R0)); | 
|  2602   locs->set_out(0, Location::RegisterLocation(R0)); |  2563   locs->set_out(0, Location::RegisterLocation(R0)); | 
|  2603   return locs; |  2564   return locs; | 
|  2604 } |  2565 } | 
|  2605  |  2566  | 
|  2606  |  2567  | 
|  2607 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  2568 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  2608   const Register context_value = locs()->in(0).reg(); |  2569   const Register context_value = locs()->in(0).reg(); | 
|  2609   const Register result = locs()->out(0).reg(); |  2570   const Register result = locs()->out(0).reg(); | 
|  2610  |  2571  | 
|  2611   __ PushObject(Object::null_object());  // Make room for the result. |  2572   __ PushObject(Object::null_object());  // Make room for the result. | 
|  2612   __ Push(context_value); |  2573   __ Push(context_value); | 
|  2613   compiler->GenerateRuntimeCall(token_pos(), |  2574   compiler->GenerateRuntimeCall(token_pos(), deopt_id(), | 
|  2614                                 deopt_id(), |  2575                                 kCloneContextRuntimeEntry, 1, locs()); | 
|  2615                                 kCloneContextRuntimeEntry, |  2576   __ Drop(1);      // Remove argument. | 
|  2616                                 1, |  | 
|  2617                                 locs()); |  | 
|  2618   __ Drop(1);  // Remove argument. |  | 
|  2619   __ Pop(result);  // Get result (cloned context). |  2577   __ Pop(result);  // Get result (cloned context). | 
|  2620 } |  2578 } | 
|  2621  |  2579  | 
|  2622  |  2580  | 
|  2623 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone, |  2581 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone, | 
|  2624                                                            bool opt) const { |  2582                                                            bool opt) const { | 
|  2625   UNREACHABLE(); |  2583   UNREACHABLE(); | 
|  2626   return NULL; |  2584   return NULL; | 
|  2627 } |  2585 } | 
|  2628  |  2586  | 
|  2629  |  2587  | 
|  2630 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  2588 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  2631   __ Bind(compiler->GetJumpLabel(this)); |  2589   __ Bind(compiler->GetJumpLabel(this)); | 
|  2632   compiler->AddExceptionHandler(catch_try_index(), |  2590   compiler->AddExceptionHandler(catch_try_index(), try_index(), | 
|  2633                                 try_index(), |  | 
|  2634                                 compiler->assembler()->CodeSize(), |  2591                                 compiler->assembler()->CodeSize(), | 
|  2635                                 catch_handler_types_, |  2592                                 catch_handler_types_, needs_stacktrace()); | 
|  2636                                 needs_stacktrace()); |  | 
|  2637   // On lazy deoptimization we patch the optimized code here to enter the |  2593   // On lazy deoptimization we patch the optimized code here to enter the | 
|  2638   // deoptimization stub. |  2594   // deoptimization stub. | 
|  2639   const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId()); |  2595   const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId()); | 
|  2640   if (compiler->is_optimizing()) { |  2596   if (compiler->is_optimizing()) { | 
|  2641     compiler->AddDeoptIndexAtCall(deopt_id); |  2597     compiler->AddDeoptIndexAtCall(deopt_id); | 
|  2642   } else { |  2598   } else { | 
|  2643     compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, |  2599     compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id, | 
|  2644                                    deopt_id, |  | 
|  2645                                    TokenPosition::kNoSource); |  2600                                    TokenPosition::kNoSource); | 
|  2646   } |  2601   } | 
|  2647   if (HasParallelMove()) { |  2602   if (HasParallelMove()) { | 
|  2648     compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |  2603     compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 
|  2649   } |  2604   } | 
|  2650  |  2605  | 
|  2651   // Restore SP from FP as we are coming from a throw and the code for |  2606   // Restore SP from FP as we are coming from a throw and the code for | 
|  2652   // popping arguments has not been run. |  2607   // popping arguments has not been run. | 
|  2653   const intptr_t fp_sp_dist = |  2608   const intptr_t fp_sp_dist = | 
|  2654       (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; |  2609       (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; | 
|  2655   ASSERT(fp_sp_dist <= 0); |  2610   ASSERT(fp_sp_dist <= 0); | 
|  2656   __ AddImmediate(SP, FP, fp_sp_dist); |  2611   __ AddImmediate(SP, FP, fp_sp_dist); | 
|  2657  |  2612  | 
|  2658   // Restore stack and initialize the two exception variables: |  2613   // Restore stack and initialize the two exception variables: | 
|  2659   // exception and stack trace variables. |  2614   // exception and stack trace variables. | 
|  2660   __ StoreToOffset(kExceptionObjectReg, |  2615   __ StoreToOffset(kExceptionObjectReg, FP, | 
|  2661                    FP, exception_var().index() * kWordSize); |  2616                    exception_var().index() * kWordSize); | 
|  2662   __ StoreToOffset(kStackTraceObjectReg, |  2617   __ StoreToOffset(kStackTraceObjectReg, FP, | 
|  2663                    FP, stacktrace_var().index() * kWordSize); |  2618                    stacktrace_var().index() * kWordSize); | 
|  2664 } |  2619 } | 
|  2665  |  2620  | 
|  2666  |  2621  | 
|  2667 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Zone* zone, |  2622 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Zone* zone, | 
|  2668                                                               bool opt) const { |  2623                                                               bool opt) const { | 
|  2669   const intptr_t kNumInputs = 0; |  2624   const intptr_t kNumInputs = 0; | 
|  2670   const intptr_t kNumTemps = 1; |  2625   const intptr_t kNumTemps = 1; | 
|  2671   LocationSummary* summary = new(zone) LocationSummary( |  2626   LocationSummary* summary = new (zone) LocationSummary( | 
|  2672       zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |  2627       zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 
|  2673   summary->set_temp(0, Location::RequiresRegister()); |  2628   summary->set_temp(0, Location::RequiresRegister()); | 
|  2674   return summary; |  2629   return summary; | 
|  2675 } |  2630 } | 
|  2676  |  2631  | 
|  2677  |  2632  | 
|  2678 class CheckStackOverflowSlowPath : public SlowPathCode { |  2633 class CheckStackOverflowSlowPath : public SlowPathCode { | 
|  2679  public: |  2634  public: | 
|  2680   explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) |  2635   explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) | 
|  2681       : instruction_(instruction) { } |  2636       : instruction_(instruction) {} | 
|  2682  |  2637  | 
|  2683   virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |  2638   virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  2684     if (FLAG_use_osr && osr_entry_label()->IsLinked()) { |  2639     if (FLAG_use_osr && osr_entry_label()->IsLinked()) { | 
|  2685       const Register value = instruction_->locs()->temp(0).reg(); |  2640       const Register value = instruction_->locs()->temp(0).reg(); | 
|  2686       __ Comment("CheckStackOverflowSlowPathOsr"); |  2641       __ Comment("CheckStackOverflowSlowPathOsr"); | 
|  2687       __ Bind(osr_entry_label()); |  2642       __ Bind(osr_entry_label()); | 
|  2688       __ LoadImmediate(value, Thread::kOsrRequest); |  2643       __ LoadImmediate(value, Thread::kOsrRequest); | 
|  2689       __ str(value, Address(THR, Thread::stack_overflow_flags_offset())); |  2644       __ str(value, Address(THR, Thread::stack_overflow_flags_offset())); | 
|  2690     } |  2645     } | 
|  2691     __ Comment("CheckStackOverflowSlowPath"); |  2646     __ Comment("CheckStackOverflowSlowPath"); | 
|  2692     __ Bind(entry_label()); |  2647     __ Bind(entry_label()); | 
|  2693     compiler->SaveLiveRegisters(instruction_->locs()); |  2648     compiler->SaveLiveRegisters(instruction_->locs()); | 
|  2694     // pending_deoptimization_env_ is needed to generate a runtime call that |  2649     // pending_deoptimization_env_ is needed to generate a runtime call that | 
|  2695     // may throw an exception. |  2650     // may throw an exception. | 
|  2696     ASSERT(compiler->pending_deoptimization_env_ == NULL); |  2651     ASSERT(compiler->pending_deoptimization_env_ == NULL); | 
|  2697     Environment* env = compiler->SlowPathEnvironmentFor(instruction_); |  2652     Environment* env = compiler->SlowPathEnvironmentFor(instruction_); | 
|  2698     compiler->pending_deoptimization_env_ = env; |  2653     compiler->pending_deoptimization_env_ = env; | 
|  2699     compiler->GenerateRuntimeCall(instruction_->token_pos(), |  2654     compiler->GenerateRuntimeCall( | 
|  2700                                   instruction_->deopt_id(), |  2655         instruction_->token_pos(), instruction_->deopt_id(), | 
|  2701                                   kStackOverflowRuntimeEntry, |  2656         kStackOverflowRuntimeEntry, 0, instruction_->locs()); | 
|  2702                                   0, |  | 
|  2703                                   instruction_->locs()); |  | 
|  2704  |  2657  | 
|  2705     if (FLAG_use_osr && !compiler->is_optimizing() && instruction_->in_loop()) { |  2658     if (FLAG_use_osr && !compiler->is_optimizing() && instruction_->in_loop()) { | 
|  2706       // In unoptimized code, record loop stack checks as possible OSR entries. |  2659       // In unoptimized code, record loop stack checks as possible OSR entries. | 
|  2707       compiler->AddCurrentDescriptor(RawPcDescriptors::kOsrEntry, |  2660       compiler->AddCurrentDescriptor(RawPcDescriptors::kOsrEntry, | 
|  2708                                      instruction_->deopt_id(), |  2661                                      instruction_->deopt_id(), | 
|  2709                                      TokenPosition::kNoSource); |  2662                                      TokenPosition::kNoSource); | 
|  2710     } |  2663     } | 
|  2711     compiler->pending_deoptimization_env_ = NULL; |  2664     compiler->pending_deoptimization_env_ = NULL; | 
|  2712     compiler->RestoreLiveRegisters(instruction_->locs()); |  2665     compiler->RestoreLiveRegisters(instruction_->locs()); | 
|  2713     __ b(exit_label()); |  2666     __ b(exit_label()); | 
| (...skipping 20 matching lines...) Expand all  Loading... | 
|  2734   __ CompareRegisters(CSP, TMP); |  2687   __ CompareRegisters(CSP, TMP); | 
|  2735   __ b(slow_path->entry_label(), LS); |  2688   __ b(slow_path->entry_label(), LS); | 
|  2736   if (compiler->CanOSRFunction() && in_loop()) { |  2689   if (compiler->CanOSRFunction() && in_loop()) { | 
|  2737     const Register temp = locs()->temp(0).reg(); |  2690     const Register temp = locs()->temp(0).reg(); | 
|  2738     // In unoptimized code check the usage counter to trigger OSR at loop |  2691     // In unoptimized code check the usage counter to trigger OSR at loop | 
|  2739     // stack checks.  Use progressively higher thresholds for more deeply |  2692     // stack checks.  Use progressively higher thresholds for more deeply | 
|  2740     // nested loops to attempt to hit outer loops with OSR when possible. |  2693     // nested loops to attempt to hit outer loops with OSR when possible. | 
|  2741     __ LoadObject(temp, compiler->parsed_function().function()); |  2694     __ LoadObject(temp, compiler->parsed_function().function()); | 
|  2742     intptr_t threshold = |  2695     intptr_t threshold = | 
|  2743         FLAG_optimization_counter_threshold * (loop_depth() + 1); |  2696         FLAG_optimization_counter_threshold * (loop_depth() + 1); | 
|  2744     __ LoadFieldFromOffset( |  2697     __ LoadFieldFromOffset(temp, temp, Function::usage_counter_offset(), kWord); | 
|  2745         temp, temp, Function::usage_counter_offset(), kWord); |  | 
|  2746     __ CompareImmediate(temp, threshold); |  2698     __ CompareImmediate(temp, threshold); | 
|  2747     __ b(slow_path->osr_entry_label(), GE); |  2699     __ b(slow_path->osr_entry_label(), GE); | 
|  2748   } |  2700   } | 
|  2749   if (compiler->ForceSlowPathForStackOverflow()) { |  2701   if (compiler->ForceSlowPathForStackOverflow()) { | 
|  2750     __ b(slow_path->entry_label()); |  2702     __ b(slow_path->entry_label()); | 
|  2751   } |  2703   } | 
|  2752   __ Bind(slow_path->exit_label()); |  2704   __ Bind(slow_path->exit_label()); | 
|  2753 } |  2705 } | 
|  2754  |  2706  | 
|  2755  |  2707  | 
|  2756 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, |  2708 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, | 
|  2757                              BinarySmiOpInstr* shift_left) { |  2709                              BinarySmiOpInstr* shift_left) { | 
|  2758   const LocationSummary& locs = *shift_left->locs(); |  2710   const LocationSummary& locs = *shift_left->locs(); | 
|  2759   const Register left = locs.in(0).reg(); |  2711   const Register left = locs.in(0).reg(); | 
|  2760   const Register result = locs.out(0).reg(); |  2712   const Register result = locs.out(0).reg(); | 
|  2761   Label* deopt = shift_left->CanDeoptimize() ? |  2713   Label* deopt = shift_left->CanDeoptimize() | 
|  2762       compiler->AddDeoptStub(shift_left->deopt_id(), ICData::kDeoptBinarySmiOp) |  2714                      ? compiler->AddDeoptStub(shift_left->deopt_id(), | 
|  2763       : NULL; |  2715                                               ICData::kDeoptBinarySmiOp) | 
 |  2716                      : NULL; | 
|  2764   if (locs.in(1).IsConstant()) { |  2717   if (locs.in(1).IsConstant()) { | 
|  2765     const Object& constant = locs.in(1).constant(); |  2718     const Object& constant = locs.in(1).constant(); | 
|  2766     ASSERT(constant.IsSmi()); |  2719     ASSERT(constant.IsSmi()); | 
|  2767     // Immediate shift operation takes 6 bits for the count. |  2720     // Immediate shift operation takes 6 bits for the count. | 
|  2768     const intptr_t kCountLimit = 0x3F; |  2721     const intptr_t kCountLimit = 0x3F; | 
|  2769     const intptr_t value = Smi::Cast(constant).Value(); |  2722     const intptr_t value = Smi::Cast(constant).Value(); | 
|  2770     ASSERT((0 < value) && (value < kCountLimit)); |  2723     ASSERT((0 < value) && (value < kCountLimit)); | 
|  2771     if (shift_left->can_overflow()) { |  2724     if (shift_left->can_overflow()) { | 
|  2772       // Check for overflow (preserve left). |  2725       // Check for overflow (preserve left). | 
|  2773       __ LslImmediate(TMP, left, value); |  2726       __ LslImmediate(TMP, left, value); | 
| (...skipping 18 matching lines...) Expand all  Loading... | 
|  2792         __ CompareRegisters(right, ZR); |  2745         __ CompareRegisters(right, ZR); | 
|  2793         __ b(deopt, MI); |  2746         __ b(deopt, MI); | 
|  2794         __ mov(result, ZR); |  2747         __ mov(result, ZR); | 
|  2795         return; |  2748         return; | 
|  2796       } |  2749       } | 
|  2797       const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int); |  2750       const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int); | 
|  2798       const bool right_needs_check = |  2751       const bool right_needs_check = | 
|  2799           !RangeUtils::IsWithin(right_range, 0, max_right - 1); |  2752           !RangeUtils::IsWithin(right_range, 0, max_right - 1); | 
|  2800       if (right_needs_check) { |  2753       if (right_needs_check) { | 
|  2801         __ CompareImmediate(right, |  2754         __ CompareImmediate(right, | 
|  2802             reinterpret_cast<int64_t>(Smi::New(max_right))); |  2755                             reinterpret_cast<int64_t>(Smi::New(max_right))); | 
|  2803         __ b(deopt, CS); |  2756         __ b(deopt, CS); | 
|  2804       } |  2757       } | 
|  2805       __ SmiUntag(TMP, right); |  2758       __ SmiUntag(TMP, right); | 
|  2806       __ lslv(result, left, TMP); |  2759       __ lslv(result, left, TMP); | 
|  2807     } |  2760     } | 
|  2808     return; |  2761     return; | 
|  2809   } |  2762   } | 
|  2810  |  2763  | 
|  2811   const bool right_needs_check = |  2764   const bool right_needs_check = | 
|  2812       !RangeUtils::IsWithin(right_range, 0, (Smi::kBits - 1)); |  2765       !RangeUtils::IsWithin(right_range, 0, (Smi::kBits - 1)); | 
|  2813   if (!shift_left->can_overflow()) { |  2766   if (!shift_left->can_overflow()) { | 
|  2814     if (right_needs_check) { |  2767     if (right_needs_check) { | 
|  2815       const bool right_may_be_negative = |  2768       const bool right_may_be_negative = | 
|  2816           (right_range == NULL) || !right_range->IsPositive(); |  2769           (right_range == NULL) || !right_range->IsPositive(); | 
|  2817       if (right_may_be_negative) { |  2770       if (right_may_be_negative) { | 
|  2818         ASSERT(shift_left->CanDeoptimize()); |  2771         ASSERT(shift_left->CanDeoptimize()); | 
|  2819         __ CompareRegisters(right, ZR); |  2772         __ CompareRegisters(right, ZR); | 
|  2820         __ b(deopt, MI); |  2773         __ b(deopt, MI); | 
|  2821       } |  2774       } | 
|  2822  |  2775  | 
|  2823       __ CompareImmediate( |  2776       __ CompareImmediate(right, | 
|  2824           right, reinterpret_cast<int64_t>(Smi::New(Smi::kBits))); |  2777                           reinterpret_cast<int64_t>(Smi::New(Smi::kBits))); | 
|  2825       __ csel(result, ZR, result, CS); |  2778       __ csel(result, ZR, result, CS); | 
|  2826       __ SmiUntag(TMP, right); |  2779       __ SmiUntag(TMP, right); | 
|  2827       __ lslv(TMP, left, TMP); |  2780       __ lslv(TMP, left, TMP); | 
|  2828       __ csel(result, TMP, result, CC); |  2781       __ csel(result, TMP, result, CC); | 
|  2829     } else { |  2782     } else { | 
|  2830       __ SmiUntag(TMP, right); |  2783       __ SmiUntag(TMP, right); | 
|  2831       __ lslv(result, left, TMP); |  2784       __ lslv(result, left, TMP); | 
|  2832     } |  2785     } | 
|  2833   } else { |  2786   } else { | 
|  2834     if (right_needs_check) { |  2787     if (right_needs_check) { | 
|  2835       ASSERT(shift_left->CanDeoptimize()); |  2788       ASSERT(shift_left->CanDeoptimize()); | 
|  2836       __ CompareImmediate( |  2789       __ CompareImmediate(right, | 
|  2837           right, reinterpret_cast<int64_t>(Smi::New(Smi::kBits))); |  2790                           reinterpret_cast<int64_t>(Smi::New(Smi::kBits))); | 
|  2838       __ b(deopt, CS); |  2791       __ b(deopt, CS); | 
|  2839     } |  2792     } | 
|  2840     // Left is not a constant. |  2793     // Left is not a constant. | 
|  2841     // Check if count too large for handling it inlined. |  2794     // Check if count too large for handling it inlined. | 
|  2842     __ SmiUntag(TMP, right); |  2795     __ SmiUntag(TMP, right); | 
|  2843     // Overflow test (preserve left, right, and TMP); |  2796     // Overflow test (preserve left, right, and TMP); | 
|  2844     const Register temp = locs.temp(0).reg(); |  2797     const Register temp = locs.temp(0).reg(); | 
|  2845     __ lslv(temp, left, TMP); |  2798     __ lslv(temp, left, TMP); | 
|  2846     __ asrv(TMP2, temp, TMP); |  2799     __ asrv(TMP2, temp, TMP); | 
|  2847     __ CompareRegisters(left, TMP2); |  2800     __ CompareRegisters(left, TMP2); | 
|  2848     __ b(deopt, NE);  // Overflow. |  2801     __ b(deopt, NE);  // Overflow. | 
|  2849     // Shift for result now we know there is no overflow. |  2802     // Shift for result now we know there is no overflow. | 
|  2850     __ lslv(result, left, TMP); |  2803     __ lslv(result, left, TMP); | 
|  2851   } |  2804   } | 
|  2852 } |  2805 } | 
|  2853  |  2806  | 
|  2854  |  2807  | 
|  2855 class CheckedSmiSlowPath : public SlowPathCode { |  2808 class CheckedSmiSlowPath : public SlowPathCode { | 
|  2856  public: |  2809  public: | 
|  2857   CheckedSmiSlowPath(CheckedSmiOpInstr* instruction, intptr_t try_index) |  2810   CheckedSmiSlowPath(CheckedSmiOpInstr* instruction, intptr_t try_index) | 
|  2858       : instruction_(instruction), try_index_(try_index) { } |  2811       : instruction_(instruction), try_index_(try_index) {} | 
|  2859  |  2812  | 
|  2860   virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |  2813   virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  2861     if (Assembler::EmittingComments()) { |  2814     if (Assembler::EmittingComments()) { | 
|  2862       __ Comment("slow path smi operation"); |  2815       __ Comment("slow path smi operation"); | 
|  2863     } |  2816     } | 
|  2864     __ Bind(entry_label()); |  2817     __ Bind(entry_label()); | 
|  2865     LocationSummary* locs = instruction_->locs(); |  2818     LocationSummary* locs = instruction_->locs(); | 
|  2866     Register result = locs->out(0).reg(); |  2819     Register result = locs->out(0).reg(); | 
|  2867     locs->live_registers()->Remove(Location::RegisterLocation(result)); |  2820     locs->live_registers()->Remove(Location::RegisterLocation(result)); | 
|  2868  |  2821  | 
|  2869     compiler->SaveLiveRegisters(locs); |  2822     compiler->SaveLiveRegisters(locs); | 
|  2870     __ Push(locs->in(0).reg()); |  2823     __ Push(locs->in(0).reg()); | 
|  2871     __ Push(locs->in(1).reg()); |  2824     __ Push(locs->in(1).reg()); | 
|  2872     compiler->EmitMegamorphicInstanceCall( |  2825     compiler->EmitMegamorphicInstanceCall( | 
|  2873         *instruction_->call()->ic_data(), |  2826         *instruction_->call()->ic_data(), instruction_->call()->ArgumentCount(), | 
|  2874         instruction_->call()->ArgumentCount(), |  2827         instruction_->call()->deopt_id(), instruction_->call()->token_pos(), | 
|  2875         instruction_->call()->deopt_id(), |  2828         locs, try_index_, | 
|  2876         instruction_->call()->token_pos(), |  | 
|  2877         locs, |  | 
|  2878         try_index_, |  | 
|  2879         /* slow_path_argument_count = */ 2); |  2829         /* slow_path_argument_count = */ 2); | 
|  2880     __ mov(result, R0); |  2830     __ mov(result, R0); | 
|  2881     compiler->RestoreLiveRegisters(locs); |  2831     compiler->RestoreLiveRegisters(locs); | 
|  2882     __ b(exit_label()); |  2832     __ b(exit_label()); | 
|  2883   } |  2833   } | 
|  2884  |  2834  | 
|  2885  private: |  2835  private: | 
|  2886   CheckedSmiOpInstr* instruction_; |  2836   CheckedSmiOpInstr* instruction_; | 
|  2887   intptr_t try_index_; |  2837   intptr_t try_index_; | 
|  2888 }; |  2838 }; | 
|  2889  |  2839  | 
|  2890  |  2840  | 
|  2891 LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, |  2841 LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, | 
|  2892                                                         bool opt) const { |  2842                                                         bool opt) const { | 
|  2893   const intptr_t kNumInputs = 2; |  2843   const intptr_t kNumInputs = 2; | 
|  2894   const intptr_t kNumTemps = 0; |  2844   const intptr_t kNumTemps = 0; | 
|  2895   LocationSummary* summary = new(zone) LocationSummary( |  2845   LocationSummary* summary = new (zone) LocationSummary( | 
|  2896       zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |  2846       zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 
|  2897   summary->set_in(0, Location::RequiresRegister()); |  2847   summary->set_in(0, Location::RequiresRegister()); | 
|  2898   summary->set_in(1, Location::RequiresRegister()); |  2848   summary->set_in(1, Location::RequiresRegister()); | 
|  2899   summary->set_out(0, Location::RequiresRegister()); |  2849   summary->set_out(0, Location::RequiresRegister()); | 
|  2900   return summary; |  2850   return summary; | 
|  2901 } |  2851 } | 
|  2902  |  2852  | 
|  2903  |  2853  | 
|  2904 void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  2854 void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  2905   CheckedSmiSlowPath* slow_path = |  2855   CheckedSmiSlowPath* slow_path = | 
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  2963  |  2913  | 
|  2964 class CheckedSmiComparisonSlowPath : public SlowPathCode { |  2914 class CheckedSmiComparisonSlowPath : public SlowPathCode { | 
|  2965  public: |  2915  public: | 
|  2966   CheckedSmiComparisonSlowPath(CheckedSmiComparisonInstr* instruction, |  2916   CheckedSmiComparisonSlowPath(CheckedSmiComparisonInstr* instruction, | 
|  2967                                intptr_t try_index, |  2917                                intptr_t try_index, | 
|  2968                                BranchLabels labels, |  2918                                BranchLabels labels, | 
|  2969                                bool merged) |  2919                                bool merged) | 
|  2970       : instruction_(instruction), |  2920       : instruction_(instruction), | 
|  2971         try_index_(try_index), |  2921         try_index_(try_index), | 
|  2972         labels_(labels), |  2922         labels_(labels), | 
|  2973         merged_(merged) { } |  2923         merged_(merged) {} | 
|  2974  |  2924  | 
|  2975   virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |  2925   virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  2976     if (Assembler::EmittingComments()) { |  2926     if (Assembler::EmittingComments()) { | 
|  2977       __ Comment("slow path smi operation"); |  2927       __ Comment("slow path smi operation"); | 
|  2978     } |  2928     } | 
|  2979     __ Bind(entry_label()); |  2929     __ Bind(entry_label()); | 
|  2980     LocationSummary* locs = instruction_->locs(); |  2930     LocationSummary* locs = instruction_->locs(); | 
|  2981     Register result = merged_ ? locs->temp(0).reg() : locs->out(0).reg(); |  2931     Register result = merged_ ? locs->temp(0).reg() : locs->out(0).reg(); | 
|  2982     locs->live_registers()->Remove(Location::RegisterLocation(result)); |  2932     locs->live_registers()->Remove(Location::RegisterLocation(result)); | 
|  2983  |  2933  | 
|  2984     compiler->SaveLiveRegisters(locs); |  2934     compiler->SaveLiveRegisters(locs); | 
|  2985     __ Push(locs->in(0).reg()); |  2935     __ Push(locs->in(0).reg()); | 
|  2986     __ Push(locs->in(1).reg()); |  2936     __ Push(locs->in(1).reg()); | 
|  2987     compiler->EmitMegamorphicInstanceCall( |  2937     compiler->EmitMegamorphicInstanceCall( | 
|  2988         *instruction_->call()->ic_data(), |  2938         *instruction_->call()->ic_data(), instruction_->call()->ArgumentCount(), | 
|  2989         instruction_->call()->ArgumentCount(), |  2939         instruction_->call()->deopt_id(), instruction_->call()->token_pos(), | 
|  2990         instruction_->call()->deopt_id(), |  2940         locs, try_index_, | 
|  2991         instruction_->call()->token_pos(), |  | 
|  2992         locs, |  | 
|  2993         try_index_, |  | 
|  2994         /* slow_path_argument_count = */ 2); |  2941         /* slow_path_argument_count = */ 2); | 
|  2995     __ mov(result, R0); |  2942     __ mov(result, R0); | 
|  2996     compiler->RestoreLiveRegisters(locs); |  2943     compiler->RestoreLiveRegisters(locs); | 
|  2997     if (merged_) { |  2944     if (merged_) { | 
|  2998       __ CompareObject(result, Bool::True()); |  2945       __ CompareObject(result, Bool::True()); | 
|  2999       __ b(instruction_->is_negated() |  2946       __ b( | 
|  3000            ? labels_.false_label : labels_.true_label, EQ); |  2947           instruction_->is_negated() ? labels_.false_label : labels_.true_label, | 
|  3001       __ b(instruction_->is_negated() |  2948           EQ); | 
|  3002            ? labels_.true_label : labels_.false_label); |  2949       __ b(instruction_->is_negated() ? labels_.true_label | 
 |  2950                                       : labels_.false_label); | 
|  3003     } else { |  2951     } else { | 
|  3004       __ b(exit_label()); |  2952       __ b(exit_label()); | 
|  3005     } |  2953     } | 
|  3006   } |  2954   } | 
|  3007  |  2955  | 
|  3008  private: |  2956  private: | 
|  3009   CheckedSmiComparisonInstr* instruction_; |  2957   CheckedSmiComparisonInstr* instruction_; | 
|  3010   intptr_t try_index_; |  2958   intptr_t try_index_; | 
|  3011   BranchLabels labels_; |  2959   BranchLabels labels_; | 
|  3012   bool merged_; |  2960   bool merged_; | 
|  3013 }; |  2961 }; | 
|  3014  |  2962  | 
|  3015  |  2963  | 
|  3016 LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary( |  2964 LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary( | 
|  3017     Zone* zone, bool opt) const { |  2965     Zone* zone, | 
 |  2966     bool opt) const { | 
|  3018   const intptr_t kNumInputs = 2; |  2967   const intptr_t kNumInputs = 2; | 
|  3019   const intptr_t kNumTemps = 1; |  2968   const intptr_t kNumTemps = 1; | 
|  3020   LocationSummary* summary = new(zone) LocationSummary( |  2969   LocationSummary* summary = new (zone) LocationSummary( | 
|  3021       zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |  2970       zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 
|  3022   summary->set_in(0, Location::RequiresRegister()); |  2971   summary->set_in(0, Location::RequiresRegister()); | 
|  3023   summary->set_in(1, Location::RequiresRegister()); |  2972   summary->set_in(1, Location::RequiresRegister()); | 
|  3024   summary->set_temp(0, Location::RequiresRegister()); |  2973   summary->set_temp(0, Location::RequiresRegister()); | 
|  3025   summary->set_out(0, Location::RequiresRegister()); |  2974   summary->set_out(0, Location::RequiresRegister()); | 
|  3026   return summary; |  2975   return summary; | 
|  3027 } |  2976 } | 
|  3028  |  2977  | 
|  3029  |  2978  | 
|  3030 Condition CheckedSmiComparisonInstr::EmitComparisonCode( |  2979 Condition CheckedSmiComparisonInstr::EmitComparisonCode( | 
|  3031     FlowGraphCompiler* compiler, BranchLabels labels) { |  2980     FlowGraphCompiler* compiler, | 
 |  2981     BranchLabels labels) { | 
|  3032   return EmitSmiComparisonOp(compiler, locs(), kind()); |  2982   return EmitSmiComparisonOp(compiler, locs(), kind()); | 
|  3033 } |  2983 } | 
|  3034  |  2984  | 
|  3035  |  2985  | 
|  3036 #define EMIT_SMI_CHECK                                                         \ |  2986 #define EMIT_SMI_CHECK                                                         \ | 
|  3037   Register left = locs()->in(0).reg();                                         \ |  2987   Register left = locs()->in(0).reg();                                         \ | 
|  3038   Register right = locs()->in(1).reg();                                        \ |  2988   Register right = locs()->in(1).reg();                                        \ | 
|  3039   Register temp = locs()->temp(0).reg();                                       \ |  2989   Register temp = locs()->temp(0).reg();                                       \ | 
|  3040   intptr_t left_cid = this->left()->Type()->ToCid();                           \ |  2990   intptr_t left_cid = this->left()->Type()->ToCid();                           \ | 
|  3041   intptr_t right_cid = this->right()->Type()->ToCid();                         \ |  2991   intptr_t right_cid = this->right()->Type()->ToCid();                         \ | 
|  3042   if (this->left()->definition() == this->right()->definition()) {             \ |  2992   if (this->left()->definition() == this->right()->definition()) {             \ | 
|  3043     __ tsti(left, Immediate(kSmiTagMask));                                     \ |  2993     __ tsti(left, Immediate(kSmiTagMask));                                     \ | 
|  3044   } else if (left_cid == kSmiCid) {                                            \ |  2994   } else if (left_cid == kSmiCid) {                                            \ | 
|  3045     __ tsti(right, Immediate(kSmiTagMask));                                    \ |  2995     __ tsti(right, Immediate(kSmiTagMask));                                    \ | 
|  3046   } else if (right_cid == kSmiCid) {                                           \ |  2996   } else if (right_cid == kSmiCid) {                                           \ | 
|  3047     __ tsti(left, Immediate(kSmiTagMask));                                     \ |  2997     __ tsti(left, Immediate(kSmiTagMask));                                     \ | 
|  3048   } else {                                                                     \ |  2998   } else {                                                                     \ | 
|  3049     __ orr(temp, left, Operand(right));                                        \ |  2999     __ orr(temp, left, Operand(right));                                        \ | 
|  3050     __ tsti(temp, Immediate(kSmiTagMask));                                     \ |  3000     __ tsti(temp, Immediate(kSmiTagMask));                                     \ | 
|  3051   }                                                                            \ |  3001   }                                                                            \ | 
|  3052   __ b(slow_path->entry_label(), NE) |  3002   __ b(slow_path->entry_label(), NE) | 
|  3053  |  3003  | 
|  3054  |  3004  | 
|  3055 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, |  3005 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 
|  3056                                                BranchInstr* branch) { |  3006                                                BranchInstr* branch) { | 
|  3057   BranchLabels labels = compiler->CreateBranchLabels(branch); |  3007   BranchLabels labels = compiler->CreateBranchLabels(branch); | 
|  3058   CheckedSmiComparisonSlowPath* slow_path = |  3008   CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( | 
|  3059       new CheckedSmiComparisonSlowPath(this, |  3009       this, compiler->CurrentTryIndex(), labels, | 
|  3060                                        compiler->CurrentTryIndex(), |  3010       /* merged = */ true); | 
|  3061                                        labels, |  | 
|  3062                                        /* merged = */ true); |  | 
|  3063   compiler->AddSlowPathCode(slow_path); |  3011   compiler->AddSlowPathCode(slow_path); | 
|  3064   EMIT_SMI_CHECK; |  3012   EMIT_SMI_CHECK; | 
|  3065   Condition true_condition = EmitComparisonCode(compiler, labels); |  3013   Condition true_condition = EmitComparisonCode(compiler, labels); | 
|  3066   EmitBranchOnCondition(compiler, true_condition, labels); |  3014   EmitBranchOnCondition(compiler, true_condition, labels); | 
|  3067   __ Bind(slow_path->exit_label()); |  3015   __ Bind(slow_path->exit_label()); | 
|  3068 } |  3016 } | 
|  3069  |  3017  | 
|  3070  |  3018  | 
|  3071 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  3019 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  3072   Label true_label, false_label, done; |  3020   Label true_label, false_label, done; | 
|  3073   BranchLabels labels = { &true_label, &false_label, &false_label }; |  3021   BranchLabels labels = {&true_label, &false_label, &false_label}; | 
|  3074   CheckedSmiComparisonSlowPath* slow_path = |  3022   CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( | 
|  3075       new CheckedSmiComparisonSlowPath(this, |  3023       this, compiler->CurrentTryIndex(), labels, | 
|  3076                                        compiler->CurrentTryIndex(), |  3024       /* merged = */ false); | 
|  3077                                        labels, |  | 
|  3078                                        /* merged = */ false); |  | 
|  3079   compiler->AddSlowPathCode(slow_path); |  3025   compiler->AddSlowPathCode(slow_path); | 
|  3080   EMIT_SMI_CHECK; |  3026   EMIT_SMI_CHECK; | 
|  3081   Condition true_condition = |  3027   Condition true_condition = EmitComparisonCode(compiler, labels); | 
|  3082       EmitComparisonCode(compiler, labels); |  | 
|  3083   EmitBranchOnCondition(compiler, true_condition, labels); |  3028   EmitBranchOnCondition(compiler, true_condition, labels); | 
|  3084   Register result = locs()->out(0).reg(); |  3029   Register result = locs()->out(0).reg(); | 
|  3085   __ Bind(&false_label); |  3030   __ Bind(&false_label); | 
|  3086   __ LoadObject(result, Bool::False()); |  3031   __ LoadObject(result, Bool::False()); | 
|  3087   __ b(&done); |  3032   __ b(&done); | 
|  3088   __ Bind(&true_label); |  3033   __ Bind(&true_label); | 
|  3089   __ LoadObject(result, Bool::True()); |  3034   __ LoadObject(result, Bool::True()); | 
|  3090   __ Bind(&done); |  3035   __ Bind(&done); | 
|  3091   __ Bind(slow_path->exit_label()); |  3036   __ Bind(slow_path->exit_label()); | 
|  3092 } |  3037 } | 
|  3093  |  3038  | 
|  3094  |  3039  | 
|  3095 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, |  3040 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, | 
|  3096                                                        bool opt) const { |  3041                                                        bool opt) const { | 
|  3097   const intptr_t kNumInputs = 2; |  3042   const intptr_t kNumInputs = 2; | 
|  3098   const intptr_t kNumTemps = |  3043   const intptr_t kNumTemps = (((op_kind() == Token::kSHL) && can_overflow()) || | 
|  3099       (((op_kind() == Token::kSHL) && can_overflow()) || |  3044                               (op_kind() == Token::kSHR)) | 
|  3100        (op_kind() == Token::kSHR)) ? 1 : 0; |  3045                                  ? 1 | 
|  3101   LocationSummary* summary = new(zone) LocationSummary( |  3046                                  : 0; | 
|  3102       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  3047   LocationSummary* summary = new (zone) | 
 |  3048       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  3103   if (op_kind() == Token::kTRUNCDIV) { |  3049   if (op_kind() == Token::kTRUNCDIV) { | 
|  3104     summary->set_in(0, Location::RequiresRegister()); |  3050     summary->set_in(0, Location::RequiresRegister()); | 
|  3105     if (RightIsPowerOfTwoConstant()) { |  3051     if (RightIsPowerOfTwoConstant()) { | 
|  3106       ConstantInstr* right_constant = right()->definition()->AsConstant(); |  3052       ConstantInstr* right_constant = right()->definition()->AsConstant(); | 
|  3107       summary->set_in(1, Location::Constant(right_constant)); |  3053       summary->set_in(1, Location::Constant(right_constant)); | 
|  3108     } else { |  3054     } else { | 
|  3109       summary->set_in(1, Location::RequiresRegister()); |  3055       summary->set_in(1, Location::RequiresRegister()); | 
|  3110     } |  3056     } | 
|  3111     summary->set_out(0, Location::RequiresRegister()); |  3057     summary->set_out(0, Location::RequiresRegister()); | 
|  3112     return summary; |  3058     return summary; | 
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  3208         __ OrImmediate(result, left, imm); |  3154         __ OrImmediate(result, left, imm); | 
|  3209         break; |  3155         break; | 
|  3210       case Token::kBIT_XOR: |  3156       case Token::kBIT_XOR: | 
|  3211         // No overflow check. |  3157         // No overflow check. | 
|  3212         __ XorImmediate(result, left, imm); |  3158         __ XorImmediate(result, left, imm); | 
|  3213         break; |  3159         break; | 
|  3214       case Token::kSHR: { |  3160       case Token::kSHR: { | 
|  3215         // Asr operation masks the count to 6 bits. |  3161         // Asr operation masks the count to 6 bits. | 
|  3216         const intptr_t kCountLimit = 0x3F; |  3162         const intptr_t kCountLimit = 0x3F; | 
|  3217         intptr_t value = Smi::Cast(constant).Value(); |  3163         intptr_t value = Smi::Cast(constant).Value(); | 
|  3218         __ AsrImmediate( |  3164         __ AsrImmediate(result, left, | 
|  3219             result, left, Utils::Minimum(value + kSmiTagSize, kCountLimit)); |  3165                         Utils::Minimum(value + kSmiTagSize, kCountLimit)); | 
|  3220         __ SmiTag(result); |  3166         __ SmiTag(result); | 
|  3221         break; |  3167         break; | 
|  3222       } |  3168       } | 
|  3223       default: |  3169       default: | 
|  3224         UNREACHABLE(); |  3170         UNREACHABLE(); | 
|  3225         break; |  3171         break; | 
|  3226     } |  3172     } | 
|  3227     return; |  3173     return; | 
|  3228   } |  3174   } | 
|  3229  |  3175  | 
| (...skipping 16 matching lines...) Expand all  Loading... | 
|  3246         __ subs(result, left, Operand(right)); |  3192         __ subs(result, left, Operand(right)); | 
|  3247         __ b(deopt, VS); |  3193         __ b(deopt, VS); | 
|  3248       } |  3194       } | 
|  3249       break; |  3195       break; | 
|  3250     } |  3196     } | 
|  3251     case Token::kMUL: { |  3197     case Token::kMUL: { | 
|  3252       __ SmiUntag(TMP, left); |  3198       __ SmiUntag(TMP, left); | 
|  3253       if (deopt == NULL) { |  3199       if (deopt == NULL) { | 
|  3254         __ mul(result, TMP, right); |  3200         __ mul(result, TMP, right); | 
|  3255       } else { |  3201       } else { | 
|  3256           __ mul(result, TMP, right); |  3202         __ mul(result, TMP, right); | 
|  3257           __ smulh(TMP, TMP, right); |  3203         __ smulh(TMP, TMP, right); | 
|  3258           // TMP: result bits 64..127. |  3204         // TMP: result bits 64..127. | 
|  3259           __ cmp(TMP, Operand(result, ASR, 63)); |  3205         __ cmp(TMP, Operand(result, ASR, 63)); | 
|  3260           __ b(deopt, NE); |  3206         __ b(deopt, NE); | 
|  3261       } |  3207       } | 
|  3262       break; |  3208       break; | 
|  3263     } |  3209     } | 
|  3264     case Token::kBIT_AND: { |  3210     case Token::kBIT_AND: { | 
|  3265       // No overflow check. |  3211       // No overflow check. | 
|  3266       __ and_(result, left, Operand(right)); |  3212       __ and_(result, left, Operand(right)); | 
|  3267       break; |  3213       break; | 
|  3268     } |  3214     } | 
|  3269     case Token::kBIT_OR: { |  3215     case Token::kBIT_OR: { | 
|  3270       // No overflow check. |  3216       // No overflow check. | 
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  3369 } |  3315 } | 
|  3370  |  3316  | 
|  3371  |  3317  | 
|  3372 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone, |  3318 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone, | 
|  3373                                                              bool opt) const { |  3319                                                              bool opt) const { | 
|  3374   intptr_t left_cid = left()->Type()->ToCid(); |  3320   intptr_t left_cid = left()->Type()->ToCid(); | 
|  3375   intptr_t right_cid = right()->Type()->ToCid(); |  3321   intptr_t right_cid = right()->Type()->ToCid(); | 
|  3376   ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); |  3322   ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); | 
|  3377   const intptr_t kNumInputs = 2; |  3323   const intptr_t kNumInputs = 2; | 
|  3378   const intptr_t kNumTemps = 0; |  3324   const intptr_t kNumTemps = 0; | 
|  3379   LocationSummary* summary = new(zone) LocationSummary( |  3325   LocationSummary* summary = new (zone) | 
|  3380       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  3326       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  3381   summary->set_in(0, Location::RequiresRegister()); |  3327   summary->set_in(0, Location::RequiresRegister()); | 
|  3382   summary->set_in(1, Location::RequiresRegister()); |  3328   summary->set_in(1, Location::RequiresRegister()); | 
|  3383   return summary; |  3329   return summary; | 
|  3384 } |  3330 } | 
|  3385  |  3331  | 
|  3386  |  3332  | 
|  3387 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  3333 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  3388   Label* deopt = compiler->AddDeoptStub(deopt_id(), |  3334   Label* deopt = | 
|  3389                                         ICData::kDeoptBinaryDoubleOp, |  3335       compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryDoubleOp, | 
|  3390                                         licm_hoisted_ ? ICData::kHoisted : 0); |  3336                              licm_hoisted_ ? ICData::kHoisted : 0); | 
|  3391   intptr_t left_cid = left()->Type()->ToCid(); |  3337   intptr_t left_cid = left()->Type()->ToCid(); | 
|  3392   intptr_t right_cid = right()->Type()->ToCid(); |  3338   intptr_t right_cid = right()->Type()->ToCid(); | 
|  3393   const Register left = locs()->in(0).reg(); |  3339   const Register left = locs()->in(0).reg(); | 
|  3394   const Register right = locs()->in(1).reg(); |  3340   const Register right = locs()->in(1).reg(); | 
|  3395   if (this->left()->definition() == this->right()->definition()) { |  3341   if (this->left()->definition() == this->right()->definition()) { | 
|  3396     __ tsti(left, Immediate(kSmiTagMask)); |  3342     __ tsti(left, Immediate(kSmiTagMask)); | 
|  3397   } else if (left_cid == kSmiCid) { |  3343   } else if (left_cid == kSmiCid) { | 
|  3398     __ tsti(right, Immediate(kSmiTagMask)); |  3344     __ tsti(right, Immediate(kSmiTagMask)); | 
|  3399   } else if (right_cid == kSmiCid) { |  3345   } else if (right_cid == kSmiCid) { | 
|  3400     __ tsti(left, Immediate(kSmiTagMask)); |  3346     __ tsti(left, Immediate(kSmiTagMask)); | 
|  3401   } else { |  3347   } else { | 
|  3402     __ orr(TMP, left, Operand(right)); |  3348     __ orr(TMP, left, Operand(right)); | 
|  3403     __ tsti(TMP, Immediate(kSmiTagMask)); |  3349     __ tsti(TMP, Immediate(kSmiTagMask)); | 
|  3404   } |  3350   } | 
|  3405   __ b(deopt, EQ); |  3351   __ b(deopt, EQ); | 
|  3406 } |  3352 } | 
|  3407  |  3353  | 
|  3408  |  3354  | 
|  3409 LocationSummary* BoxInstr::MakeLocationSummary(Zone* zone, |  3355 LocationSummary* BoxInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 
|  3410                                                bool opt) const { |  | 
|  3411   const intptr_t kNumInputs = 1; |  3356   const intptr_t kNumInputs = 1; | 
|  3412   const intptr_t kNumTemps = 1; |  3357   const intptr_t kNumTemps = 1; | 
|  3413   LocationSummary* summary = new(zone) LocationSummary( |  3358   LocationSummary* summary = new (zone) LocationSummary( | 
|  3414       zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |  3359       zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 
|  3415   summary->set_in(0, Location::RequiresFpuRegister()); |  3360   summary->set_in(0, Location::RequiresFpuRegister()); | 
|  3416   summary->set_temp(0, Location::RequiresRegister()); |  3361   summary->set_temp(0, Location::RequiresRegister()); | 
|  3417   summary->set_out(0, Location::RequiresRegister()); |  3362   summary->set_out(0, Location::RequiresRegister()); | 
|  3418   return summary; |  3363   return summary; | 
|  3419 } |  3364 } | 
|  3420  |  3365  | 
|  3421  |  3366  | 
|  3422 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  3367 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  3423   const Register out_reg = locs()->out(0).reg(); |  3368   const Register out_reg = locs()->out(0).reg(); | 
|  3424   const Register temp_reg = locs()->temp(0).reg(); |  3369   const Register temp_reg = locs()->temp(0).reg(); | 
|  3425   const VRegister value = locs()->in(0).fpu_reg(); |  3370   const VRegister value = locs()->in(0).fpu_reg(); | 
|  3426  |  3371  | 
|  3427   BoxAllocationSlowPath::Allocate( |  3372   BoxAllocationSlowPath::Allocate(compiler, this, | 
|  3428       compiler, |  3373                                   compiler->BoxClassFor(from_representation()), | 
|  3429       this, |  3374                                   out_reg, temp_reg); | 
|  3430       compiler->BoxClassFor(from_representation()), |  | 
|  3431       out_reg, |  | 
|  3432       temp_reg); |  | 
|  3433  |  3375  | 
|  3434   switch (from_representation()) { |  3376   switch (from_representation()) { | 
|  3435     case kUnboxedDouble: |  3377     case kUnboxedDouble: | 
|  3436       __ StoreDFieldToOffset(value, out_reg, ValueOffset()); |  3378       __ StoreDFieldToOffset(value, out_reg, ValueOffset()); | 
|  3437       break; |  3379       break; | 
|  3438     case kUnboxedFloat32x4: |  3380     case kUnboxedFloat32x4: | 
|  3439     case kUnboxedFloat64x2: |  3381     case kUnboxedFloat64x2: | 
|  3440     case kUnboxedInt32x4: |  3382     case kUnboxedInt32x4: | 
|  3441       __ StoreQFieldToOffset(value, out_reg, ValueOffset()); |  3383       __ StoreQFieldToOffset(value, out_reg, ValueOffset()); | 
|  3442       break; |  3384       break; | 
|  3443     default: |  3385     default: | 
|  3444       UNREACHABLE(); |  3386       UNREACHABLE(); | 
|  3445       break; |  3387       break; | 
|  3446   } |  3388   } | 
|  3447 } |  3389 } | 
|  3448  |  3390  | 
|  3449  |  3391  | 
|  3450 LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, |  3392 LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 
|  3451                                                  bool opt) const { |  | 
|  3452   const intptr_t kNumInputs = 1; |  3393   const intptr_t kNumInputs = 1; | 
|  3453   const intptr_t kNumTemps = 0; |  3394   const intptr_t kNumTemps = 0; | 
|  3454   LocationSummary* summary = new(zone) LocationSummary( |  3395   LocationSummary* summary = new (zone) | 
|  3455       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  3396       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  3456   summary->set_in(0, Location::RequiresRegister()); |  3397   summary->set_in(0, Location::RequiresRegister()); | 
|  3457   summary->set_out(0, Location::RequiresFpuRegister()); |  3398   summary->set_out(0, Location::RequiresFpuRegister()); | 
|  3458   return summary; |  3399   return summary; | 
|  3459 } |  3400 } | 
|  3460  |  3401  | 
|  3461  |  3402  | 
|  3462 void UnboxInstr::EmitLoadFromBox(FlowGraphCompiler* compiler) { |  3403 void UnboxInstr::EmitLoadFromBox(FlowGraphCompiler* compiler) { | 
|  3463   const Register box = locs()->in(0).reg(); |  3404   const Register box = locs()->in(0).reg(); | 
|  3464  |  3405  | 
|  3465   switch (representation()) { |  3406   switch (representation()) { | 
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  3515 void UnboxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  3456 void UnboxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  3516   const intptr_t value_cid = value()->Type()->ToCid(); |  3457   const intptr_t value_cid = value()->Type()->ToCid(); | 
|  3517   const intptr_t box_cid = BoxCid(); |  3458   const intptr_t box_cid = BoxCid(); | 
|  3518  |  3459  | 
|  3519   if (value_cid == box_cid) { |  3460   if (value_cid == box_cid) { | 
|  3520     EmitLoadFromBox(compiler); |  3461     EmitLoadFromBox(compiler); | 
|  3521   } else if (CanConvertSmi() && (value_cid == kSmiCid)) { |  3462   } else if (CanConvertSmi() && (value_cid == kSmiCid)) { | 
|  3522     EmitSmiConversion(compiler); |  3463     EmitSmiConversion(compiler); | 
|  3523   } else { |  3464   } else { | 
|  3524     const Register box = locs()->in(0).reg(); |  3465     const Register box = locs()->in(0).reg(); | 
|  3525     Label* deopt = compiler->AddDeoptStub(GetDeoptId(), |  3466     Label* deopt = | 
|  3526                                           ICData::kDeoptCheckClass); |  3467         compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptCheckClass); | 
|  3527     Label is_smi; |  3468     Label is_smi; | 
|  3528  |  3469  | 
|  3529     if ((value()->Type()->ToNullableCid() == box_cid) && |  3470     if ((value()->Type()->ToNullableCid() == box_cid) && | 
|  3530         value()->Type()->is_nullable()) { |  3471         value()->Type()->is_nullable()) { | 
|  3531       __ CompareObject(box, Object::null_object()); |  3472       __ CompareObject(box, Object::null_object()); | 
|  3532       __ b(deopt, EQ); |  3473       __ b(deopt, EQ); | 
|  3533     } else { |  3474     } else { | 
|  3534       __ tsti(box, Immediate(kSmiTagMask)); |  3475       __ tsti(box, Immediate(kSmiTagMask)); | 
|  3535       __ b(CanConvertSmi() ? &is_smi : deopt, EQ); |  3476       __ b(CanConvertSmi() ? &is_smi : deopt, EQ); | 
|  3536       __ CompareClassId(box, box_cid); |  3477       __ CompareClassId(box, box_cid); | 
| (...skipping 12 matching lines...) Expand all  Loading... | 
|  3549   } |  3490   } | 
|  3550 } |  3491 } | 
|  3551  |  3492  | 
|  3552  |  3493  | 
|  3553 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone, |  3494 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone, | 
|  3554                                                         bool opt) const { |  3495                                                         bool opt) const { | 
|  3555   ASSERT((from_representation() == kUnboxedInt32) || |  3496   ASSERT((from_representation() == kUnboxedInt32) || | 
|  3556          (from_representation() == kUnboxedUint32)); |  3497          (from_representation() == kUnboxedUint32)); | 
|  3557   const intptr_t kNumInputs = 1; |  3498   const intptr_t kNumInputs = 1; | 
|  3558   const intptr_t kNumTemps = 0; |  3499   const intptr_t kNumTemps = 0; | 
|  3559   LocationSummary* summary = new(zone) LocationSummary( |  3500   LocationSummary* summary = new (zone) | 
|  3560       zone, |  3501       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  3561       kNumInputs, |  | 
|  3562       kNumTemps, |  | 
|  3563       LocationSummary::kNoCall); |  | 
|  3564   summary->set_in(0, Location::RequiresRegister()); |  3502   summary->set_in(0, Location::RequiresRegister()); | 
|  3565   summary->set_out(0, Location::RequiresRegister()); |  3503   summary->set_out(0, Location::RequiresRegister()); | 
|  3566   return summary; |  3504   return summary; | 
|  3567 } |  3505 } | 
|  3568  |  3506  | 
|  3569  |  3507  | 
|  3570 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |  3508 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  3571   Register value = locs()->in(0).reg(); |  3509   Register value = locs()->in(0).reg(); | 
|  3572   Register out = locs()->out(0).reg(); |  3510   Register out = locs()->out(0).reg(); | 
|  3573   ASSERT(value != out); |  3511   ASSERT(value != out); | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
|  3584 } |  3522 } | 
|  3585  |  3523  | 
|  3586  |  3524  | 
|  3587 DEFINE_UNIMPLEMENTED_INSTRUCTION(BoxInt64Instr) |  3525 DEFINE_UNIMPLEMENTED_INSTRUCTION(BoxInt64Instr) | 
|  3588  |  3526  | 
|  3589  |  3527  | 
|  3590 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Zone* zone, |  3528 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Zone* zone, | 
|  3591                                                           bool opt) const { |  3529                                                           bool opt) const { | 
|  3592   const intptr_t kNumInputs = 1; |  3530   const intptr_t kNumInputs = 1; | 
|  3593   const intptr_t kNumTemps = 0; |  3531   const intptr_t kNumTemps = 0; | 
|  3594   LocationSummary* summary = new(zone) LocationSummary( |  3532   LocationSummary* summary = new (zone) | 
|  3595       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  3533       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  3596   summary->set_in(0, Location::RequiresRegister()); |  3534   summary->set_in(0, Location::RequiresRegister()); | 
|  3597   summary->set_out(0, Location::RequiresRegister()); |  3535   summary->set_out(0, Location::RequiresRegister()); | 
|  3598   return summary; |  3536   return summary; | 
|  3599 } |  3537 } | 
|  3600  |  3538  | 
|  3601  |  3539  | 
|  3602 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |  3540 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  3603   const intptr_t value_cid = value()->Type()->ToCid(); |  3541   const intptr_t value_cid = value()->Type()->ToCid(); | 
|  3604   const Register out = locs()->out(0).reg(); |  3542   const Register out = locs()->out(0).reg(); | 
|  3605   const Register value = locs()->in(0).reg(); |  3543   const Register value = locs()->in(0).reg(); | 
|  3606   Label* deopt = CanDeoptimize() ? |  3544   Label* deopt = | 
|  3607       compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger) : NULL; |  3545       CanDeoptimize() | 
 |  3546           ? compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger) | 
 |  3547           : NULL; | 
|  3608  |  3548  | 
|  3609   if (value_cid == kSmiCid) { |  3549   if (value_cid == kSmiCid) { | 
|  3610     __ SmiUntag(out, value); |  3550     __ SmiUntag(out, value); | 
|  3611   } else if (value_cid == kMintCid) { |  3551   } else if (value_cid == kMintCid) { | 
|  3612     __ LoadFieldFromOffset(out, value, Mint::value_offset()); |  3552     __ LoadFieldFromOffset(out, value, Mint::value_offset()); | 
|  3613   } else if (!CanDeoptimize()) { |  3553   } else if (!CanDeoptimize()) { | 
|  3614     // Type information is not conclusive, but range analysis found |  3554     // Type information is not conclusive, but range analysis found | 
|  3615     // the value to be in int64 range. Therefore it must be a smi |  3555     // the value to be in int64 range. Therefore it must be a smi | 
|  3616     // or mint value. |  3556     // or mint value. | 
|  3617     ASSERT(is_truncating()); |  3557     ASSERT(is_truncating()); | 
| (...skipping 21 matching lines...) Expand all  Loading... | 
|  3639     __ cmp(out, Operand(out, SXTW, 0)); |  3579     __ cmp(out, Operand(out, SXTW, 0)); | 
|  3640     __ b(deopt, NE); |  3580     __ b(deopt, NE); | 
|  3641   } |  3581   } | 
|  3642 } |  3582 } | 
|  3643  |  3583  | 
|  3644  |  3584  | 
|  3645 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Zone* zone, |  3585 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Zone* zone, | 
|  3646                                                           bool opt) const { |  3586                                                           bool opt) const { | 
|  3647   const intptr_t kNumInputs = 2; |  3587   const intptr_t kNumInputs = 2; | 
|  3648   const intptr_t kNumTemps = 0; |  3588   const intptr_t kNumTemps = 0; | 
|  3649   LocationSummary* summary = new(zone) LocationSummary( |  3589   LocationSummary* summary = new (zone) | 
|  3650       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  3590       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  3651   summary->set_in(0, Location::RequiresFpuRegister()); |  3591   summary->set_in(0, Location::RequiresFpuRegister()); | 
|  3652   summary->set_in(1, Location::RequiresFpuRegister()); |  3592   summary->set_in(1, Location::RequiresFpuRegister()); | 
|  3653   summary->set_out(0, Location::RequiresFpuRegister()); |  3593   summary->set_out(0, Location::RequiresFpuRegister()); | 
|  3654   return summary; |  3594   return summary; | 
|  3655 } |  3595 } | 
|  3656  |  3596  | 
|  3657  |  3597  | 
|  3658 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  3598 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  3659   const VRegister left = locs()->in(0).fpu_reg(); |  3599   const VRegister left = locs()->in(0).fpu_reg(); | 
|  3660   const VRegister right = locs()->in(1).fpu_reg(); |  3600   const VRegister right = locs()->in(1).fpu_reg(); | 
|  3661   const VRegister result = locs()->out(0).fpu_reg(); |  3601   const VRegister result = locs()->out(0).fpu_reg(); | 
|  3662   switch (op_kind()) { |  3602   switch (op_kind()) { | 
|  3663     case Token::kADD: __ faddd(result, left, right); break; |  3603     case Token::kADD: | 
|  3664     case Token::kSUB: __ fsubd(result, left, right); break; |  3604       __ faddd(result, left, right); | 
|  3665     case Token::kMUL: __ fmuld(result, left, right); break; |  3605       break; | 
|  3666     case Token::kDIV: __ fdivd(result, left, right); break; |  3606     case Token::kSUB: | 
|  3667     default: UNREACHABLE(); |  3607       __ fsubd(result, left, right); | 
 |  3608       break; | 
 |  3609     case Token::kMUL: | 
 |  3610       __ fmuld(result, left, right); | 
 |  3611       break; | 
 |  3612     case Token::kDIV: | 
 |  3613       __ fdivd(result, left, right); | 
 |  3614       break; | 
 |  3615     default: | 
 |  3616       UNREACHABLE(); | 
|  3668   } |  3617   } | 
|  3669 } |  3618 } | 
|  3670  |  3619  | 
|  3671  |  3620  | 
|  3672 LocationSummary* DoubleTestOpInstr::MakeLocationSummary(Zone* zone, |  3621 LocationSummary* DoubleTestOpInstr::MakeLocationSummary(Zone* zone, | 
|  3673                                                         bool opt) const { |  3622                                                         bool opt) const { | 
|  3674   const intptr_t kNumInputs = 1; |  3623   const intptr_t kNumInputs = 1; | 
|  3675   const intptr_t kNumTemps = |  3624   const intptr_t kNumTemps = | 
|  3676       op_kind() == MethodRecognizer::kDouble_getIsInfinite ? 1 : 0; |  3625       op_kind() == MethodRecognizer::kDouble_getIsInfinite ? 1 : 0; | 
|  3677   LocationSummary* summary = new(zone) LocationSummary( |  3626   LocationSummary* summary = new (zone) | 
|  3678       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  3627       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  3679   summary->set_in(0, Location::RequiresFpuRegister()); |  3628   summary->set_in(0, Location::RequiresFpuRegister()); | 
|  3680   if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) { |  3629   if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) { | 
|  3681     summary->set_temp(0, Location::RequiresRegister()); |  3630     summary->set_temp(0, Location::RequiresRegister()); | 
|  3682   } |  3631   } | 
|  3683   summary->set_out(0, Location::RequiresRegister()); |  3632   summary->set_out(0, Location::RequiresRegister()); | 
|  3684   return summary; |  3633   return summary; | 
|  3685 } |  3634 } | 
|  3686  |  3635  | 
|  3687  |  3636  | 
|  3688 Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |  3637 Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 
| (...skipping 22 matching lines...) Expand all  Loading... | 
|  3711   ASSERT(compiler->is_optimizing()); |  3660   ASSERT(compiler->is_optimizing()); | 
|  3712   BranchLabels labels = compiler->CreateBranchLabels(branch); |  3661   BranchLabels labels = compiler->CreateBranchLabels(branch); | 
|  3713   Condition true_condition = EmitComparisonCode(compiler, labels); |  3662   Condition true_condition = EmitComparisonCode(compiler, labels); | 
|  3714   EmitBranchOnCondition(compiler, true_condition, labels); |  3663   EmitBranchOnCondition(compiler, true_condition, labels); | 
|  3715 } |  3664 } | 
|  3716  |  3665  | 
|  3717  |  3666  | 
|  3718 void DoubleTestOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  3667 void DoubleTestOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  3719   ASSERT(compiler->is_optimizing()); |  3668   ASSERT(compiler->is_optimizing()); | 
|  3720   Label is_true, is_false; |  3669   Label is_true, is_false; | 
|  3721   BranchLabels labels = { &is_true, &is_false, &is_false }; |  3670   BranchLabels labels = {&is_true, &is_false, &is_false}; | 
|  3722   Condition true_condition = EmitComparisonCode(compiler, labels); |  3671   Condition true_condition = EmitComparisonCode(compiler, labels); | 
|  3723   const Register result = locs()->out(0).reg(); |  3672   const Register result = locs()->out(0).reg(); | 
|  3724   if (op_kind() == MethodRecognizer::kDouble_getIsNaN) { |  3673   if (op_kind() == MethodRecognizer::kDouble_getIsNaN) { | 
|  3725     __ LoadObject(result, Bool::False()); |  3674     __ LoadObject(result, Bool::False()); | 
|  3726     __ LoadObject(TMP, Bool::True()); |  3675     __ LoadObject(TMP, Bool::True()); | 
|  3727     __ csel(result, TMP, result, true_condition); |  3676     __ csel(result, TMP, result, true_condition); | 
|  3728   } else { |  3677   } else { | 
|  3729     __ LoadObject(result, Bool::False()); |  3678     __ LoadObject(result, Bool::False()); | 
|  3730     __ LoadObject(TMP, Bool::True()); |  3679     __ LoadObject(TMP, Bool::True()); | 
|  3731     __ csel(result, TMP, result, true_condition); |  3680     __ csel(result, TMP, result, true_condition); | 
|  3732   } |  3681   } | 
|  3733 } |  3682 } | 
|  3734  |  3683  | 
|  3735  |  3684  | 
|  3736 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, |  3685 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, | 
|  3737                                                              bool opt) const { |  3686                                                              bool opt) const { | 
|  3738   const intptr_t kNumInputs = 2; |  3687   const intptr_t kNumInputs = 2; | 
|  3739   const intptr_t kNumTemps = 0; |  3688   const intptr_t kNumTemps = 0; | 
|  3740   LocationSummary* summary = new(zone) LocationSummary( |  3689   LocationSummary* summary = new (zone) | 
|  3741       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  3690       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  3742   summary->set_in(0, Location::RequiresFpuRegister()); |  3691   summary->set_in(0, Location::RequiresFpuRegister()); | 
|  3743   summary->set_in(1, Location::RequiresFpuRegister()); |  3692   summary->set_in(1, Location::RequiresFpuRegister()); | 
|  3744   summary->set_out(0, Location::RequiresFpuRegister()); |  3693   summary->set_out(0, Location::RequiresFpuRegister()); | 
|  3745   return summary; |  3694   return summary; | 
|  3746 } |  3695 } | 
|  3747  |  3696  | 
|  3748  |  3697  | 
|  3749 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  3698 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  3750   const VRegister left = locs()->in(0).fpu_reg(); |  3699   const VRegister left = locs()->in(0).fpu_reg(); | 
|  3751   const VRegister right = locs()->in(1).fpu_reg(); |  3700   const VRegister right = locs()->in(1).fpu_reg(); | 
|  3752   const VRegister result = locs()->out(0).fpu_reg(); |  3701   const VRegister result = locs()->out(0).fpu_reg(); | 
|  3753  |  3702  | 
|  3754   switch (op_kind()) { |  3703   switch (op_kind()) { | 
|  3755     case Token::kADD: __ vadds(result, left, right); break; |  3704     case Token::kADD: | 
|  3756     case Token::kSUB: __ vsubs(result, left, right); break; |  3705       __ vadds(result, left, right); | 
|  3757     case Token::kMUL: __ vmuls(result, left, right); break; |  3706       break; | 
|  3758     case Token::kDIV: __ vdivs(result, left, right); break; |  3707     case Token::kSUB: | 
|  3759     default: UNREACHABLE(); |  3708       __ vsubs(result, left, right); | 
 |  3709       break; | 
 |  3710     case Token::kMUL: | 
 |  3711       __ vmuls(result, left, right); | 
 |  3712       break; | 
 |  3713     case Token::kDIV: | 
 |  3714       __ vdivs(result, left, right); | 
 |  3715       break; | 
 |  3716     default: | 
 |  3717       UNREACHABLE(); | 
|  3760   } |  3718   } | 
|  3761 } |  3719 } | 
|  3762  |  3720  | 
|  3763  |  3721  | 
|  3764 LocationSummary* BinaryFloat64x2OpInstr::MakeLocationSummary(Zone* zone, |  3722 LocationSummary* BinaryFloat64x2OpInstr::MakeLocationSummary(Zone* zone, | 
|  3765                                                              bool opt) const { |  3723                                                              bool opt) const { | 
|  3766   const intptr_t kNumInputs = 2; |  3724   const intptr_t kNumInputs = 2; | 
|  3767   const intptr_t kNumTemps = 0; |  3725   const intptr_t kNumTemps = 0; | 
|  3768   LocationSummary* summary = new(zone) LocationSummary( |  3726   LocationSummary* summary = new (zone) | 
|  3769       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  3727       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  3770   summary->set_in(0, Location::RequiresFpuRegister()); |  3728   summary->set_in(0, Location::RequiresFpuRegister()); | 
|  3771   summary->set_in(1, Location::RequiresFpuRegister()); |  3729   summary->set_in(1, Location::RequiresFpuRegister()); | 
|  3772   summary->set_out(0, Location::RequiresFpuRegister()); |  3730   summary->set_out(0, Location::RequiresFpuRegister()); | 
|  3773   return summary; |  3731   return summary; | 
|  3774 } |  3732 } | 
|  3775  |  3733  | 
|  3776  |  3734  | 
|  3777 void BinaryFloat64x2OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  3735 void BinaryFloat64x2OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  3778   const VRegister left = locs()->in(0).fpu_reg(); |  3736   const VRegister left = locs()->in(0).fpu_reg(); | 
|  3779   const VRegister right = locs()->in(1).fpu_reg(); |  3737   const VRegister right = locs()->in(1).fpu_reg(); | 
|  3780   const VRegister result = locs()->out(0).fpu_reg(); |  3738   const VRegister result = locs()->out(0).fpu_reg(); | 
|  3781  |  3739  | 
|  3782   switch (op_kind()) { |  3740   switch (op_kind()) { | 
|  3783     case Token::kADD: __ vaddd(result, left, right); break; |  3741     case Token::kADD: | 
|  3784     case Token::kSUB: __ vsubd(result, left, right); break; |  3742       __ vaddd(result, left, right); | 
|  3785     case Token::kMUL: __ vmuld(result, left, right); break; |  3743       break; | 
|  3786     case Token::kDIV: __ vdivd(result, left, right); break; |  3744     case Token::kSUB: | 
|  3787     default: UNREACHABLE(); |  3745       __ vsubd(result, left, right); | 
 |  3746       break; | 
 |  3747     case Token::kMUL: | 
 |  3748       __ vmuld(result, left, right); | 
 |  3749       break; | 
 |  3750     case Token::kDIV: | 
 |  3751       __ vdivd(result, left, right); | 
 |  3752       break; | 
 |  3753     default: | 
 |  3754       UNREACHABLE(); | 
|  3788   } |  3755   } | 
|  3789 } |  3756 } | 
|  3790  |  3757  | 
|  3791  |  3758  | 
|  3792 LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary(Zone* zone, |  3759 LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary(Zone* zone, | 
|  3793                                                            bool opt) const { |  3760                                                            bool opt) const { | 
|  3794   const intptr_t kNumInputs = 1; |  3761   const intptr_t kNumInputs = 1; | 
|  3795   const intptr_t kNumTemps = 0; |  3762   const intptr_t kNumTemps = 0; | 
|  3796   LocationSummary* summary = new LocationSummary( |  3763   LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, | 
|  3797       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  3764                                                  LocationSummary::kNoCall); | 
|  3798   summary->set_in(0, Location::RequiresFpuRegister()); |  3765   summary->set_in(0, Location::RequiresFpuRegister()); | 
|  3799   summary->set_out(0, Location::RequiresFpuRegister()); |  3766   summary->set_out(0, Location::RequiresFpuRegister()); | 
|  3800   return summary; |  3767   return summary; | 
|  3801 } |  3768 } | 
|  3802  |  3769  | 
|  3803  |  3770  | 
|  3804 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  3771 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  3805   const VRegister value = locs()->in(0).fpu_reg(); |  3772   const VRegister value = locs()->in(0).fpu_reg(); | 
|  3806   const VRegister result = locs()->out(0).fpu_reg(); |  3773   const VRegister result = locs()->out(0).fpu_reg(); | 
|  3807  |  3774  | 
| (...skipping 15 matching lines...) Expand all  Loading... | 
|  3823       __ fcvtds(result, result); |  3790       __ fcvtds(result, result); | 
|  3824       break; |  3791       break; | 
|  3825     case MethodRecognizer::kInt32x4Shuffle: |  3792     case MethodRecognizer::kInt32x4Shuffle: | 
|  3826     case MethodRecognizer::kFloat32x4Shuffle: |  3793     case MethodRecognizer::kFloat32x4Shuffle: | 
|  3827       if (mask_ == 0x00) { |  3794       if (mask_ == 0x00) { | 
|  3828         __ vdups(result, value, 0); |  3795         __ vdups(result, value, 0); | 
|  3829       } else if (mask_ == 0x55) { |  3796       } else if (mask_ == 0x55) { | 
|  3830         __ vdups(result, value, 1); |  3797         __ vdups(result, value, 1); | 
|  3831       } else if (mask_ == 0xAA) { |  3798       } else if (mask_ == 0xAA) { | 
|  3832         __ vdups(result, value, 2); |  3799         __ vdups(result, value, 2); | 
|  3833       } else  if (mask_ == 0xFF) { |  3800       } else if (mask_ == 0xFF) { | 
|  3834         __ vdups(result, value, 3); |  3801         __ vdups(result, value, 3); | 
|  3835       } else { |  3802       } else { | 
|  3836         __ vinss(result, 0, value, mask_ & 0x3); |  3803         __ vinss(result, 0, value, mask_ & 0x3); | 
|  3837         __ vinss(result, 1, value, (mask_ >> 2) & 0x3); |  3804         __ vinss(result, 1, value, (mask_ >> 2) & 0x3); | 
|  3838         __ vinss(result, 2, value, (mask_ >> 4) & 0x3); |  3805         __ vinss(result, 2, value, (mask_ >> 4) & 0x3); | 
|  3839         __ vinss(result, 3, value, (mask_ >> 6) & 0x3); |  3806         __ vinss(result, 3, value, (mask_ >> 6) & 0x3); | 
|  3840       } |  3807       } | 
|  3841       break; |  3808       break; | 
|  3842     default: UNREACHABLE(); |  3809     default: | 
 |  3810       UNREACHABLE(); | 
|  3843   } |  3811   } | 
|  3844 } |  3812 } | 
|  3845  |  3813  | 
|  3846  |  3814  | 
|  3847 LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(Zone* zone, |  3815 LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(Zone* zone, | 
|  3848                                                               bool opt) const { |  3816                                                               bool opt) const { | 
|  3849   const intptr_t kNumInputs = 2; |  3817   const intptr_t kNumInputs = 2; | 
|  3850   const intptr_t kNumTemps = 0; |  3818   const intptr_t kNumTemps = 0; | 
|  3851   LocationSummary* summary = new LocationSummary( |  3819   LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, | 
|  3852       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  3820                                                  LocationSummary::kNoCall); | 
|  3853   summary->set_in(0, Location::RequiresFpuRegister()); |  3821   summary->set_in(0, Location::RequiresFpuRegister()); | 
|  3854   summary->set_in(1, Location::RequiresFpuRegister()); |  3822   summary->set_in(1, Location::RequiresFpuRegister()); | 
|  3855   summary->set_out(0, Location::RequiresFpuRegister()); |  3823   summary->set_out(0, Location::RequiresFpuRegister()); | 
|  3856   return summary; |  3824   return summary; | 
|  3857 } |  3825 } | 
|  3858  |  3826  | 
|  3859  |  3827  | 
|  3860 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  3828 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  3861   const VRegister left = locs()->in(0).fpu_reg(); |  3829   const VRegister left = locs()->in(0).fpu_reg(); | 
|  3862   const VRegister right = locs()->in(1).fpu_reg(); |  3830   const VRegister right = locs()->in(1).fpu_reg(); | 
|  3863   const VRegister result = locs()->out(0).fpu_reg(); |  3831   const VRegister result = locs()->out(0).fpu_reg(); | 
|  3864  |  3832  | 
|  3865   switch (op_kind()) { |  3833   switch (op_kind()) { | 
|  3866     case MethodRecognizer::kFloat32x4ShuffleMix: |  3834     case MethodRecognizer::kFloat32x4ShuffleMix: | 
|  3867     case MethodRecognizer::kInt32x4ShuffleMix: |  3835     case MethodRecognizer::kInt32x4ShuffleMix: | 
|  3868       __ vinss(result, 0, left, mask_ & 0x3); |  3836       __ vinss(result, 0, left, mask_ & 0x3); | 
|  3869       __ vinss(result, 1, left, (mask_ >> 2) & 0x3); |  3837       __ vinss(result, 1, left, (mask_ >> 2) & 0x3); | 
|  3870       __ vinss(result, 2, right, (mask_ >> 4) & 0x3); |  3838       __ vinss(result, 2, right, (mask_ >> 4) & 0x3); | 
|  3871       __ vinss(result, 3, right, (mask_ >> 6) & 0x3); |  3839       __ vinss(result, 3, right, (mask_ >> 6) & 0x3); | 
|  3872       break; |  3840       break; | 
|  3873     default: UNREACHABLE(); |  3841     default: | 
 |  3842       UNREACHABLE(); | 
|  3874   } |  3843   } | 
|  3875 } |  3844 } | 
|  3876  |  3845  | 
|  3877  |  3846  | 
|  3878 LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary(Zone* zone, |  3847 LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary(Zone* zone, | 
|  3879                                                                bool opt) const { |  3848                                                                bool opt) const { | 
|  3880   const intptr_t kNumInputs = 1; |  3849   const intptr_t kNumInputs = 1; | 
|  3881   const intptr_t kNumTemps = 1; |  3850   const intptr_t kNumTemps = 1; | 
|  3882   LocationSummary* summary =  new LocationSummary( |  3851   LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, | 
|  3883       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  3852                                                  LocationSummary::kNoCall); | 
|  3884   summary->set_in(0, Location::RequiresFpuRegister()); |  3853   summary->set_in(0, Location::RequiresFpuRegister()); | 
|  3885   summary->set_temp(0, Location::RequiresRegister()); |  3854   summary->set_temp(0, Location::RequiresRegister()); | 
|  3886   summary->set_out(0, Location::RequiresRegister()); |  3855   summary->set_out(0, Location::RequiresRegister()); | 
|  3887   return summary; |  3856   return summary; | 
|  3888 } |  3857 } | 
|  3889  |  3858  | 
|  3890  |  3859  | 
|  3891 void Simd32x4GetSignMaskInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  3860 void Simd32x4GetSignMaskInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  3892   const VRegister value = locs()->in(0).fpu_reg(); |  3861   const VRegister value = locs()->in(0).fpu_reg(); | 
|  3893   const Register out = locs()->out(0).reg(); |  3862   const Register out = locs()->out(0).reg(); | 
| (...skipping 13 matching lines...) Expand all  Loading... | 
|  3907   // W lane. |  3876   // W lane. | 
|  3908   __ vmovrs(temp, value, 3); |  3877   __ vmovrs(temp, value, 3); | 
|  3909   __ LsrImmediate(temp, temp, 31); |  3878   __ LsrImmediate(temp, temp, 31); | 
|  3910   __ orr(out, out, Operand(temp, LSL, 3)); |  3879   __ orr(out, out, Operand(temp, LSL, 3)); | 
|  3911   // Tag. |  3880   // Tag. | 
|  3912   __ SmiTag(out); |  3881   __ SmiTag(out); | 
|  3913 } |  3882 } | 
|  3914  |  3883  | 
|  3915  |  3884  | 
|  3916 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( |  3885 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( | 
|  3917     Zone* zone, bool opt) const { |  3886     Zone* zone, | 
 |  3887     bool opt) const { | 
|  3918   const intptr_t kNumInputs = 4; |  3888   const intptr_t kNumInputs = 4; | 
|  3919   const intptr_t kNumTemps = 0; |  3889   const intptr_t kNumTemps = 0; | 
|  3920   LocationSummary* summary = new(zone) LocationSummary( |  3890   LocationSummary* summary = new (zone) | 
|  3921       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  3891       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  3922   summary->set_in(0, Location::RequiresFpuRegister()); |  3892   summary->set_in(0, Location::RequiresFpuRegister()); | 
|  3923   summary->set_in(1, Location::RequiresFpuRegister()); |  3893   summary->set_in(1, Location::RequiresFpuRegister()); | 
|  3924   summary->set_in(2, Location::RequiresFpuRegister()); |  3894   summary->set_in(2, Location::RequiresFpuRegister()); | 
|  3925   summary->set_in(3, Location::RequiresFpuRegister()); |  3895   summary->set_in(3, Location::RequiresFpuRegister()); | 
|  3926   summary->set_out(0, Location::RequiresFpuRegister()); |  3896   summary->set_out(0, Location::RequiresFpuRegister()); | 
|  3927   return summary; |  3897   return summary; | 
|  3928 } |  3898 } | 
|  3929  |  3899  | 
|  3930  |  3900  | 
|  3931 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  3901 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
|  3943   __ vinss(r, 2, VTMP, 0); |  3913   __ vinss(r, 2, VTMP, 0); | 
|  3944   __ fcvtsd(VTMP, v3); |  3914   __ fcvtsd(VTMP, v3); | 
|  3945   __ vinss(r, 3, VTMP, 0); |  3915   __ vinss(r, 3, VTMP, 0); | 
|  3946 } |  3916 } | 
|  3947  |  3917  | 
|  3948  |  3918  | 
|  3949 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(Zone* zone, |  3919 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(Zone* zone, | 
|  3950                                                          bool opt) const { |  3920                                                          bool opt) const { | 
|  3951   const intptr_t kNumInputs = 0; |  3921   const intptr_t kNumInputs = 0; | 
|  3952   const intptr_t kNumTemps = 0; |  3922   const intptr_t kNumTemps = 0; | 
|  3953   LocationSummary* summary = new(zone) LocationSummary( |  3923   LocationSummary* summary = new (zone) | 
|  3954       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  3924       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  3955   summary->set_out(0, Location::RequiresFpuRegister()); |  3925   summary->set_out(0, Location::RequiresFpuRegister()); | 
|  3956   return summary; |  3926   return summary; | 
|  3957 } |  3927 } | 
|  3958  |  3928  | 
|  3959  |  3929  | 
|  3960 void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  3930 void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  3961   const VRegister v = locs()->out(0).fpu_reg(); |  3931   const VRegister v = locs()->out(0).fpu_reg(); | 
|  3962   __ veor(v, v, v); |  3932   __ veor(v, v, v); | 
|  3963 } |  3933 } | 
|  3964  |  3934  | 
|  3965  |  3935  | 
|  3966 LocationSummary* Float32x4SplatInstr::MakeLocationSummary(Zone* zone, |  3936 LocationSummary* Float32x4SplatInstr::MakeLocationSummary(Zone* zone, | 
|  3967                                                           bool opt) const { |  3937                                                           bool opt) const { | 
|  3968   const intptr_t kNumInputs = 1; |  3938   const intptr_t kNumInputs = 1; | 
|  3969   const intptr_t kNumTemps = 0; |  3939   const intptr_t kNumTemps = 0; | 
|  3970   LocationSummary* summary = new(zone) LocationSummary( |  3940   LocationSummary* summary = new (zone) | 
|  3971       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  3941       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  3972   summary->set_in(0, Location::RequiresFpuRegister()); |  3942   summary->set_in(0, Location::RequiresFpuRegister()); | 
|  3973   summary->set_out(0, Location::RequiresFpuRegister()); |  3943   summary->set_out(0, Location::RequiresFpuRegister()); | 
|  3974   return summary; |  3944   return summary; | 
|  3975 } |  3945 } | 
|  3976  |  3946  | 
|  3977  |  3947  | 
|  3978 void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  3948 void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  3979   const VRegister value = locs()->in(0).fpu_reg(); |  3949   const VRegister value = locs()->in(0).fpu_reg(); | 
|  3980   const VRegister result = locs()->out(0).fpu_reg(); |  3950   const VRegister result = locs()->out(0).fpu_reg(); | 
|  3981  |  3951  | 
|  3982   // Convert to Float32. |  3952   // Convert to Float32. | 
|  3983   __ fcvtsd(VTMP, value); |  3953   __ fcvtsd(VTMP, value); | 
|  3984  |  3954  | 
|  3985   // Splat across all lanes. |  3955   // Splat across all lanes. | 
|  3986   __ vdups(result, VTMP, 0); |  3956   __ vdups(result, VTMP, 0); | 
|  3987 } |  3957 } | 
|  3988  |  3958  | 
|  3989  |  3959  | 
|  3990 LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(Zone* zone, |  3960 LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(Zone* zone, | 
|  3991                                                                bool opt) const { |  3961                                                                bool opt) const { | 
|  3992   const intptr_t kNumInputs = 2; |  3962   const intptr_t kNumInputs = 2; | 
|  3993   const intptr_t kNumTemps = 0; |  3963   const intptr_t kNumTemps = 0; | 
|  3994   LocationSummary* summary = new(zone) LocationSummary( |  3964   LocationSummary* summary = new (zone) | 
|  3995       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  3965       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  3996   summary->set_in(0, Location::RequiresFpuRegister()); |  3966   summary->set_in(0, Location::RequiresFpuRegister()); | 
|  3997   summary->set_in(1, Location::RequiresFpuRegister()); |  3967   summary->set_in(1, Location::RequiresFpuRegister()); | 
|  3998   summary->set_out(0, Location::RequiresFpuRegister()); |  3968   summary->set_out(0, Location::RequiresFpuRegister()); | 
|  3999   return summary; |  3969   return summary; | 
|  4000 } |  3970 } | 
|  4001  |  3971  | 
|  4002  |  3972  | 
|  4003 void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  3973 void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  4004   const VRegister left = locs()->in(0).fpu_reg(); |  3974   const VRegister left = locs()->in(0).fpu_reg(); | 
|  4005   const VRegister right = locs()->in(1).fpu_reg(); |  3975   const VRegister right = locs()->in(1).fpu_reg(); | 
| (...skipping 14 matching lines...) Expand all  Loading... | 
|  4020     case MethodRecognizer::kFloat32x4GreaterThanOrEqual: |  3990     case MethodRecognizer::kFloat32x4GreaterThanOrEqual: | 
|  4021       __ vcges(result, left, right); |  3991       __ vcges(result, left, right); | 
|  4022       break; |  3992       break; | 
|  4023     case MethodRecognizer::kFloat32x4LessThan: |  3993     case MethodRecognizer::kFloat32x4LessThan: | 
|  4024       __ vcgts(result, right, left); |  3994       __ vcgts(result, right, left); | 
|  4025       break; |  3995       break; | 
|  4026     case MethodRecognizer::kFloat32x4LessThanOrEqual: |  3996     case MethodRecognizer::kFloat32x4LessThanOrEqual: | 
|  4027       __ vcges(result, right, left); |  3997       __ vcges(result, right, left); | 
|  4028       break; |  3998       break; | 
|  4029  |  3999  | 
|  4030     default: UNREACHABLE(); |  4000     default: | 
 |  4001       UNREACHABLE(); | 
|  4031   } |  4002   } | 
|  4032 } |  4003 } | 
|  4033  |  4004  | 
|  4034  |  4005  | 
|  4035 LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary(Zone* zone, |  4006 LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary(Zone* zone, | 
|  4036                                                            bool opt) const { |  4007                                                            bool opt) const { | 
|  4037   const intptr_t kNumInputs = 2; |  4008   const intptr_t kNumInputs = 2; | 
|  4038   const intptr_t kNumTemps = 0; |  4009   const intptr_t kNumTemps = 0; | 
|  4039   LocationSummary* summary = new(zone) LocationSummary( |  4010   LocationSummary* summary = new (zone) | 
|  4040       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  4011       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  4041   summary->set_in(0, Location::RequiresFpuRegister()); |  4012   summary->set_in(0, Location::RequiresFpuRegister()); | 
|  4042   summary->set_in(1, Location::RequiresFpuRegister()); |  4013   summary->set_in(1, Location::RequiresFpuRegister()); | 
|  4043   summary->set_out(0, Location::RequiresFpuRegister()); |  4014   summary->set_out(0, Location::RequiresFpuRegister()); | 
|  4044   return summary; |  4015   return summary; | 
|  4045 } |  4016 } | 
|  4046  |  4017  | 
|  4047  |  4018  | 
|  4048 void Float32x4MinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  4019 void Float32x4MinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  4049   const VRegister left = locs()->in(0).fpu_reg(); |  4020   const VRegister left = locs()->in(0).fpu_reg(); | 
|  4050   const VRegister right = locs()->in(1).fpu_reg(); |  4021   const VRegister right = locs()->in(1).fpu_reg(); | 
|  4051   const VRegister result = locs()->out(0).fpu_reg(); |  4022   const VRegister result = locs()->out(0).fpu_reg(); | 
|  4052  |  4023  | 
|  4053   switch (op_kind()) { |  4024   switch (op_kind()) { | 
|  4054     case MethodRecognizer::kFloat32x4Min: |  4025     case MethodRecognizer::kFloat32x4Min: | 
|  4055       __ vmins(result, left, right); |  4026       __ vmins(result, left, right); | 
|  4056       break; |  4027       break; | 
|  4057     case MethodRecognizer::kFloat32x4Max: |  4028     case MethodRecognizer::kFloat32x4Max: | 
|  4058       __ vmaxs(result, left, right); |  4029       __ vmaxs(result, left, right); | 
|  4059       break; |  4030       break; | 
|  4060     default: UNREACHABLE(); |  4031     default: | 
 |  4032       UNREACHABLE(); | 
|  4061   } |  4033   } | 
|  4062 } |  4034 } | 
|  4063  |  4035  | 
|  4064  |  4036  | 
|  4065 LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(Zone* zone, |  4037 LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(Zone* zone, | 
|  4066                                                          bool opt) const { |  4038                                                          bool opt) const { | 
|  4067   const intptr_t kNumInputs = 1; |  4039   const intptr_t kNumInputs = 1; | 
|  4068   const intptr_t kNumTemps = 0; |  4040   const intptr_t kNumTemps = 0; | 
|  4069   LocationSummary* summary = new(zone) LocationSummary( |  4041   LocationSummary* summary = new (zone) | 
|  4070       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  4042       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  4071   summary->set_in(0, Location::RequiresFpuRegister()); |  4043   summary->set_in(0, Location::RequiresFpuRegister()); | 
|  4072   summary->set_out(0, Location::RequiresFpuRegister()); |  4044   summary->set_out(0, Location::RequiresFpuRegister()); | 
|  4073   return summary; |  4045   return summary; | 
|  4074 } |  4046 } | 
|  4075  |  4047  | 
|  4076  |  4048  | 
|  4077 void Float32x4SqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  4049 void Float32x4SqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  4078   const VRegister left = locs()->in(0).fpu_reg(); |  4050   const VRegister left = locs()->in(0).fpu_reg(); | 
|  4079   const VRegister result = locs()->out(0).fpu_reg(); |  4051   const VRegister result = locs()->out(0).fpu_reg(); | 
|  4080  |  4052  | 
|  4081   switch (op_kind()) { |  4053   switch (op_kind()) { | 
|  4082     case MethodRecognizer::kFloat32x4Sqrt: |  4054     case MethodRecognizer::kFloat32x4Sqrt: | 
|  4083       __ vsqrts(result, left); |  4055       __ vsqrts(result, left); | 
|  4084       break; |  4056       break; | 
|  4085     case MethodRecognizer::kFloat32x4Reciprocal: |  4057     case MethodRecognizer::kFloat32x4Reciprocal: | 
|  4086       __ VRecps(result, left); |  4058       __ VRecps(result, left); | 
|  4087       break; |  4059       break; | 
|  4088     case MethodRecognizer::kFloat32x4ReciprocalSqrt: |  4060     case MethodRecognizer::kFloat32x4ReciprocalSqrt: | 
|  4089       __ VRSqrts(result, left); |  4061       __ VRSqrts(result, left); | 
|  4090       break; |  4062       break; | 
|  4091     default: UNREACHABLE(); |  4063     default: | 
 |  4064       UNREACHABLE(); | 
|  4092   } |  4065   } | 
|  4093 } |  4066 } | 
|  4094  |  4067  | 
|  4095  |  4068  | 
|  4096 LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(Zone* zone, |  4069 LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(Zone* zone, | 
|  4097                                                           bool opt) const { |  4070                                                           bool opt) const { | 
|  4098   const intptr_t kNumInputs = 2; |  4071   const intptr_t kNumInputs = 2; | 
|  4099   const intptr_t kNumTemps = 0; |  4072   const intptr_t kNumTemps = 0; | 
|  4100   LocationSummary* summary = new(zone) LocationSummary( |  4073   LocationSummary* summary = new (zone) | 
|  4101       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  4074       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  4102   summary->set_in(0, Location::RequiresFpuRegister()); |  4075   summary->set_in(0, Location::RequiresFpuRegister()); | 
|  4103   summary->set_in(1, Location::RequiresFpuRegister()); |  4076   summary->set_in(1, Location::RequiresFpuRegister()); | 
|  4104   summary->set_out(0, Location::RequiresFpuRegister()); |  4077   summary->set_out(0, Location::RequiresFpuRegister()); | 
|  4105   return summary; |  4078   return summary; | 
|  4106 } |  4079 } | 
|  4107  |  4080  | 
|  4108  |  4081  | 
|  4109 void Float32x4ScaleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  4082 void Float32x4ScaleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  4110   const VRegister left = locs()->in(0).fpu_reg(); |  4083   const VRegister left = locs()->in(0).fpu_reg(); | 
|  4111   const VRegister right = locs()->in(1).fpu_reg(); |  4084   const VRegister right = locs()->in(1).fpu_reg(); | 
|  4112   const VRegister result = locs()->out(0).fpu_reg(); |  4085   const VRegister result = locs()->out(0).fpu_reg(); | 
|  4113  |  4086  | 
|  4114   switch (op_kind()) { |  4087   switch (op_kind()) { | 
|  4115     case MethodRecognizer::kFloat32x4Scale: |  4088     case MethodRecognizer::kFloat32x4Scale: | 
|  4116       __ fcvtsd(VTMP, left); |  4089       __ fcvtsd(VTMP, left); | 
|  4117       __ vdups(result, VTMP, 0); |  4090       __ vdups(result, VTMP, 0); | 
|  4118       __ vmuls(result, result, right); |  4091       __ vmuls(result, result, right); | 
|  4119       break; |  4092       break; | 
|  4120     default: UNREACHABLE(); |  4093     default: | 
 |  4094       UNREACHABLE(); | 
|  4121   } |  4095   } | 
|  4122 } |  4096 } | 
|  4123  |  4097  | 
|  4124  |  4098  | 
|  4125 LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(Zone* zone, |  4099 LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(Zone* zone, | 
|  4126                                                             bool opt) const { |  4100                                                             bool opt) const { | 
|  4127   const intptr_t kNumInputs = 1; |  4101   const intptr_t kNumInputs = 1; | 
|  4128   const intptr_t kNumTemps = 0; |  4102   const intptr_t kNumTemps = 0; | 
|  4129   LocationSummary* summary = new LocationSummary( |  4103   LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, | 
|  4130       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  4104                                                  LocationSummary::kNoCall); | 
|  4131   summary->set_in(0, Location::RequiresFpuRegister()); |  4105   summary->set_in(0, Location::RequiresFpuRegister()); | 
|  4132   summary->set_out(0, Location::RequiresFpuRegister()); |  4106   summary->set_out(0, Location::RequiresFpuRegister()); | 
|  4133   return summary; |  4107   return summary; | 
|  4134 } |  4108 } | 
|  4135  |  4109  | 
|  4136  |  4110  | 
|  4137 void Float32x4ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  4111 void Float32x4ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  4138   const VRegister left = locs()->in(0).fpu_reg(); |  4112   const VRegister left = locs()->in(0).fpu_reg(); | 
|  4139   const VRegister result = locs()->out(0).fpu_reg(); |  4113   const VRegister result = locs()->out(0).fpu_reg(); | 
|  4140  |  4114  | 
|  4141   switch (op_kind()) { |  4115   switch (op_kind()) { | 
|  4142     case MethodRecognizer::kFloat32x4Negate: |  4116     case MethodRecognizer::kFloat32x4Negate: | 
|  4143       __ vnegs(result, left); |  4117       __ vnegs(result, left); | 
|  4144       break; |  4118       break; | 
|  4145     case MethodRecognizer::kFloat32x4Absolute: |  4119     case MethodRecognizer::kFloat32x4Absolute: | 
|  4146       __ vabss(result, left); |  4120       __ vabss(result, left); | 
|  4147       break; |  4121       break; | 
|  4148     default: UNREACHABLE(); |  4122     default: | 
 |  4123       UNREACHABLE(); | 
|  4149   } |  4124   } | 
|  4150 } |  4125 } | 
|  4151  |  4126  | 
|  4152  |  4127  | 
|  4153 LocationSummary* Float32x4ClampInstr::MakeLocationSummary(Zone* zone, |  4128 LocationSummary* Float32x4ClampInstr::MakeLocationSummary(Zone* zone, | 
|  4154                                                           bool opt) const { |  4129                                                           bool opt) const { | 
|  4155   const intptr_t kNumInputs = 3; |  4130   const intptr_t kNumInputs = 3; | 
|  4156   const intptr_t kNumTemps = 0; |  4131   const intptr_t kNumTemps = 0; | 
|  4157   LocationSummary* summary = new(zone) LocationSummary( |  4132   LocationSummary* summary = new (zone) | 
|  4158       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  4133       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  4159   summary->set_in(0, Location::RequiresFpuRegister()); |  4134   summary->set_in(0, Location::RequiresFpuRegister()); | 
|  4160   summary->set_in(1, Location::RequiresFpuRegister()); |  4135   summary->set_in(1, Location::RequiresFpuRegister()); | 
|  4161   summary->set_in(2, Location::RequiresFpuRegister()); |  4136   summary->set_in(2, Location::RequiresFpuRegister()); | 
|  4162   summary->set_out(0, Location::RequiresFpuRegister()); |  4137   summary->set_out(0, Location::RequiresFpuRegister()); | 
|  4163   return summary; |  4138   return summary; | 
|  4164 } |  4139 } | 
|  4165  |  4140  | 
|  4166  |  4141  | 
|  4167 void Float32x4ClampInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  4142 void Float32x4ClampInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  4168   const VRegister left = locs()->in(0).fpu_reg(); |  4143   const VRegister left = locs()->in(0).fpu_reg(); | 
|  4169   const VRegister lower = locs()->in(1).fpu_reg(); |  4144   const VRegister lower = locs()->in(1).fpu_reg(); | 
|  4170   const VRegister upper = locs()->in(2).fpu_reg(); |  4145   const VRegister upper = locs()->in(2).fpu_reg(); | 
|  4171   const VRegister result = locs()->out(0).fpu_reg(); |  4146   const VRegister result = locs()->out(0).fpu_reg(); | 
|  4172   __ vmins(result, left, upper); |  4147   __ vmins(result, left, upper); | 
|  4173   __ vmaxs(result, result, lower); |  4148   __ vmaxs(result, result, lower); | 
|  4174 } |  4149 } | 
|  4175  |  4150  | 
|  4176  |  4151  | 
|  4177 LocationSummary* Float32x4WithInstr::MakeLocationSummary(Zone* zone, |  4152 LocationSummary* Float32x4WithInstr::MakeLocationSummary(Zone* zone, | 
|  4178                                                          bool opt) const { |  4153                                                          bool opt) const { | 
|  4179   const intptr_t kNumInputs = 2; |  4154   const intptr_t kNumInputs = 2; | 
|  4180   const intptr_t kNumTemps = 0; |  4155   const intptr_t kNumTemps = 0; | 
|  4181   LocationSummary* summary = new LocationSummary( |  4156   LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, | 
|  4182       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  4157                                                  LocationSummary::kNoCall); | 
|  4183   summary->set_in(0, Location::RequiresFpuRegister()); |  4158   summary->set_in(0, Location::RequiresFpuRegister()); | 
|  4184   summary->set_in(1, Location::RequiresFpuRegister()); |  4159   summary->set_in(1, Location::RequiresFpuRegister()); | 
|  4185   summary->set_out(0, Location::RequiresFpuRegister()); |  4160   summary->set_out(0, Location::RequiresFpuRegister()); | 
|  4186   return summary; |  4161   return summary; | 
|  4187 } |  4162 } | 
|  4188  |  4163  | 
|  4189  |  4164  | 
|  4190 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  4165 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  4191   const VRegister replacement = locs()->in(0).fpu_reg(); |  4166   const VRegister replacement = locs()->in(0).fpu_reg(); | 
|  4192   const VRegister value = locs()->in(1).fpu_reg(); |  4167   const VRegister value = locs()->in(1).fpu_reg(); | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
|  4203       break; |  4178       break; | 
|  4204     case MethodRecognizer::kFloat32x4WithY: |  4179     case MethodRecognizer::kFloat32x4WithY: | 
|  4205       __ vinss(result, 1, VTMP, 0); |  4180       __ vinss(result, 1, VTMP, 0); | 
|  4206       break; |  4181       break; | 
|  4207     case MethodRecognizer::kFloat32x4WithZ: |  4182     case MethodRecognizer::kFloat32x4WithZ: | 
|  4208       __ vinss(result, 2, VTMP, 0); |  4183       __ vinss(result, 2, VTMP, 0); | 
|  4209       break; |  4184       break; | 
|  4210     case MethodRecognizer::kFloat32x4WithW: |  4185     case MethodRecognizer::kFloat32x4WithW: | 
|  4211       __ vinss(result, 3, VTMP, 0); |  4186       __ vinss(result, 3, VTMP, 0); | 
|  4212       break; |  4187       break; | 
|  4213     default: UNREACHABLE(); |  4188     default: | 
 |  4189       UNREACHABLE(); | 
|  4214   } |  4190   } | 
|  4215 } |  4191 } | 
|  4216  |  4192  | 
|  4217  |  4193  | 
|  4218 LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(Zone* zone, |  4194 LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(Zone* zone, | 
|  4219                                                               bool opt) const { |  4195                                                               bool opt) const { | 
|  4220   const intptr_t kNumInputs = 1; |  4196   const intptr_t kNumInputs = 1; | 
|  4221   const intptr_t kNumTemps = 0; |  4197   const intptr_t kNumTemps = 0; | 
|  4222   LocationSummary* summary = new LocationSummary( |  4198   LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, | 
|  4223       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  4199                                                  LocationSummary::kNoCall); | 
|  4224   summary->set_in(0, Location::RequiresFpuRegister()); |  4200   summary->set_in(0, Location::RequiresFpuRegister()); | 
|  4225   summary->set_out(0, Location::RequiresFpuRegister()); |  4201   summary->set_out(0, Location::RequiresFpuRegister()); | 
|  4226   return summary; |  4202   return summary; | 
|  4227 } |  4203 } | 
|  4228  |  4204  | 
|  4229  |  4205  | 
|  4230 void Float32x4ToInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |  4206 void Float32x4ToInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  4231   const VRegister value = locs()->in(0).fpu_reg(); |  4207   const VRegister value = locs()->in(0).fpu_reg(); | 
|  4232   const VRegister result = locs()->out(0).fpu_reg(); |  4208   const VRegister result = locs()->out(0).fpu_reg(); | 
|  4233  |  4209  | 
|  4234   if (value != result) { |  4210   if (value != result) { | 
|  4235     __ vmov(result, value); |  4211     __ vmov(result, value); | 
|  4236   } |  4212   } | 
|  4237 } |  4213 } | 
|  4238  |  4214  | 
|  4239  |  4215  | 
|  4240 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(Zone* zone, |  4216 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(Zone* zone, | 
|  4241                                                            bool opt) const { |  4217                                                            bool opt) const { | 
|  4242   const intptr_t kNumInputs = 1; |  4218   const intptr_t kNumInputs = 1; | 
|  4243   const intptr_t kNumTemps = 0; |  4219   const intptr_t kNumTemps = 0; | 
|  4244   LocationSummary* summary = new(zone) LocationSummary( |  4220   LocationSummary* summary = new (zone) | 
|  4245       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  4221       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  4246   summary->set_in(0, Location::RequiresFpuRegister()); |  4222   summary->set_in(0, Location::RequiresFpuRegister()); | 
|  4247   summary->set_out(0, Location::RequiresFpuRegister()); |  4223   summary->set_out(0, Location::RequiresFpuRegister()); | 
|  4248   return summary; |  4224   return summary; | 
|  4249 } |  4225 } | 
|  4250  |  4226  | 
|  4251  |  4227  | 
|  4252 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  4228 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  4253   const VRegister value = locs()->in(0).fpu_reg(); |  4229   const VRegister value = locs()->in(0).fpu_reg(); | 
|  4254   const VRegister result = locs()->out(0).fpu_reg(); |  4230   const VRegister result = locs()->out(0).fpu_reg(); | 
|  4255  |  4231  | 
|  4256   switch (op_kind()) { |  4232   switch (op_kind()) { | 
|  4257     case MethodRecognizer::kFloat64x2GetX: |  4233     case MethodRecognizer::kFloat64x2GetX: | 
|  4258       __ vinsd(result, 0, value, 0); |  4234       __ vinsd(result, 0, value, 0); | 
|  4259       break; |  4235       break; | 
|  4260     case MethodRecognizer::kFloat64x2GetY: |  4236     case MethodRecognizer::kFloat64x2GetY: | 
|  4261       __ vinsd(result, 0, value, 1); |  4237       __ vinsd(result, 0, value, 1); | 
|  4262       break; |  4238       break; | 
|  4263     default: UNREACHABLE(); |  4239     default: | 
 |  4240       UNREACHABLE(); | 
|  4264   } |  4241   } | 
|  4265 } |  4242 } | 
|  4266  |  4243  | 
|  4267  |  4244  | 
|  4268 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(Zone* zone, |  4245 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(Zone* zone, | 
|  4269                                                          bool opt) const { |  4246                                                          bool opt) const { | 
|  4270   const intptr_t kNumInputs = 0; |  4247   const intptr_t kNumInputs = 0; | 
|  4271   const intptr_t kNumTemps = 0; |  4248   const intptr_t kNumTemps = 0; | 
|  4272   LocationSummary* summary = new(zone) LocationSummary( |  4249   LocationSummary* summary = new (zone) | 
|  4273       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  4250       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  4274   summary->set_out(0, Location::RequiresFpuRegister()); |  4251   summary->set_out(0, Location::RequiresFpuRegister()); | 
|  4275   return summary; |  4252   return summary; | 
|  4276 } |  4253 } | 
|  4277  |  4254  | 
|  4278  |  4255  | 
|  4279 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  4256 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  4280   const VRegister v = locs()->out(0).fpu_reg(); |  4257   const VRegister v = locs()->out(0).fpu_reg(); | 
|  4281   __ veor(v, v, v); |  4258   __ veor(v, v, v); | 
|  4282 } |  4259 } | 
|  4283  |  4260  | 
|  4284  |  4261  | 
|  4285 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(Zone* zone, |  4262 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(Zone* zone, | 
|  4286                                                           bool opt) const { |  4263                                                           bool opt) const { | 
|  4287   const intptr_t kNumInputs = 1; |  4264   const intptr_t kNumInputs = 1; | 
|  4288   const intptr_t kNumTemps = 0; |  4265   const intptr_t kNumTemps = 0; | 
|  4289   LocationSummary* summary = new(zone) LocationSummary( |  4266   LocationSummary* summary = new (zone) | 
|  4290       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  4267       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  4291   summary->set_in(0, Location::RequiresFpuRegister()); |  4268   summary->set_in(0, Location::RequiresFpuRegister()); | 
|  4292   summary->set_out(0, Location::RequiresFpuRegister()); |  4269   summary->set_out(0, Location::RequiresFpuRegister()); | 
|  4293   return summary; |  4270   return summary; | 
|  4294 } |  4271 } | 
|  4295  |  4272  | 
|  4296  |  4273  | 
|  4297 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  4274 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  4298   const VRegister value = locs()->in(0).fpu_reg(); |  4275   const VRegister value = locs()->in(0).fpu_reg(); | 
|  4299   const VRegister result = locs()->out(0).fpu_reg(); |  4276   const VRegister result = locs()->out(0).fpu_reg(); | 
|  4300   __ vdupd(result, value, 0); |  4277   __ vdupd(result, value, 0); | 
|  4301 } |  4278 } | 
|  4302  |  4279  | 
|  4303  |  4280  | 
|  4304 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary( |  4281 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary( | 
|  4305     Zone* zone, bool opt) const { |  4282     Zone* zone, | 
 |  4283     bool opt) const { | 
|  4306   const intptr_t kNumInputs = 2; |  4284   const intptr_t kNumInputs = 2; | 
|  4307   const intptr_t kNumTemps = 0; |  4285   const intptr_t kNumTemps = 0; | 
|  4308   LocationSummary* summary = new(zone) LocationSummary( |  4286   LocationSummary* summary = new (zone) | 
|  4309       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  4287       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  4310   summary->set_in(0, Location::RequiresFpuRegister()); |  4288   summary->set_in(0, Location::RequiresFpuRegister()); | 
|  4311   summary->set_in(1, Location::RequiresFpuRegister()); |  4289   summary->set_in(1, Location::RequiresFpuRegister()); | 
|  4312   summary->set_out(0, Location::RequiresFpuRegister()); |  4290   summary->set_out(0, Location::RequiresFpuRegister()); | 
|  4313   return summary; |  4291   return summary; | 
|  4314 } |  4292 } | 
|  4315  |  4293  | 
|  4316  |  4294  | 
|  4317 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  4295 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  4318   const VRegister v0 = locs()->in(0).fpu_reg(); |  4296   const VRegister v0 = locs()->in(0).fpu_reg(); | 
|  4319   const VRegister v1 = locs()->in(1).fpu_reg(); |  4297   const VRegister v1 = locs()->in(1).fpu_reg(); | 
|  4320   const VRegister r = locs()->out(0).fpu_reg(); |  4298   const VRegister r = locs()->out(0).fpu_reg(); | 
|  4321   __ vinsd(r, 0, v0, 0); |  4299   __ vinsd(r, 0, v0, 0); | 
|  4322   __ vinsd(r, 1, v1, 0); |  4300   __ vinsd(r, 1, v1, 0); | 
|  4323 } |  4301 } | 
|  4324  |  4302  | 
|  4325  |  4303  | 
|  4326 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary( |  4304 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary( | 
|  4327     Zone* zone, bool opt) const { |  4305     Zone* zone, | 
 |  4306     bool opt) const { | 
|  4328   const intptr_t kNumInputs = 1; |  4307   const intptr_t kNumInputs = 1; | 
|  4329   const intptr_t kNumTemps = 0; |  4308   const intptr_t kNumTemps = 0; | 
|  4330   LocationSummary* summary = new LocationSummary( |  4309   LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, | 
|  4331       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  4310                                                  LocationSummary::kNoCall); | 
|  4332   summary->set_in(0, Location::RequiresFpuRegister()); |  4311   summary->set_in(0, Location::RequiresFpuRegister()); | 
|  4333   summary->set_out(0, Location::RequiresFpuRegister()); |  4312   summary->set_out(0, Location::RequiresFpuRegister()); | 
|  4334   return summary; |  4313   return summary; | 
|  4335 } |  4314 } | 
|  4336  |  4315  | 
|  4337  |  4316  | 
|  4338 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |  4317 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  4339   const VRegister q = locs()->in(0).fpu_reg(); |  4318   const VRegister q = locs()->in(0).fpu_reg(); | 
|  4340   const VRegister r = locs()->out(0).fpu_reg(); |  4319   const VRegister r = locs()->out(0).fpu_reg(); | 
|  4341  |  4320  | 
|  4342   // Zero register. |  4321   // Zero register. | 
|  4343   __ veor(r, r, r); |  4322   __ veor(r, r, r); | 
|  4344   // Set X lane. |  4323   // Set X lane. | 
|  4345   __ vinsd(VTMP, 0, q, 0); |  4324   __ vinsd(VTMP, 0, q, 0); | 
|  4346   __ fcvtsd(VTMP, VTMP); |  4325   __ fcvtsd(VTMP, VTMP); | 
|  4347   __ vinss(r, 0, VTMP, 0); |  4326   __ vinss(r, 0, VTMP, 0); | 
|  4348   // Set Y lane. |  4327   // Set Y lane. | 
|  4349   __ vinsd(VTMP, 0, q, 1); |  4328   __ vinsd(VTMP, 0, q, 1); | 
|  4350   __ fcvtsd(VTMP, VTMP); |  4329   __ fcvtsd(VTMP, VTMP); | 
|  4351   __ vinss(r, 1, VTMP, 0); |  4330   __ vinss(r, 1, VTMP, 0); | 
|  4352 } |  4331 } | 
|  4353  |  4332  | 
|  4354  |  4333  | 
|  4355 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary( |  4334 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary( | 
|  4356     Zone* zone, bool opt) const { |  4335     Zone* zone, | 
 |  4336     bool opt) const { | 
|  4357   const intptr_t kNumInputs = 1; |  4337   const intptr_t kNumInputs = 1; | 
|  4358   const intptr_t kNumTemps = 0; |  4338   const intptr_t kNumTemps = 0; | 
|  4359   LocationSummary* summary = new LocationSummary( |  4339   LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, | 
|  4360       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  4340                                                  LocationSummary::kNoCall); | 
|  4361   summary->set_in(0, Location::RequiresFpuRegister()); |  4341   summary->set_in(0, Location::RequiresFpuRegister()); | 
|  4362   summary->set_out(0, Location::RequiresFpuRegister()); |  4342   summary->set_out(0, Location::RequiresFpuRegister()); | 
|  4363   return summary; |  4343   return summary; | 
|  4364 } |  4344 } | 
|  4365  |  4345  | 
|  4366  |  4346  | 
|  4367 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |  4347 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  4368   const VRegister q = locs()->in(0).fpu_reg(); |  4348   const VRegister q = locs()->in(0).fpu_reg(); | 
|  4369   const VRegister r = locs()->out(0).fpu_reg(); |  4349   const VRegister r = locs()->out(0).fpu_reg(); | 
|  4370  |  4350  | 
|  4371   // Set X. |  4351   // Set X. | 
|  4372   __ vinss(VTMP, 0, q, 0); |  4352   __ vinss(VTMP, 0, q, 0); | 
|  4373   __ fcvtds(VTMP, VTMP); |  4353   __ fcvtds(VTMP, VTMP); | 
|  4374   __ vinsd(r, 0, VTMP, 0); |  4354   __ vinsd(r, 0, VTMP, 0); | 
|  4375   // Set Y. |  4355   // Set Y. | 
|  4376   __ vinss(VTMP, 0, q, 1); |  4356   __ vinss(VTMP, 0, q, 1); | 
|  4377   __ fcvtds(VTMP, VTMP); |  4357   __ fcvtds(VTMP, VTMP); | 
|  4378   __ vinsd(r, 1, VTMP, 0); |  4358   __ vinsd(r, 1, VTMP, 0); | 
|  4379 } |  4359 } | 
|  4380  |  4360  | 
|  4381  |  4361  | 
|  4382 LocationSummary* Float64x2ZeroArgInstr::MakeLocationSummary(Zone* zone, |  4362 LocationSummary* Float64x2ZeroArgInstr::MakeLocationSummary(Zone* zone, | 
|  4383                                                             bool opt) const { |  4363                                                             bool opt) const { | 
|  4384   const intptr_t kNumInputs = 1; |  4364   const intptr_t kNumInputs = 1; | 
|  4385   const intptr_t kNumTemps = 0; |  4365   const intptr_t kNumTemps = 0; | 
|  4386   LocationSummary* summary = new(zone) LocationSummary( |  4366   LocationSummary* summary = new (zone) | 
|  4387       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  4367       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  4388  |  4368  | 
|  4389   if (representation() == kTagged) { |  4369   if (representation() == kTagged) { | 
|  4390     ASSERT(op_kind() == MethodRecognizer::kFloat64x2GetSignMask); |  4370     ASSERT(op_kind() == MethodRecognizer::kFloat64x2GetSignMask); | 
|  4391     summary->set_in(0, Location::RequiresFpuRegister()); |  4371     summary->set_in(0, Location::RequiresFpuRegister()); | 
|  4392     summary->set_out(0, Location::RequiresRegister()); |  4372     summary->set_out(0, Location::RequiresRegister()); | 
|  4393   } else { |  4373   } else { | 
|  4394     summary->set_in(0, Location::RequiresFpuRegister()); |  4374     summary->set_in(0, Location::RequiresFpuRegister()); | 
|  4395     summary->set_out(0, Location::RequiresFpuRegister()); |  4375     summary->set_out(0, Location::RequiresFpuRegister()); | 
|  4396   } |  4376   } | 
|  4397   return summary; |  4377   return summary; | 
| (...skipping 23 matching lines...) Expand all  Loading... | 
|  4421   switch (op_kind()) { |  4401   switch (op_kind()) { | 
|  4422     case MethodRecognizer::kFloat64x2Negate: |  4402     case MethodRecognizer::kFloat64x2Negate: | 
|  4423       __ vnegd(result, value); |  4403       __ vnegd(result, value); | 
|  4424       break; |  4404       break; | 
|  4425     case MethodRecognizer::kFloat64x2Abs: |  4405     case MethodRecognizer::kFloat64x2Abs: | 
|  4426       __ vabsd(result, value); |  4406       __ vabsd(result, value); | 
|  4427       break; |  4407       break; | 
|  4428     case MethodRecognizer::kFloat64x2Sqrt: |  4408     case MethodRecognizer::kFloat64x2Sqrt: | 
|  4429       __ vsqrtd(result, value); |  4409       __ vsqrtd(result, value); | 
|  4430       break; |  4410       break; | 
|  4431     default: UNREACHABLE(); |  4411     default: | 
 |  4412       UNREACHABLE(); | 
|  4432   } |  4413   } | 
|  4433 } |  4414 } | 
|  4434  |  4415  | 
|  4435  |  4416  | 
|  4436 LocationSummary* Float64x2OneArgInstr::MakeLocationSummary(Zone* zone, |  4417 LocationSummary* Float64x2OneArgInstr::MakeLocationSummary(Zone* zone, | 
|  4437                                                            bool opt) const { |  4418                                                            bool opt) const { | 
|  4438   const intptr_t kNumInputs = 2; |  4419   const intptr_t kNumInputs = 2; | 
|  4439   const intptr_t kNumTemps = 0; |  4420   const intptr_t kNumTemps = 0; | 
|  4440   LocationSummary* summary = new LocationSummary( |  4421   LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, | 
|  4441       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  4422                                                  LocationSummary::kNoCall); | 
|  4442   summary->set_in(0, Location::RequiresFpuRegister()); |  4423   summary->set_in(0, Location::RequiresFpuRegister()); | 
|  4443   summary->set_in(1, Location::RequiresFpuRegister()); |  4424   summary->set_in(1, Location::RequiresFpuRegister()); | 
|  4444   summary->set_out(0, Location::SameAsFirstInput()); |  4425   summary->set_out(0, Location::SameAsFirstInput()); | 
|  4445   return summary; |  4426   return summary; | 
|  4446 } |  4427 } | 
|  4447  |  4428  | 
|  4448  |  4429  | 
|  4449 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  4430 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  4450   const VRegister left = locs()->in(0).fpu_reg(); |  4431   const VRegister left = locs()->in(0).fpu_reg(); | 
|  4451   const VRegister right = locs()->in(1).fpu_reg(); |  4432   const VRegister right = locs()->in(1).fpu_reg(); | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
|  4462       break; |  4443       break; | 
|  4463     case MethodRecognizer::kFloat64x2WithY: |  4444     case MethodRecognizer::kFloat64x2WithY: | 
|  4464       __ vinsd(out, 1, right, 0); |  4445       __ vinsd(out, 1, right, 0); | 
|  4465       break; |  4446       break; | 
|  4466     case MethodRecognizer::kFloat64x2Min: |  4447     case MethodRecognizer::kFloat64x2Min: | 
|  4467       __ vmind(out, left, right); |  4448       __ vmind(out, left, right); | 
|  4468       break; |  4449       break; | 
|  4469     case MethodRecognizer::kFloat64x2Max: |  4450     case MethodRecognizer::kFloat64x2Max: | 
|  4470       __ vmaxd(out, left, right); |  4451       __ vmaxd(out, left, right); | 
|  4471       break; |  4452       break; | 
|  4472     default: UNREACHABLE(); |  4453     default: | 
 |  4454       UNREACHABLE(); | 
|  4473   } |  4455   } | 
|  4474 } |  4456 } | 
|  4475  |  4457  | 
|  4476  |  4458  | 
|  4477 LocationSummary* Int32x4ConstructorInstr::MakeLocationSummary( |  4459 LocationSummary* Int32x4ConstructorInstr::MakeLocationSummary(Zone* zone, | 
|  4478     Zone* zone, bool opt) const { |  4460                                                               bool opt) const { | 
|  4479   const intptr_t kNumInputs = 4; |  4461   const intptr_t kNumInputs = 4; | 
|  4480   const intptr_t kNumTemps = 0; |  4462   const intptr_t kNumTemps = 0; | 
|  4481   LocationSummary* summary = new(zone) LocationSummary( |  4463   LocationSummary* summary = new (zone) | 
|  4482       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  4464       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  4483   summary->set_in(0, Location::RequiresRegister()); |  4465   summary->set_in(0, Location::RequiresRegister()); | 
|  4484   summary->set_in(1, Location::RequiresRegister()); |  4466   summary->set_in(1, Location::RequiresRegister()); | 
|  4485   summary->set_in(2, Location::RequiresRegister()); |  4467   summary->set_in(2, Location::RequiresRegister()); | 
|  4486   summary->set_in(3, Location::RequiresRegister()); |  4468   summary->set_in(3, Location::RequiresRegister()); | 
|  4487   summary->set_out(0, Location::RequiresFpuRegister()); |  4469   summary->set_out(0, Location::RequiresFpuRegister()); | 
|  4488   return summary; |  4470   return summary; | 
|  4489 } |  4471 } | 
|  4490  |  4472  | 
|  4491  |  4473  | 
|  4492 void Int32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  4474 void Int32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  4493   const Register v0 = locs()->in(0).reg(); |  4475   const Register v0 = locs()->in(0).reg(); | 
|  4494   const Register v1 = locs()->in(1).reg(); |  4476   const Register v1 = locs()->in(1).reg(); | 
|  4495   const Register v2 = locs()->in(2).reg(); |  4477   const Register v2 = locs()->in(2).reg(); | 
|  4496   const Register v3 = locs()->in(3).reg(); |  4478   const Register v3 = locs()->in(3).reg(); | 
|  4497   const VRegister result = locs()->out(0).fpu_reg(); |  4479   const VRegister result = locs()->out(0).fpu_reg(); | 
|  4498   __ veor(result, result, result); |  4480   __ veor(result, result, result); | 
|  4499   __ vinsw(result, 0, v0); |  4481   __ vinsw(result, 0, v0); | 
|  4500   __ vinsw(result, 1, v1); |  4482   __ vinsw(result, 1, v1); | 
|  4501   __ vinsw(result, 2, v2); |  4483   __ vinsw(result, 2, v2); | 
|  4502   __ vinsw(result, 3, v3); |  4484   __ vinsw(result, 3, v3); | 
|  4503 } |  4485 } | 
|  4504  |  4486  | 
|  4505  |  4487  | 
|  4506 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary( |  4488 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary( | 
|  4507     Zone* zone, bool opt) const { |  4489     Zone* zone, | 
 |  4490     bool opt) const { | 
|  4508   const intptr_t kNumInputs = 4; |  4491   const intptr_t kNumInputs = 4; | 
|  4509   const intptr_t kNumTemps = 1; |  4492   const intptr_t kNumTemps = 1; | 
|  4510   LocationSummary* summary = new LocationSummary( |  4493   LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, | 
|  4511       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  4494                                                  LocationSummary::kNoCall); | 
|  4512   summary->set_in(0, Location::RequiresRegister()); |  4495   summary->set_in(0, Location::RequiresRegister()); | 
|  4513   summary->set_in(1, Location::RequiresRegister()); |  4496   summary->set_in(1, Location::RequiresRegister()); | 
|  4514   summary->set_in(2, Location::RequiresRegister()); |  4497   summary->set_in(2, Location::RequiresRegister()); | 
|  4515   summary->set_in(3, Location::RequiresRegister()); |  4498   summary->set_in(3, Location::RequiresRegister()); | 
|  4516   summary->set_temp(0, Location::RequiresRegister()); |  4499   summary->set_temp(0, Location::RequiresRegister()); | 
|  4517   summary->set_out(0, Location::RequiresFpuRegister()); |  4500   summary->set_out(0, Location::RequiresFpuRegister()); | 
|  4518   return summary; |  4501   return summary; | 
|  4519 } |  4502 } | 
|  4520  |  4503  | 
|  4521  |  4504  | 
| (...skipping 28 matching lines...) Expand all  Loading... | 
|  4550   __ CompareRegisters(v3, TMP2); |  4533   __ CompareRegisters(v3, TMP2); | 
|  4551   __ csel(TMP, temp, ZR, EQ); |  4534   __ csel(TMP, temp, ZR, EQ); | 
|  4552   __ vinsw(result, 3, TMP); |  4535   __ vinsw(result, 3, TMP); | 
|  4553 } |  4536 } | 
|  4554  |  4537  | 
|  4555  |  4538  | 
|  4556 LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(Zone* zone, |  4539 LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(Zone* zone, | 
|  4557                                                           bool opt) const { |  4540                                                           bool opt) const { | 
|  4558   const intptr_t kNumInputs = 1; |  4541   const intptr_t kNumInputs = 1; | 
|  4559   const intptr_t kNumTemps = 0; |  4542   const intptr_t kNumTemps = 0; | 
|  4560   LocationSummary* summary = new LocationSummary( |  4543   LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, | 
|  4561       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  4544                                                  LocationSummary::kNoCall); | 
|  4562   summary->set_in(0, Location::RequiresFpuRegister()); |  4545   summary->set_in(0, Location::RequiresFpuRegister()); | 
|  4563   summary->set_out(0, Location::RequiresRegister()); |  4546   summary->set_out(0, Location::RequiresRegister()); | 
|  4564   return summary; |  4547   return summary; | 
|  4565 } |  4548 } | 
|  4566  |  4549  | 
|  4567  |  4550  | 
|  4568 void Int32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  4551 void Int32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  4569   const VRegister value = locs()->in(0).fpu_reg(); |  4552   const VRegister value = locs()->in(0).fpu_reg(); | 
|  4570   const Register result = locs()->out(0).reg(); |  4553   const Register result = locs()->out(0).reg(); | 
|  4571  |  4554  | 
|  4572   switch (op_kind()) { |  4555   switch (op_kind()) { | 
|  4573     case MethodRecognizer::kInt32x4GetFlagX: |  4556     case MethodRecognizer::kInt32x4GetFlagX: | 
|  4574       __ vmovrs(result, value, 0); |  4557       __ vmovrs(result, value, 0); | 
|  4575       break; |  4558       break; | 
|  4576     case MethodRecognizer::kInt32x4GetFlagY: |  4559     case MethodRecognizer::kInt32x4GetFlagY: | 
|  4577       __ vmovrs(result, value, 1); |  4560       __ vmovrs(result, value, 1); | 
|  4578       break; |  4561       break; | 
|  4579     case MethodRecognizer::kInt32x4GetFlagZ: |  4562     case MethodRecognizer::kInt32x4GetFlagZ: | 
|  4580       __ vmovrs(result, value, 2); |  4563       __ vmovrs(result, value, 2); | 
|  4581       break; |  4564       break; | 
|  4582     case MethodRecognizer::kInt32x4GetFlagW: |  4565     case MethodRecognizer::kInt32x4GetFlagW: | 
|  4583       __ vmovrs(result, value, 3); |  4566       __ vmovrs(result, value, 3); | 
|  4584       break; |  4567       break; | 
|  4585     default: UNREACHABLE(); |  4568     default: | 
 |  4569       UNREACHABLE(); | 
|  4586   } |  4570   } | 
|  4587  |  4571  | 
|  4588   __ tst(result, Operand(result)); |  4572   __ tst(result, Operand(result)); | 
|  4589   __ LoadObject(result, Bool::True()); |  4573   __ LoadObject(result, Bool::True()); | 
|  4590   __ LoadObject(TMP, Bool::False()); |  4574   __ LoadObject(TMP, Bool::False()); | 
|  4591   __ csel(result, TMP, result, EQ); |  4575   __ csel(result, TMP, result, EQ); | 
|  4592 } |  4576 } | 
|  4593  |  4577  | 
|  4594  |  4578  | 
|  4595 LocationSummary* Int32x4SelectInstr::MakeLocationSummary(Zone* zone, |  4579 LocationSummary* Int32x4SelectInstr::MakeLocationSummary(Zone* zone, | 
|  4596                                                          bool opt) const { |  4580                                                          bool opt) const { | 
|  4597   const intptr_t kNumInputs = 3; |  4581   const intptr_t kNumInputs = 3; | 
|  4598   const intptr_t kNumTemps = 1; |  4582   const intptr_t kNumTemps = 1; | 
|  4599   LocationSummary* summary = new LocationSummary( |  4583   LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, | 
|  4600       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  4584                                                  LocationSummary::kNoCall); | 
|  4601   summary->set_in(0, Location::RequiresFpuRegister()); |  4585   summary->set_in(0, Location::RequiresFpuRegister()); | 
|  4602   summary->set_in(1, Location::RequiresFpuRegister()); |  4586   summary->set_in(1, Location::RequiresFpuRegister()); | 
|  4603   summary->set_in(2, Location::RequiresFpuRegister()); |  4587   summary->set_in(2, Location::RequiresFpuRegister()); | 
|  4604   summary->set_temp(0, Location::RequiresFpuRegister()); |  4588   summary->set_temp(0, Location::RequiresFpuRegister()); | 
|  4605   summary->set_out(0, Location::RequiresFpuRegister()); |  4589   summary->set_out(0, Location::RequiresFpuRegister()); | 
|  4606   return summary; |  4590   return summary; | 
|  4607 } |  4591 } | 
|  4608  |  4592  | 
|  4609  |  4593  | 
|  4610 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  4594 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
| (...skipping 13 matching lines...) Expand all  Loading... | 
|  4624   __ vand(temp, temp, falseValue); |  4608   __ vand(temp, temp, falseValue); | 
|  4625   // out = mask | temp. |  4609   // out = mask | temp. | 
|  4626   __ vorr(out, mask, temp); |  4610   __ vorr(out, mask, temp); | 
|  4627 } |  4611 } | 
|  4628  |  4612  | 
|  4629  |  4613  | 
|  4630 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(Zone* zone, |  4614 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(Zone* zone, | 
|  4631                                                           bool opt) const { |  4615                                                           bool opt) const { | 
|  4632   const intptr_t kNumInputs = 2; |  4616   const intptr_t kNumInputs = 2; | 
|  4633   const intptr_t kNumTemps = 0; |  4617   const intptr_t kNumTemps = 0; | 
|  4634   LocationSummary* summary = new LocationSummary( |  4618   LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, | 
|  4635       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  4619                                                  LocationSummary::kNoCall); | 
|  4636   summary->set_in(0, Location::RequiresFpuRegister()); |  4620   summary->set_in(0, Location::RequiresFpuRegister()); | 
|  4637   summary->set_in(1, Location::RequiresRegister()); |  4621   summary->set_in(1, Location::RequiresRegister()); | 
|  4638   summary->set_out(0, Location::RequiresFpuRegister()); |  4622   summary->set_out(0, Location::RequiresFpuRegister()); | 
|  4639   return summary; |  4623   return summary; | 
|  4640 } |  4624 } | 
|  4641  |  4625  | 
|  4642  |  4626  | 
|  4643 void Int32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  4627 void Int32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  4644   const VRegister mask = locs()->in(0).fpu_reg(); |  4628   const VRegister mask = locs()->in(0).fpu_reg(); | 
|  4645   const Register flag = locs()->in(1).reg(); |  4629   const Register flag = locs()->in(1).reg(); | 
| (...skipping 12 matching lines...) Expand all  Loading... | 
|  4658       break; |  4642       break; | 
|  4659     case MethodRecognizer::kInt32x4WithFlagY: |  4643     case MethodRecognizer::kInt32x4WithFlagY: | 
|  4660       __ vinsw(result, 1, TMP); |  4644       __ vinsw(result, 1, TMP); | 
|  4661       break; |  4645       break; | 
|  4662     case MethodRecognizer::kInt32x4WithFlagZ: |  4646     case MethodRecognizer::kInt32x4WithFlagZ: | 
|  4663       __ vinsw(result, 2, TMP); |  4647       __ vinsw(result, 2, TMP); | 
|  4664       break; |  4648       break; | 
|  4665     case MethodRecognizer::kInt32x4WithFlagW: |  4649     case MethodRecognizer::kInt32x4WithFlagW: | 
|  4666       __ vinsw(result, 3, TMP); |  4650       __ vinsw(result, 3, TMP); | 
|  4667       break; |  4651       break; | 
|  4668     default: UNREACHABLE(); |  4652     default: | 
 |  4653       UNREACHABLE(); | 
|  4669   } |  4654   } | 
|  4670 } |  4655 } | 
|  4671  |  4656  | 
|  4672  |  4657  | 
|  4673 LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(Zone* zone, |  4658 LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(Zone* zone, | 
|  4674                                                               bool opt) const { |  4659                                                               bool opt) const { | 
|  4675   const intptr_t kNumInputs = 1; |  4660   const intptr_t kNumInputs = 1; | 
|  4676   const intptr_t kNumTemps = 0; |  4661   const intptr_t kNumTemps = 0; | 
|  4677   LocationSummary* summary = new LocationSummary( |  4662   LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, | 
|  4678       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  4663                                                  LocationSummary::kNoCall); | 
|  4679   summary->set_in(0, Location::RequiresFpuRegister()); |  4664   summary->set_in(0, Location::RequiresFpuRegister()); | 
|  4680   summary->set_out(0, Location::RequiresFpuRegister()); |  4665   summary->set_out(0, Location::RequiresFpuRegister()); | 
|  4681   return summary; |  4666   return summary; | 
|  4682 } |  4667 } | 
|  4683  |  4668  | 
|  4684  |  4669  | 
|  4685 void Int32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |  4670 void Int32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  4686   const VRegister value = locs()->in(0).fpu_reg(); |  4671   const VRegister value = locs()->in(0).fpu_reg(); | 
|  4687   const VRegister result = locs()->out(0).fpu_reg(); |  4672   const VRegister result = locs()->out(0).fpu_reg(); | 
|  4688  |  4673  | 
|  4689   if (value != result) { |  4674   if (value != result) { | 
|  4690     __ vmov(result, value); |  4675     __ vmov(result, value); | 
|  4691   } |  4676   } | 
|  4692 } |  4677 } | 
|  4693  |  4678  | 
|  4694  |  4679  | 
|  4695 LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(Zone* zone, |  4680 LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(Zone* zone, | 
|  4696                                                            bool opt) const { |  4681                                                            bool opt) const { | 
|  4697   const intptr_t kNumInputs = 2; |  4682   const intptr_t kNumInputs = 2; | 
|  4698   const intptr_t kNumTemps = 0; |  4683   const intptr_t kNumTemps = 0; | 
|  4699   LocationSummary* summary = new LocationSummary( |  4684   LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, | 
|  4700       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  4685                                                  LocationSummary::kNoCall); | 
|  4701   summary->set_in(0, Location::RequiresFpuRegister()); |  4686   summary->set_in(0, Location::RequiresFpuRegister()); | 
|  4702   summary->set_in(1, Location::RequiresFpuRegister()); |  4687   summary->set_in(1, Location::RequiresFpuRegister()); | 
|  4703   summary->set_out(0, Location::RequiresFpuRegister()); |  4688   summary->set_out(0, Location::RequiresFpuRegister()); | 
|  4704   return summary; |  4689   return summary; | 
|  4705 } |  4690 } | 
|  4706  |  4691  | 
|  4707  |  4692  | 
|  4708 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  4693 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  4709   const VRegister left = locs()->in(0).fpu_reg(); |  4694   const VRegister left = locs()->in(0).fpu_reg(); | 
|  4710   const VRegister right = locs()->in(1).fpu_reg(); |  4695   const VRegister right = locs()->in(1).fpu_reg(); | 
|  4711   const VRegister result = locs()->out(0).fpu_reg(); |  4696   const VRegister result = locs()->out(0).fpu_reg(); | 
|  4712   switch (op_kind()) { |  4697   switch (op_kind()) { | 
|  4713     case Token::kBIT_AND: __ vand(result, left, right); break; |  4698     case Token::kBIT_AND: | 
|  4714     case Token::kBIT_OR: __ vorr(result, left, right); break; |  4699       __ vand(result, left, right); | 
|  4715     case Token::kBIT_XOR: __ veor(result, left, right); break; |  4700       break; | 
|  4716     case Token::kADD: __ vaddw(result, left, right); break; |  4701     case Token::kBIT_OR: | 
|  4717     case Token::kSUB: __ vsubw(result, left, right); break; |  4702       __ vorr(result, left, right); | 
|  4718     default: UNREACHABLE(); |  4703       break; | 
 |  4704     case Token::kBIT_XOR: | 
 |  4705       __ veor(result, left, right); | 
 |  4706       break; | 
 |  4707     case Token::kADD: | 
 |  4708       __ vaddw(result, left, right); | 
 |  4709       break; | 
 |  4710     case Token::kSUB: | 
 |  4711       __ vsubw(result, left, right); | 
 |  4712       break; | 
 |  4713     default: | 
 |  4714       UNREACHABLE(); | 
|  4719   } |  4715   } | 
|  4720 } |  4716 } | 
|  4721  |  4717  | 
|  4722  |  4718  | 
|  4723 LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone, |  4719 LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone, | 
|  4724                                                      bool opt) const { |  4720                                                      bool opt) const { | 
|  4725   ASSERT((kind() == MathUnaryInstr::kSqrt) || |  4721   ASSERT((kind() == MathUnaryInstr::kSqrt) || | 
|  4726          (kind() == MathUnaryInstr::kDoubleSquare)); |  4722          (kind() == MathUnaryInstr::kDoubleSquare)); | 
|  4727   const intptr_t kNumInputs = 1; |  4723   const intptr_t kNumInputs = 1; | 
|  4728   const intptr_t kNumTemps = 0; |  4724   const intptr_t kNumTemps = 0; | 
|  4729   LocationSummary* summary = new(zone) LocationSummary( |  4725   LocationSummary* summary = new (zone) | 
|  4730       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  4726       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  4731   summary->set_in(0, Location::RequiresFpuRegister()); |  4727   summary->set_in(0, Location::RequiresFpuRegister()); | 
|  4732   summary->set_out(0, Location::RequiresFpuRegister()); |  4728   summary->set_out(0, Location::RequiresFpuRegister()); | 
|  4733   return summary; |  4729   return summary; | 
|  4734 } |  4730 } | 
|  4735  |  4731  | 
|  4736  |  4732  | 
|  4737 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  4733 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  4738   if (kind() == MathUnaryInstr::kSqrt) { |  4734   if (kind() == MathUnaryInstr::kSqrt) { | 
|  4739     const VRegister val = locs()->in(0).fpu_reg(); |  4735     const VRegister val = locs()->in(0).fpu_reg(); | 
|  4740     const VRegister result = locs()->out(0).fpu_reg(); |  4736     const VRegister result = locs()->out(0).fpu_reg(); | 
|  4741     __ fsqrtd(result, val); |  4737     __ fsqrtd(result, val); | 
|  4742   } else if (kind() == MathUnaryInstr::kDoubleSquare) { |  4738   } else if (kind() == MathUnaryInstr::kDoubleSquare) { | 
|  4743     const VRegister val = locs()->in(0).fpu_reg(); |  4739     const VRegister val = locs()->in(0).fpu_reg(); | 
|  4744     const VRegister result = locs()->out(0).fpu_reg(); |  4740     const VRegister result = locs()->out(0).fpu_reg(); | 
|  4745     __ fmuld(result, val, val); |  4741     __ fmuld(result, val, val); | 
|  4746   } else { |  4742   } else { | 
|  4747     UNREACHABLE(); |  4743     UNREACHABLE(); | 
|  4748   } |  4744   } | 
|  4749 } |  4745 } | 
|  4750  |  4746  | 
|  4751  |  4747  | 
|  4752 LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary( |  4748 LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary( | 
|  4753     Zone* zone, bool opt) const { |  4749     Zone* zone, | 
 |  4750     bool opt) const { | 
|  4754   const intptr_t kNumTemps = 0; |  4751   const intptr_t kNumTemps = 0; | 
|  4755   LocationSummary* summary = new(zone) LocationSummary( |  4752   LocationSummary* summary = new (zone) | 
|  4756       zone, InputCount(), kNumTemps, LocationSummary::kCall); |  4753       LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); | 
|  4757   summary->set_in(0, Location::RegisterLocation(R0)); |  4754   summary->set_in(0, Location::RegisterLocation(R0)); | 
|  4758   summary->set_in(1, Location::RegisterLocation(R1)); |  4755   summary->set_in(1, Location::RegisterLocation(R1)); | 
|  4759   summary->set_in(2, Location::RegisterLocation(R2)); |  4756   summary->set_in(2, Location::RegisterLocation(R2)); | 
|  4760   summary->set_in(3, Location::RegisterLocation(R3)); |  4757   summary->set_in(3, Location::RegisterLocation(R3)); | 
|  4761   summary->set_out(0, Location::RegisterLocation(R0)); |  4758   summary->set_out(0, Location::RegisterLocation(R0)); | 
|  4762   return summary; |  4759   return summary; | 
|  4763 } |  4760 } | 
|  4764  |  4761  | 
|  4765  |  4762  | 
|  4766 void CaseInsensitiveCompareUC16Instr::EmitNativeCode( |  4763 void CaseInsensitiveCompareUC16Instr::EmitNativeCode( | 
|  4767     FlowGraphCompiler* compiler) { |  4764     FlowGraphCompiler* compiler) { | 
|  4768  |  | 
|  4769   // Call the function. |  4765   // Call the function. | 
|  4770   __ CallRuntime(TargetFunction(), TargetFunction().argument_count()); |  4766   __ CallRuntime(TargetFunction(), TargetFunction().argument_count()); | 
|  4771 } |  4767 } | 
|  4772  |  4768  | 
|  4773  |  4769  | 
|  4774 LocationSummary* MathMinMaxInstr::MakeLocationSummary(Zone* zone, |  4770 LocationSummary* MathMinMaxInstr::MakeLocationSummary(Zone* zone, | 
|  4775                                                       bool opt) const { |  4771                                                       bool opt) const { | 
|  4776   if (result_cid() == kDoubleCid) { |  4772   if (result_cid() == kDoubleCid) { | 
|  4777     const intptr_t kNumInputs = 2; |  4773     const intptr_t kNumInputs = 2; | 
|  4778     const intptr_t kNumTemps = 0; |  4774     const intptr_t kNumTemps = 0; | 
|  4779     LocationSummary* summary = new(zone) LocationSummary( |  4775     LocationSummary* summary = new (zone) | 
|  4780         zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  4776         LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  4781     summary->set_in(0, Location::RequiresFpuRegister()); |  4777     summary->set_in(0, Location::RequiresFpuRegister()); | 
|  4782     summary->set_in(1, Location::RequiresFpuRegister()); |  4778     summary->set_in(1, Location::RequiresFpuRegister()); | 
|  4783     // Reuse the left register so that code can be made shorter. |  4779     // Reuse the left register so that code can be made shorter. | 
|  4784     summary->set_out(0, Location::SameAsFirstInput()); |  4780     summary->set_out(0, Location::SameAsFirstInput()); | 
|  4785     return summary; |  4781     return summary; | 
|  4786   } |  4782   } | 
|  4787   ASSERT(result_cid() == kSmiCid); |  4783   ASSERT(result_cid() == kSmiCid); | 
|  4788   const intptr_t kNumInputs = 2; |  4784   const intptr_t kNumInputs = 2; | 
|  4789   const intptr_t kNumTemps = 0; |  4785   const intptr_t kNumTemps = 0; | 
|  4790   LocationSummary* summary = new(zone) LocationSummary( |  4786   LocationSummary* summary = new (zone) | 
|  4791       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  4787       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  4792   summary->set_in(0, Location::RequiresRegister()); |  4788   summary->set_in(0, Location::RequiresRegister()); | 
|  4793   summary->set_in(1, Location::RequiresRegister()); |  4789   summary->set_in(1, Location::RequiresRegister()); | 
|  4794   // Reuse the left register so that code can be made shorter. |  4790   // Reuse the left register so that code can be made shorter. | 
|  4795   summary->set_out(0, Location::SameAsFirstInput()); |  4791   summary->set_out(0, Location::SameAsFirstInput()); | 
|  4796   return summary; |  4792   return summary; | 
|  4797 } |  4793 } | 
|  4798  |  4794  | 
|  4799  |  4795  | 
|  4800 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  4796 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  4801   ASSERT((op_kind() == MethodRecognizer::kMathMin) || |  4797   ASSERT((op_kind() == MethodRecognizer::kMathMin) || | 
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  4854   } else { |  4850   } else { | 
|  4855     __ csel(result, right, left, LT); |  4851     __ csel(result, right, left, LT); | 
|  4856   } |  4852   } | 
|  4857 } |  4853 } | 
|  4858  |  4854  | 
|  4859  |  4855  | 
|  4860 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(Zone* zone, |  4856 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(Zone* zone, | 
|  4861                                                       bool opt) const { |  4857                                                       bool opt) const { | 
|  4862   const intptr_t kNumInputs = 1; |  4858   const intptr_t kNumInputs = 1; | 
|  4863   const intptr_t kNumTemps = 0; |  4859   const intptr_t kNumTemps = 0; | 
|  4864   LocationSummary* summary = new(zone) LocationSummary( |  4860   LocationSummary* summary = new (zone) | 
|  4865       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  4861       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  4866   summary->set_in(0, Location::RequiresRegister()); |  4862   summary->set_in(0, Location::RequiresRegister()); | 
|  4867   // We make use of 3-operand instructions by not requiring result register |  4863   // We make use of 3-operand instructions by not requiring result register | 
|  4868   // to be identical to first input register as on Intel. |  4864   // to be identical to first input register as on Intel. | 
|  4869   summary->set_out(0, Location::RequiresRegister()); |  4865   summary->set_out(0, Location::RequiresRegister()); | 
|  4870   return summary; |  4866   return summary; | 
|  4871 } |  4867 } | 
|  4872  |  4868  | 
|  4873  |  4869  | 
|  4874 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  4870 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  4875   const Register value = locs()->in(0).reg(); |  4871   const Register value = locs()->in(0).reg(); | 
| (...skipping 13 matching lines...) Expand all  Loading... | 
|  4889     default: |  4885     default: | 
|  4890       UNREACHABLE(); |  4886       UNREACHABLE(); | 
|  4891   } |  4887   } | 
|  4892 } |  4888 } | 
|  4893  |  4889  | 
|  4894  |  4890  | 
|  4895 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, |  4891 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, | 
|  4896                                                          bool opt) const { |  4892                                                          bool opt) const { | 
|  4897   const intptr_t kNumInputs = 1; |  4893   const intptr_t kNumInputs = 1; | 
|  4898   const intptr_t kNumTemps = 0; |  4894   const intptr_t kNumTemps = 0; | 
|  4899   LocationSummary* summary = new(zone) LocationSummary( |  4895   LocationSummary* summary = new (zone) | 
|  4900       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  4896       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  4901   summary->set_in(0, Location::RequiresFpuRegister()); |  4897   summary->set_in(0, Location::RequiresFpuRegister()); | 
|  4902   summary->set_out(0, Location::RequiresFpuRegister()); |  4898   summary->set_out(0, Location::RequiresFpuRegister()); | 
|  4903   return summary; |  4899   return summary; | 
|  4904 } |  4900 } | 
|  4905  |  4901  | 
|  4906  |  4902  | 
|  4907 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  4903 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  4908   const VRegister result = locs()->out(0).fpu_reg(); |  4904   const VRegister result = locs()->out(0).fpu_reg(); | 
|  4909   const VRegister value = locs()->in(0).fpu_reg(); |  4905   const VRegister value = locs()->in(0).fpu_reg(); | 
|  4910   __ fnegd(result, value); |  4906   __ fnegd(result, value); | 
|  4911 } |  4907 } | 
|  4912  |  4908  | 
|  4913  |  4909  | 
|  4914 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone, |  4910 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone, | 
|  4915                                                        bool opt) const { |  4911                                                          bool opt) const { | 
|  4916   const intptr_t kNumInputs = 1; |  4912   const intptr_t kNumInputs = 1; | 
|  4917   const intptr_t kNumTemps = 0; |  4913   const intptr_t kNumTemps = 0; | 
|  4918   LocationSummary* result = new(zone) LocationSummary( |  4914   LocationSummary* result = new (zone) | 
|  4919       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  4915       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  4920   result->set_in(0, Location::RequiresRegister()); |  4916   result->set_in(0, Location::RequiresRegister()); | 
|  4921   result->set_out(0, Location::RequiresFpuRegister()); |  4917   result->set_out(0, Location::RequiresFpuRegister()); | 
|  4922   return result; |  4918   return result; | 
|  4923 } |  4919 } | 
|  4924  |  4920  | 
|  4925  |  4921  | 
|  4926 void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  4922 void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  4927   const Register value = locs()->in(0).reg(); |  4923   const Register value = locs()->in(0).reg(); | 
|  4928   const VRegister result = locs()->out(0).fpu_reg(); |  4924   const VRegister result = locs()->out(0).fpu_reg(); | 
|  4929   __ scvtfdw(result, value); |  4925   __ scvtfdw(result, value); | 
|  4930 } |  4926 } | 
|  4931  |  4927  | 
|  4932  |  4928  | 
|  4933 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Zone* zone, |  4929 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Zone* zone, | 
|  4934                                                        bool opt) const { |  4930                                                        bool opt) const { | 
|  4935   const intptr_t kNumInputs = 1; |  4931   const intptr_t kNumInputs = 1; | 
|  4936   const intptr_t kNumTemps = 0; |  4932   const intptr_t kNumTemps = 0; | 
|  4937   LocationSummary* result = new(zone) LocationSummary( |  4933   LocationSummary* result = new (zone) | 
|  4938       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  4934       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  4939   result->set_in(0, Location::RequiresRegister()); |  4935   result->set_in(0, Location::RequiresRegister()); | 
|  4940   result->set_out(0, Location::RequiresFpuRegister()); |  4936   result->set_out(0, Location::RequiresFpuRegister()); | 
|  4941   return result; |  4937   return result; | 
|  4942 } |  4938 } | 
|  4943  |  4939  | 
|  4944  |  4940  | 
|  4945 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  4941 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  4946   const Register value = locs()->in(0).reg(); |  4942   const Register value = locs()->in(0).reg(); | 
|  4947   const VRegister result = locs()->out(0).fpu_reg(); |  4943   const VRegister result = locs()->out(0).fpu_reg(); | 
|  4948   __ SmiUntag(TMP, value); |  4944   __ SmiUntag(TMP, value); | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
|  4959  |  4955  | 
|  4960 void MintToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  4956 void MintToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  4961   UNIMPLEMENTED(); |  4957   UNIMPLEMENTED(); | 
|  4962 } |  4958 } | 
|  4963  |  4959  | 
|  4964  |  4960  | 
|  4965 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Zone* zone, |  4961 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Zone* zone, | 
|  4966                                                            bool opt) const { |  4962                                                            bool opt) const { | 
|  4967   const intptr_t kNumInputs = 1; |  4963   const intptr_t kNumInputs = 1; | 
|  4968   const intptr_t kNumTemps = 0; |  4964   const intptr_t kNumTemps = 0; | 
|  4969   LocationSummary* result = new(zone) LocationSummary( |  4965   LocationSummary* result = new (zone) | 
|  4970       zone, kNumInputs, kNumTemps, LocationSummary::kCall); |  4966       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 
|  4971   result->set_in(0, Location::RegisterLocation(R1)); |  4967   result->set_in(0, Location::RegisterLocation(R1)); | 
|  4972   result->set_out(0, Location::RegisterLocation(R0)); |  4968   result->set_out(0, Location::RegisterLocation(R0)); | 
|  4973   return result; |  4969   return result; | 
|  4974 } |  4970 } | 
|  4975  |  4971  | 
|  4976  |  4972  | 
|  4977 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  4973 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  4978   const Register result = locs()->out(0).reg(); |  4974   const Register result = locs()->out(0).reg(); | 
|  4979   const Register value_obj = locs()->in(0).reg(); |  4975   const Register value_obj = locs()->in(0).reg(); | 
|  4980   ASSERT(result == R0); |  4976   ASSERT(result == R0); | 
| (...skipping 15 matching lines...) Expand all  Loading... | 
|  4996   __ SmiTag(result); |  4992   __ SmiTag(result); | 
|  4997   __ b(&done); |  4993   __ b(&done); | 
|  4998   __ Bind(&do_call); |  4994   __ Bind(&do_call); | 
|  4999   __ Push(value_obj); |  4995   __ Push(value_obj); | 
|  5000   ASSERT(instance_call()->HasICData()); |  4996   ASSERT(instance_call()->HasICData()); | 
|  5001   const ICData& ic_data = *instance_call()->ic_data(); |  4997   const ICData& ic_data = *instance_call()->ic_data(); | 
|  5002   ASSERT((ic_data.NumberOfChecks() == 1)); |  4998   ASSERT((ic_data.NumberOfChecks() == 1)); | 
|  5003   const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); |  4999   const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); | 
|  5004  |  5000  | 
|  5005   const intptr_t kNumberOfArguments = 1; |  5001   const intptr_t kNumberOfArguments = 1; | 
|  5006   compiler->GenerateStaticCall(deopt_id(), |  5002   compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), target, | 
|  5007                                instance_call()->token_pos(), |  | 
|  5008                                target, |  | 
|  5009                                kNumberOfArguments, |  5003                                kNumberOfArguments, | 
|  5010                                Object::null_array(),  // No argument names., |  5004                                Object::null_array(),  // No argument names., | 
|  5011                                locs(), |  5005                                locs(), ICData::Handle()); | 
|  5012                                ICData::Handle()); |  | 
|  5013   __ Bind(&done); |  5006   __ Bind(&done); | 
|  5014 } |  5007 } | 
|  5015  |  5008  | 
|  5016  |  5009  | 
|  5017 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone, |  5010 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone, | 
|  5018                                                        bool opt) const { |  5011                                                        bool opt) const { | 
|  5019   const intptr_t kNumInputs = 1; |  5012   const intptr_t kNumInputs = 1; | 
|  5020   const intptr_t kNumTemps = 0; |  5013   const intptr_t kNumTemps = 0; | 
|  5021   LocationSummary* result = new(zone) LocationSummary( |  5014   LocationSummary* result = new (zone) | 
|  5022       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  5015       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  5023   result->set_in(0, Location::RequiresFpuRegister()); |  5016   result->set_in(0, Location::RequiresFpuRegister()); | 
|  5024   result->set_out(0, Location::RequiresRegister()); |  5017   result->set_out(0, Location::RequiresRegister()); | 
|  5025   return result; |  5018   return result; | 
|  5026 } |  5019 } | 
|  5027  |  5020  | 
|  5028  |  5021  | 
|  5029 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  5022 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  5030   Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi); |  5023   Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi); | 
|  5031   const Register result = locs()->out(0).reg(); |  5024   const Register result = locs()->out(0).reg(); | 
|  5032   const VRegister value = locs()->in(0).fpu_reg(); |  5025   const VRegister value = locs()->in(0).fpu_reg(); | 
| (...skipping 20 matching lines...) Expand all  Loading... | 
|  5053  |  5046  | 
|  5054 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  5047 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  5055   UNIMPLEMENTED(); |  5048   UNIMPLEMENTED(); | 
|  5056 } |  5049 } | 
|  5057  |  5050  | 
|  5058  |  5051  | 
|  5059 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone, |  5052 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone, | 
|  5060                                                          bool opt) const { |  5053                                                          bool opt) const { | 
|  5061   const intptr_t kNumInputs = 1; |  5054   const intptr_t kNumInputs = 1; | 
|  5062   const intptr_t kNumTemps = 0; |  5055   const intptr_t kNumTemps = 0; | 
|  5063   LocationSummary* result = new(zone) LocationSummary( |  5056   LocationSummary* result = new (zone) | 
|  5064       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  5057       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  5065   result->set_in(0, Location::RequiresFpuRegister()); |  5058   result->set_in(0, Location::RequiresFpuRegister()); | 
|  5066   result->set_out(0, Location::RequiresFpuRegister()); |  5059   result->set_out(0, Location::RequiresFpuRegister()); | 
|  5067   return result; |  5060   return result; | 
|  5068 } |  5061 } | 
|  5069  |  5062  | 
|  5070  |  5063  | 
|  5071 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  5064 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  5072   const VRegister value = locs()->in(0).fpu_reg(); |  5065   const VRegister value = locs()->in(0).fpu_reg(); | 
|  5073   const VRegister result = locs()->out(0).fpu_reg(); |  5066   const VRegister result = locs()->out(0).fpu_reg(); | 
|  5074   __ fcvtsd(result, value); |  5067   __ fcvtsd(result, value); | 
|  5075 } |  5068 } | 
|  5076  |  5069  | 
|  5077  |  5070  | 
|  5078 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(Zone* zone, |  5071 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(Zone* zone, | 
|  5079                                                          bool opt) const { |  5072                                                          bool opt) const { | 
|  5080   const intptr_t kNumInputs = 1; |  5073   const intptr_t kNumInputs = 1; | 
|  5081   const intptr_t kNumTemps = 0; |  5074   const intptr_t kNumTemps = 0; | 
|  5082   LocationSummary* result = new(zone) LocationSummary( |  5075   LocationSummary* result = new (zone) | 
|  5083       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  5076       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  5084   result->set_in(0, Location::RequiresFpuRegister()); |  5077   result->set_in(0, Location::RequiresFpuRegister()); | 
|  5085   result->set_out(0, Location::RequiresFpuRegister()); |  5078   result->set_out(0, Location::RequiresFpuRegister()); | 
|  5086   return result; |  5079   return result; | 
|  5087 } |  5080 } | 
|  5088  |  5081  | 
|  5089  |  5082  | 
|  5090 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  5083 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  5091   const VRegister value = locs()->in(0).fpu_reg(); |  5084   const VRegister value = locs()->in(0).fpu_reg(); | 
|  5092   const VRegister result = locs()->out(0).fpu_reg(); |  5085   const VRegister result = locs()->out(0).fpu_reg(); | 
|  5093   __ fcvtds(result, value); |  5086   __ fcvtds(result, value); | 
|  5094 } |  5087 } | 
|  5095  |  5088  | 
|  5096  |  5089  | 
|  5097 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone, |  5090 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone, | 
|  5098                                                                bool opt) const { |  5091                                                                bool opt) const { | 
|  5099   ASSERT((InputCount() == 1) || (InputCount() == 2)); |  5092   ASSERT((InputCount() == 1) || (InputCount() == 2)); | 
|  5100   const intptr_t kNumTemps = |  5093   const intptr_t kNumTemps = | 
|  5101       (recognized_kind() == MethodRecognizer::kMathDoublePow) ? 1 : 0; |  5094       (recognized_kind() == MethodRecognizer::kMathDoublePow) ? 1 : 0; | 
|  5102   LocationSummary* result = new(zone) LocationSummary( |  5095   LocationSummary* result = new (zone) | 
|  5103       zone, InputCount(), kNumTemps, LocationSummary::kCall); |  5096       LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); | 
|  5104   result->set_in(0, Location::FpuRegisterLocation(V0)); |  5097   result->set_in(0, Location::FpuRegisterLocation(V0)); | 
|  5105   if (InputCount() == 2) { |  5098   if (InputCount() == 2) { | 
|  5106     result->set_in(1, Location::FpuRegisterLocation(V1)); |  5099     result->set_in(1, Location::FpuRegisterLocation(V1)); | 
|  5107   } |  5100   } | 
|  5108   if (recognized_kind() == MethodRecognizer::kMathDoublePow) { |  5101   if (recognized_kind() == MethodRecognizer::kMathDoublePow) { | 
|  5109     result->set_temp(0, Location::FpuRegisterLocation(V30)); |  5102     result->set_temp(0, Location::FpuRegisterLocation(V30)); | 
|  5110   } |  5103   } | 
|  5111   result->set_out(0, Location::FpuRegisterLocation(V0)); |  5104   result->set_out(0, Location::FpuRegisterLocation(V0)); | 
|  5112   return result; |  5105   return result; | 
|  5113 } |  5106 } | 
| (...skipping 26 matching lines...) Expand all  Loading... | 
|  5140   const VRegister result = locs->out(0).fpu_reg(); |  5133   const VRegister result = locs->out(0).fpu_reg(); | 
|  5141   const VRegister saved_base = locs->temp(0).fpu_reg(); |  5134   const VRegister saved_base = locs->temp(0).fpu_reg(); | 
|  5142   ASSERT((base == result) && (result != saved_base)); |  5135   ASSERT((base == result) && (result != saved_base)); | 
|  5143  |  5136  | 
|  5144   Label skip_call, try_sqrt, check_base, return_nan, do_pow; |  5137   Label skip_call, try_sqrt, check_base, return_nan, do_pow; | 
|  5145   __ fmovdd(saved_base, base); |  5138   __ fmovdd(saved_base, base); | 
|  5146   __ LoadDImmediate(result, 1.0); |  5139   __ LoadDImmediate(result, 1.0); | 
|  5147   // exponent == 0.0 -> return 1.0; |  5140   // exponent == 0.0 -> return 1.0; | 
|  5148   __ fcmpdz(exp); |  5141   __ fcmpdz(exp); | 
|  5149   __ b(&check_base, VS);  // NaN -> check base. |  5142   __ b(&check_base, VS);  // NaN -> check base. | 
|  5150   __ b(&skip_call, EQ);  // exp is 0.0, result is 1.0. |  5143   __ b(&skip_call, EQ);   // exp is 0.0, result is 1.0. | 
|  5151  |  5144  | 
|  5152   // exponent == 1.0 ? |  5145   // exponent == 1.0 ? | 
|  5153   __ fcmpd(exp, result); |  5146   __ fcmpd(exp, result); | 
|  5154   Label return_base; |  5147   Label return_base; | 
|  5155   __ b(&return_base, EQ); |  5148   __ b(&return_base, EQ); | 
|  5156  |  5149  | 
|  5157   // exponent == 2.0 ? |  5150   // exponent == 2.0 ? | 
|  5158   __ LoadDImmediate(VTMP, 2.0); |  5151   __ LoadDImmediate(VTMP, 2.0); | 
|  5159   __ fcmpd(exp, VTMP); |  5152   __ fcmpd(exp, VTMP); | 
|  5160   Label return_base_times_2; |  5153   Label return_base_times_2; | 
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  5233   } |  5226   } | 
|  5234   __ CallRuntime(TargetFunction(), InputCount()); |  5227   __ CallRuntime(TargetFunction(), InputCount()); | 
|  5235 } |  5228 } | 
|  5236  |  5229  | 
|  5237  |  5230  | 
|  5238 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(Zone* zone, |  5231 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(Zone* zone, | 
|  5239                                                             bool opt) const { |  5232                                                             bool opt) const { | 
|  5240   // Only use this instruction in optimized code. |  5233   // Only use this instruction in optimized code. | 
|  5241   ASSERT(opt); |  5234   ASSERT(opt); | 
|  5242   const intptr_t kNumInputs = 1; |  5235   const intptr_t kNumInputs = 1; | 
|  5243   LocationSummary* summary = new(zone) LocationSummary( |  5236   LocationSummary* summary = | 
|  5244       zone, kNumInputs, 0, LocationSummary::kNoCall); |  5237       new (zone) LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); | 
|  5245   if (representation() == kUnboxedDouble) { |  5238   if (representation() == kUnboxedDouble) { | 
|  5246     if (index() == 0) { |  5239     if (index() == 0) { | 
|  5247       summary->set_in(0, Location::Pair(Location::RequiresFpuRegister(), |  5240       summary->set_in( | 
|  5248                                         Location::Any())); |  5241           0, Location::Pair(Location::RequiresFpuRegister(), Location::Any())); | 
|  5249     } else { |  5242     } else { | 
|  5250       ASSERT(index() == 1); |  5243       ASSERT(index() == 1); | 
|  5251       summary->set_in(0, Location::Pair(Location::Any(), |  5244       summary->set_in( | 
|  5252                                         Location::RequiresFpuRegister())); |  5245           0, Location::Pair(Location::Any(), Location::RequiresFpuRegister())); | 
|  5253     } |  5246     } | 
|  5254     summary->set_out(0, Location::RequiresFpuRegister()); |  5247     summary->set_out(0, Location::RequiresFpuRegister()); | 
|  5255   } else { |  5248   } else { | 
|  5256     ASSERT(representation() == kTagged); |  5249     ASSERT(representation() == kTagged); | 
|  5257     if (index() == 0) { |  5250     if (index() == 0) { | 
|  5258       summary->set_in(0, Location::Pair(Location::RequiresRegister(), |  5251       summary->set_in( | 
|  5259                                         Location::Any())); |  5252           0, Location::Pair(Location::RequiresRegister(), Location::Any())); | 
|  5260     } else { |  5253     } else { | 
|  5261       ASSERT(index() == 1); |  5254       ASSERT(index() == 1); | 
|  5262       summary->set_in(0, Location::Pair(Location::Any(), |  5255       summary->set_in( | 
|  5263                                         Location::RequiresRegister())); |  5256           0, Location::Pair(Location::Any(), Location::RequiresRegister())); | 
|  5264     } |  5257     } | 
|  5265     summary->set_out(0, Location::RequiresRegister()); |  5258     summary->set_out(0, Location::RequiresRegister()); | 
|  5266   } |  5259   } | 
|  5267   return summary; |  5260   return summary; | 
|  5268 } |  5261 } | 
|  5269  |  5262  | 
|  5270  |  5263  | 
|  5271 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  5264 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  5272   ASSERT(locs()->in(0).IsPairLocation()); |  5265   ASSERT(locs()->in(0).IsPairLocation()); | 
|  5273   PairLocation* pair = locs()->in(0).AsPairLocation(); |  5266   PairLocation* pair = locs()->in(0).AsPairLocation(); | 
|  5274   Location in_loc = pair->At(index()); |  5267   Location in_loc = pair->At(index()); | 
|  5275   if (representation() == kUnboxedDouble) { |  5268   if (representation() == kUnboxedDouble) { | 
|  5276     const VRegister out = locs()->out(0).fpu_reg(); |  5269     const VRegister out = locs()->out(0).fpu_reg(); | 
|  5277     const VRegister in = in_loc.fpu_reg(); |  5270     const VRegister in = in_loc.fpu_reg(); | 
|  5278     __ fmovdd(out, in); |  5271     __ fmovdd(out, in); | 
|  5279   } else { |  5272   } else { | 
|  5280     ASSERT(representation() == kTagged); |  5273     ASSERT(representation() == kTagged); | 
|  5281     const Register out = locs()->out(0).reg(); |  5274     const Register out = locs()->out(0).reg(); | 
|  5282     const Register in = in_loc.reg(); |  5275     const Register in = in_loc.reg(); | 
|  5283     __ mov(out, in); |  5276     __ mov(out, in); | 
|  5284   } |  5277   } | 
|  5285 } |  5278 } | 
|  5286  |  5279  | 
|  5287  |  5280  | 
|  5288 LocationSummary* MergedMathInstr::MakeLocationSummary(Zone* zone, |  5281 LocationSummary* MergedMathInstr::MakeLocationSummary(Zone* zone, | 
|  5289                                                       bool opt) const { |  5282                                                       bool opt) const { | 
|  5290   if (kind() == MergedMathInstr::kTruncDivMod) { |  5283   if (kind() == MergedMathInstr::kTruncDivMod) { | 
|  5291     const intptr_t kNumInputs = 2; |  5284     const intptr_t kNumInputs = 2; | 
|  5292     const intptr_t kNumTemps = 0; |  5285     const intptr_t kNumTemps = 0; | 
|  5293     LocationSummary* summary = new(zone) LocationSummary( |  5286     LocationSummary* summary = new (zone) | 
|  5294         zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  5287         LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  5295     summary->set_in(0, Location::RequiresRegister()); |  5288     summary->set_in(0, Location::RequiresRegister()); | 
|  5296     summary->set_in(1, Location::RequiresRegister()); |  5289     summary->set_in(1, Location::RequiresRegister()); | 
|  5297     // Output is a pair of registers. |  5290     // Output is a pair of registers. | 
|  5298     summary->set_out(0, Location::Pair(Location::RequiresRegister(), |  5291     summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 
|  5299                                        Location::RequiresRegister())); |  5292                                        Location::RequiresRegister())); | 
|  5300     return summary; |  5293     return summary; | 
|  5301   } |  5294   } | 
|  5302   UNIMPLEMENTED(); |  5295   UNIMPLEMENTED(); | 
|  5303   return NULL; |  5296   return NULL; | 
|  5304 } |  5297 } | 
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  5357     return; |  5350     return; | 
|  5358   } |  5351   } | 
|  5359   if (kind() == MergedMathInstr::kSinCos) { |  5352   if (kind() == MergedMathInstr::kSinCos) { | 
|  5360     UNIMPLEMENTED(); |  5353     UNIMPLEMENTED(); | 
|  5361   } |  5354   } | 
|  5362   UNIMPLEMENTED(); |  5355   UNIMPLEMENTED(); | 
|  5363 } |  5356 } | 
|  5364  |  5357  | 
|  5365  |  5358  | 
|  5366 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( |  5359 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( | 
|  5367     Zone* zone, bool opt) const { |  5360     Zone* zone, | 
 |  5361     bool opt) const { | 
|  5368   return MakeCallSummary(zone); |  5362   return MakeCallSummary(zone); | 
|  5369 } |  5363 } | 
|  5370  |  5364  | 
|  5371  |  5365  | 
|  5372 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, |  5366 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 
|  5373                                                   bool opt) const { |  | 
|  5374   comparison()->InitializeLocationSummary(zone, opt); |  5367   comparison()->InitializeLocationSummary(zone, opt); | 
|  5375   // Branches don't produce a result. |  5368   // Branches don't produce a result. | 
|  5376   comparison()->locs()->set_out(0, Location::NoLocation()); |  5369   comparison()->locs()->set_out(0, Location::NoLocation()); | 
|  5377   return comparison()->locs(); |  5370   return comparison()->locs(); | 
|  5378 } |  5371 } | 
|  5379  |  5372  | 
|  5380  |  5373  | 
|  5381 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  5374 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  5382   comparison()->EmitBranchCode(compiler, this); |  5375   comparison()->EmitBranchCode(compiler, this); | 
|  5383 } |  5376 } | 
|  5384  |  5377  | 
|  5385  |  5378  | 
|  5386 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone, |  5379 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone, | 
|  5387                                                       bool opt) const { |  5380                                                       bool opt) const { | 
|  5388   const intptr_t kNumInputs = 1; |  5381   const intptr_t kNumInputs = 1; | 
|  5389   const bool need_mask_temp = IsDenseSwitch() && !IsDenseMask(ComputeCidMask()); |  5382   const bool need_mask_temp = IsDenseSwitch() && !IsDenseMask(ComputeCidMask()); | 
|  5390   const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0; |  5383   const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0; | 
|  5391   LocationSummary* summary = new(zone) LocationSummary( |  5384   LocationSummary* summary = new (zone) | 
|  5392       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  5385       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  5393   summary->set_in(0, Location::RequiresRegister()); |  5386   summary->set_in(0, Location::RequiresRegister()); | 
|  5394   if (!IsNullCheck()) { |  5387   if (!IsNullCheck()) { | 
|  5395     summary->set_temp(0, Location::RequiresRegister()); |  5388     summary->set_temp(0, Location::RequiresRegister()); | 
|  5396     if (need_mask_temp) { |  5389     if (need_mask_temp) { | 
|  5397       summary->set_temp(1, Location::RequiresRegister()); |  5390       summary->set_temp(1, Location::RequiresRegister()); | 
|  5398     } |  5391     } | 
|  5399   } |  5392   } | 
|  5400   return summary; |  5393   return summary; | 
|  5401 } |  5394 } | 
|  5402  |  5395  | 
|  5403  |  5396  | 
|  5404 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  5397 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  5405   Label* deopt = compiler->AddDeoptStub(deopt_id(), |  5398   Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass, | 
|  5406                                         ICData::kDeoptCheckClass, |  | 
|  5407                                         licm_hoisted_ ? ICData::kHoisted : 0); |  5399                                         licm_hoisted_ ? ICData::kHoisted : 0); | 
|  5408   if (IsNullCheck()) { |  5400   if (IsNullCheck()) { | 
|  5409     __ CompareObject(locs()->in(0).reg(), Object::null_object()); |  5401     __ CompareObject(locs()->in(0).reg(), Object::null_object()); | 
|  5410     ASSERT(DeoptIfNull() || DeoptIfNotNull()); |  5402     ASSERT(DeoptIfNull() || DeoptIfNotNull()); | 
|  5411     Condition cond = DeoptIfNull() ? EQ : NE; |  5403     Condition cond = DeoptIfNull() ? EQ : NE; | 
|  5412     __ b(deopt, cond); |  5404     __ b(deopt, cond); | 
|  5413     return; |  5405     return; | 
|  5414   } |  5406   } | 
|  5415  |  5407  | 
|  5416   ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || |  5408   ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || | 
| (...skipping 22 matching lines...) Expand all  Loading... | 
|  5439       ASSERT(cids_.length() > 2); |  5431       ASSERT(cids_.length() > 2); | 
|  5440       Register mask_reg = locs()->temp(1).reg(); |  5432       Register mask_reg = locs()->temp(1).reg(); | 
|  5441       __ LoadImmediate(mask_reg, 1); |  5433       __ LoadImmediate(mask_reg, 1); | 
|  5442       __ lslv(mask_reg, mask_reg, temp); |  5434       __ lslv(mask_reg, mask_reg, temp); | 
|  5443       __ TestImmediate(mask_reg, mask); |  5435       __ TestImmediate(mask_reg, mask); | 
|  5444       __ b(deopt, EQ); |  5436       __ b(deopt, EQ); | 
|  5445     } |  5437     } | 
|  5446  |  5438  | 
|  5447   } else { |  5439   } else { | 
|  5448     GrowableArray<CidTarget> sorted_ic_data; |  5440     GrowableArray<CidTarget> sorted_ic_data; | 
|  5449     FlowGraphCompiler::SortICDataByCount(unary_checks(), |  5441     FlowGraphCompiler::SortICDataByCount(unary_checks(), &sorted_ic_data, | 
|  5450                                          &sorted_ic_data, |  | 
|  5451                                          /* drop_smi = */ true); |  5442                                          /* drop_smi = */ true); | 
|  5452     const intptr_t num_checks = sorted_ic_data.length(); |  5443     const intptr_t num_checks = sorted_ic_data.length(); | 
|  5453     for (intptr_t i = 0; i < num_checks; i++) { |  5444     for (intptr_t i = 0; i < num_checks; i++) { | 
|  5454       const intptr_t cid = sorted_ic_data[i].cid; |  5445       const intptr_t cid = sorted_ic_data[i].cid; | 
|  5455       ASSERT(cid != kSmiCid); |  5446       ASSERT(cid != kSmiCid); | 
|  5456       __ CompareImmediate(temp, cid); |  5447       __ CompareImmediate(temp, cid); | 
|  5457       if (i == (num_checks - 1)) { |  5448       if (i == (num_checks - 1)) { | 
|  5458         __ b(deopt, NE); |  5449         __ b(deopt, NE); | 
|  5459       } else { |  5450       } else { | 
|  5460         __ b(&is_ok, EQ); |  5451         __ b(&is_ok, EQ); | 
|  5461       } |  5452       } | 
|  5462     } |  5453     } | 
|  5463   } |  5454   } | 
|  5464   __ Bind(&is_ok); |  5455   __ Bind(&is_ok); | 
|  5465 } |  5456 } | 
|  5466  |  5457  | 
|  5467  |  5458  | 
|  5468 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone, |  5459 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone, | 
|  5469                                                         bool opt) const { |  5460                                                         bool opt) const { | 
|  5470   const intptr_t kNumInputs = 1; |  5461   const intptr_t kNumInputs = 1; | 
|  5471   const intptr_t kNumTemps = 0; |  5462   const intptr_t kNumTemps = 0; | 
|  5472   LocationSummary* summary = new(zone) LocationSummary( |  5463   LocationSummary* summary = new (zone) | 
|  5473       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  5464       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  5474   summary->set_in(0, Location::RequiresRegister()); |  5465   summary->set_in(0, Location::RequiresRegister()); | 
|  5475   return summary; |  5466   return summary; | 
|  5476 } |  5467 } | 
|  5477  |  5468  | 
|  5478  |  5469  | 
|  5479 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  5470 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  5480   Register value = locs()->in(0).reg(); |  5471   Register value = locs()->in(0).reg(); | 
|  5481   Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass); |  5472   Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass); | 
|  5482   __ CompareImmediate(value, Smi::RawValue(cid_)); |  5473   __ CompareImmediate(value, Smi::RawValue(cid_)); | 
|  5483   __ b(deopt, NE); |  5474   __ b(deopt, NE); | 
|  5484 } |  5475 } | 
|  5485  |  5476  | 
|  5486  |  5477  | 
|  5487 LocationSummary* CheckSmiInstr::MakeLocationSummary(Zone* zone, |  5478 LocationSummary* CheckSmiInstr::MakeLocationSummary(Zone* zone, | 
|  5488                                                     bool opt) const { |  5479                                                     bool opt) const { | 
|  5489   const intptr_t kNumInputs = 1; |  5480   const intptr_t kNumInputs = 1; | 
|  5490   const intptr_t kNumTemps = 0; |  5481   const intptr_t kNumTemps = 0; | 
|  5491   LocationSummary* summary = new(zone) LocationSummary( |  5482   LocationSummary* summary = new (zone) | 
|  5492       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  5483       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  5493   summary->set_in(0, Location::RequiresRegister()); |  5484   summary->set_in(0, Location::RequiresRegister()); | 
|  5494   return summary; |  5485   return summary; | 
|  5495 } |  5486 } | 
|  5496  |  5487  | 
|  5497  |  5488  | 
|  5498 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  5489 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  5499   const Register value = locs()->in(0).reg(); |  5490   const Register value = locs()->in(0).reg(); | 
|  5500   Label* deopt = compiler->AddDeoptStub(deopt_id(), |  5491   Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckSmi, | 
|  5501                                         ICData::kDeoptCheckSmi, |  | 
|  5502                                         licm_hoisted_ ? ICData::kHoisted : 0); |  5492                                         licm_hoisted_ ? ICData::kHoisted : 0); | 
|  5503   __ BranchIfNotSmi(value, deopt); |  5493   __ BranchIfNotSmi(value, deopt); | 
|  5504 } |  5494 } | 
|  5505  |  5495  | 
|  5506  |  5496  | 
|  5507  |  | 
|  5508 LocationSummary* GenericCheckBoundInstr::MakeLocationSummary(Zone* zone, |  5497 LocationSummary* GenericCheckBoundInstr::MakeLocationSummary(Zone* zone, | 
|  5509                                                              bool opt) const { |  5498                                                              bool opt) const { | 
|  5510   const intptr_t kNumInputs = 2; |  5499   const intptr_t kNumInputs = 2; | 
|  5511   const intptr_t kNumTemps = 0; |  5500   const intptr_t kNumTemps = 0; | 
|  5512   LocationSummary* locs = new(zone) LocationSummary( |  5501   LocationSummary* locs = new (zone) LocationSummary( | 
|  5513       zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |  5502       zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 
|  5514   locs->set_in(kLengthPos, Location::RequiresRegister()); |  5503   locs->set_in(kLengthPos, Location::RequiresRegister()); | 
|  5515   locs->set_in(kIndexPos, Location::RequiresRegister()); |  5504   locs->set_in(kIndexPos, Location::RequiresRegister()); | 
|  5516   return locs; |  5505   return locs; | 
|  5517 } |  5506 } | 
|  5518  |  5507  | 
|  5519  |  5508  | 
|  5520 class RangeErrorSlowPath : public SlowPathCode { |  5509 class RangeErrorSlowPath : public SlowPathCode { | 
|  5521  public: |  5510  public: | 
|  5522   RangeErrorSlowPath(GenericCheckBoundInstr* instruction, intptr_t try_index) |  5511   RangeErrorSlowPath(GenericCheckBoundInstr* instruction, intptr_t try_index) | 
|  5523       : instruction_(instruction), try_index_(try_index) { } |  5512       : instruction_(instruction), try_index_(try_index) {} | 
|  5524  |  5513  | 
|  5525   virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |  5514   virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  5526     if (Assembler::EmittingComments()) { |  5515     if (Assembler::EmittingComments()) { | 
|  5527       __ Comment("slow path check bound operation"); |  5516       __ Comment("slow path check bound operation"); | 
|  5528     } |  5517     } | 
|  5529     __ Bind(entry_label()); |  5518     __ Bind(entry_label()); | 
|  5530     LocationSummary* locs = instruction_->locs(); |  5519     LocationSummary* locs = instruction_->locs(); | 
|  5531     __ Push(locs->in(0).reg()); |  5520     __ Push(locs->in(0).reg()); | 
|  5532     __ Push(locs->in(1).reg()); |  5521     __ Push(locs->in(1).reg()); | 
|  5533     __ CallRuntime(kRangeErrorRuntimeEntry, 2); |  5522     __ CallRuntime(kRangeErrorRuntimeEntry, 2); | 
|  5534     compiler->pc_descriptors_list()->AddDescriptor( |  5523     compiler->pc_descriptors_list()->AddDescriptor( | 
|  5535         RawPcDescriptors::kOther, |  5524         RawPcDescriptors::kOther, compiler->assembler()->CodeSize(), | 
|  5536         compiler->assembler()->CodeSize(), |  5525         instruction_->deopt_id(), instruction_->token_pos(), try_index_); | 
|  5537         instruction_->deopt_id(), |  | 
|  5538         instruction_->token_pos(), |  | 
|  5539         try_index_); |  | 
|  5540     compiler->RecordSafepoint(locs, 2); |  5526     compiler->RecordSafepoint(locs, 2); | 
|  5541     __ brk(0); |  5527     __ brk(0); | 
|  5542   } |  5528   } | 
|  5543  |  5529  | 
|  5544  private: |  5530  private: | 
|  5545   GenericCheckBoundInstr* instruction_; |  5531   GenericCheckBoundInstr* instruction_; | 
|  5546   intptr_t try_index_; |  5532   intptr_t try_index_; | 
|  5547 }; |  5533 }; | 
|  5548  |  5534  | 
|  5549  |  5535  | 
| (...skipping 12 matching lines...) Expand all  Loading... | 
|  5562   } |  5548   } | 
|  5563   __ cmp(index, Operand(length)); |  5549   __ cmp(index, Operand(length)); | 
|  5564   __ b(slow_path->entry_label(), CS); |  5550   __ b(slow_path->entry_label(), CS); | 
|  5565 } |  5551 } | 
|  5566  |  5552  | 
|  5567  |  5553  | 
|  5568 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone, |  5554 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone, | 
|  5569                                                            bool opt) const { |  5555                                                            bool opt) const { | 
|  5570   const intptr_t kNumInputs = 2; |  5556   const intptr_t kNumInputs = 2; | 
|  5571   const intptr_t kNumTemps = 0; |  5557   const intptr_t kNumTemps = 0; | 
|  5572   LocationSummary* locs = new(zone) LocationSummary( |  5558   LocationSummary* locs = new (zone) | 
|  5573       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  5559       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  5574   locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length())); |  5560   locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length())); | 
|  5575   locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index())); |  5561   locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index())); | 
|  5576   return locs; |  5562   return locs; | 
|  5577 } |  5563 } | 
|  5578  |  5564  | 
|  5579  |  5565  | 
|  5580 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  5566 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  5581   uint32_t flags = generalized_ ? ICData::kGeneralized : 0; |  5567   uint32_t flags = generalized_ ? ICData::kGeneralized : 0; | 
|  5582   flags |= licm_hoisted_ ? ICData::kHoisted : 0; |  5568   flags |= licm_hoisted_ ? ICData::kHoisted : 0; | 
|  5583   Label* deopt = compiler->AddDeoptStub( |  5569   Label* deopt = | 
|  5584       deopt_id(), |  5570       compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckArrayBound, flags); | 
|  5585       ICData::kDeoptCheckArrayBound, |  | 
|  5586       flags); |  | 
|  5587  |  5571  | 
|  5588   Location length_loc = locs()->in(kLengthPos); |  5572   Location length_loc = locs()->in(kLengthPos); | 
|  5589   Location index_loc = locs()->in(kIndexPos); |  5573   Location index_loc = locs()->in(kIndexPos); | 
|  5590  |  5574  | 
|  5591   const intptr_t index_cid = index()->Type()->ToCid(); |  5575   const intptr_t index_cid = index()->Type()->ToCid(); | 
|  5592   if (length_loc.IsConstant() && index_loc.IsConstant()) { |  5576   if (length_loc.IsConstant() && index_loc.IsConstant()) { | 
|  5593     // TODO(srdjan): remove this code once failures are fixed. |  5577     // TODO(srdjan): remove this code once failures are fixed. | 
|  5594     if ((Smi::Cast(length_loc.constant()).Value() > |  5578     if ((Smi::Cast(length_loc.constant()).Value() > | 
|  5595          Smi::Cast(index_loc.constant()).Value()) && |  5579          Smi::Cast(index_loc.constant()).Value()) && | 
|  5596         (Smi::Cast(index_loc.constant()).Value() >= 0)) { |  5580         (Smi::Cast(index_loc.constant()).Value() >= 0)) { | 
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  5696 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryUint32OpInstr) |  5680 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryUint32OpInstr) | 
|  5697 DEFINE_UNIMPLEMENTED_INSTRUCTION(ShiftUint32OpInstr) |  5681 DEFINE_UNIMPLEMENTED_INSTRUCTION(ShiftUint32OpInstr) | 
|  5698 DEFINE_UNIMPLEMENTED_INSTRUCTION(UnaryUint32OpInstr) |  5682 DEFINE_UNIMPLEMENTED_INSTRUCTION(UnaryUint32OpInstr) | 
|  5699 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr) |  5683 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr) | 
|  5700  |  5684  | 
|  5701  |  5685  | 
|  5702 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Zone* zone, |  5686 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Zone* zone, | 
|  5703                                                                bool opt) const { |  5687                                                                bool opt) const { | 
|  5704   const intptr_t kNumInputs = 1; |  5688   const intptr_t kNumInputs = 1; | 
|  5705   const intptr_t kNumTemps = 0; |  5689   const intptr_t kNumTemps = 0; | 
|  5706   LocationSummary* summary = new(zone) LocationSummary( |  5690   LocationSummary* summary = new (zone) | 
|  5707       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  5691       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  5708   if (from() == kUnboxedMint) { |  5692   if (from() == kUnboxedMint) { | 
|  5709     UNREACHABLE(); |  5693     UNREACHABLE(); | 
|  5710   } else if (to() == kUnboxedMint) { |  5694   } else if (to() == kUnboxedMint) { | 
|  5711     UNREACHABLE(); |  5695     UNREACHABLE(); | 
|  5712   } else { |  5696   } else { | 
|  5713     ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); |  5697     ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); | 
|  5714     ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); |  5698     ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); | 
|  5715     summary->set_in(0, Location::RequiresRegister()); |  5699     summary->set_in(0, Location::RequiresRegister()); | 
|  5716     summary->set_out(0, Location::RequiresRegister()); |  5700     summary->set_out(0, Location::RequiresRegister()); | 
|  5717   } |  5701   } | 
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  5749     UNREACHABLE(); |  5733     UNREACHABLE(); | 
|  5750   } else if (to() == kUnboxedMint) { |  5734   } else if (to() == kUnboxedMint) { | 
|  5751     ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); |  5735     ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); | 
|  5752     UNREACHABLE(); |  5736     UNREACHABLE(); | 
|  5753   } else { |  5737   } else { | 
|  5754     UNREACHABLE(); |  5738     UNREACHABLE(); | 
|  5755   } |  5739   } | 
|  5756 } |  5740 } | 
|  5757  |  5741  | 
|  5758  |  5742  | 
|  5759 LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, |  5743 LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 
|  5760                                                  bool opt) const { |  5744   return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); | 
|  5761   return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); |  | 
|  5762 } |  5745 } | 
|  5763  |  5746  | 
|  5764  |  5747  | 
|  5765 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  5748 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  5766   compiler->GenerateRuntimeCall(token_pos(), |  5749   compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kThrowRuntimeEntry, 1, | 
|  5767                                 deopt_id(), |  | 
|  5768                                 kThrowRuntimeEntry, |  | 
|  5769                                 1, |  | 
|  5770                                 locs()); |  5750                                 locs()); | 
|  5771   __ brk(0); |  5751   __ brk(0); | 
|  5772 } |  5752 } | 
|  5773  |  5753  | 
|  5774  |  5754  | 
|  5775 LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, |  5755 LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 
|  5776                                                    bool opt) const { |  5756   return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); | 
|  5777   return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); |  | 
|  5778 } |  5757 } | 
|  5779  |  5758  | 
|  5780  |  5759  | 
|  5781 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  5760 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  5782   compiler->SetNeedsStacktrace(catch_try_index()); |  5761   compiler->SetNeedsStacktrace(catch_try_index()); | 
|  5783   compiler->GenerateRuntimeCall(token_pos(), |  5762   compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kReThrowRuntimeEntry, | 
|  5784                                 deopt_id(), |  5763                                 2, locs()); | 
|  5785                                 kReThrowRuntimeEntry, |  | 
|  5786                                 2, |  | 
|  5787                                 locs()); |  | 
|  5788   __ brk(0); |  5764   __ brk(0); | 
|  5789 } |  5765 } | 
|  5790  |  5766  | 
|  5791  |  5767  | 
|  5792 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, |  5768 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 
|  5793                                                 bool opt) const { |  5769   return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); | 
|  5794   return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); |  | 
|  5795 } |  5770 } | 
|  5796  |  5771  | 
|  5797  |  5772  | 
|  5798 void StopInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  5773 void StopInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  5799   __ Stop(message()); |  5774   __ Stop(message()); | 
|  5800 } |  5775 } | 
|  5801  |  5776  | 
|  5802  |  5777  | 
|  5803 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  5778 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  5804   if (!compiler->CanFallThroughTo(normal_entry())) { |  5779   if (!compiler->CanFallThroughTo(normal_entry())) { | 
|  5805     __ b(compiler->GetJumpLabel(normal_entry())); |  5780     __ b(compiler->GetJumpLabel(normal_entry())); | 
|  5806   } |  5781   } | 
|  5807 } |  5782 } | 
|  5808  |  5783  | 
|  5809  |  5784  | 
|  5810 LocationSummary* GotoInstr::MakeLocationSummary(Zone* zone, |  5785 LocationSummary* GotoInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 
|  5811                                                 bool opt) const { |  5786   return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); | 
|  5812   return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); |  | 
|  5813 } |  5787 } | 
|  5814  |  5788  | 
|  5815  |  5789  | 
|  5816 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  5790 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  5817   if (!compiler->is_optimizing()) { |  5791   if (!compiler->is_optimizing()) { | 
|  5818     if (FLAG_reorder_basic_blocks) { |  5792     if (FLAG_reorder_basic_blocks) { | 
|  5819       compiler->EmitEdgeCounter(block()->preorder_number()); |  5793       compiler->EmitEdgeCounter(block()->preorder_number()); | 
|  5820     } |  5794     } | 
|  5821     // Add a deoptimization descriptor for deoptimizing instructions that |  5795     // Add a deoptimization descriptor for deoptimizing instructions that | 
|  5822     // may be inserted before this instruction. |  5796     // may be inserted before this instruction. | 
|  5823     compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, |  5797     compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, GetDeoptId(), | 
|  5824                                    GetDeoptId(), |  | 
|  5825                                    TokenPosition::kNoSource); |  5798                                    TokenPosition::kNoSource); | 
|  5826   } |  5799   } | 
|  5827   if (HasParallelMove()) { |  5800   if (HasParallelMove()) { | 
|  5828     compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |  5801     compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 
|  5829   } |  5802   } | 
|  5830  |  5803  | 
|  5831   // We can fall through if the successor is the next block in the list. |  5804   // We can fall through if the successor is the next block in the list. | 
|  5832   // Otherwise, we need a jump. |  5805   // Otherwise, we need a jump. | 
|  5833   if (!compiler->CanFallThroughTo(successor())) { |  5806   if (!compiler->CanFallThroughTo(successor())) { | 
|  5834     __ b(compiler->GetJumpLabel(successor())); |  5807     __ b(compiler->GetJumpLabel(successor())); | 
|  5835   } |  5808   } | 
|  5836 } |  5809 } | 
|  5837  |  5810  | 
|  5838  |  5811  | 
|  5839 LocationSummary* IndirectGotoInstr::MakeLocationSummary(Zone* zone, |  5812 LocationSummary* IndirectGotoInstr::MakeLocationSummary(Zone* zone, | 
|  5840                                                         bool opt) const { |  5813                                                         bool opt) const { | 
|  5841   const intptr_t kNumInputs = 1; |  5814   const intptr_t kNumInputs = 1; | 
|  5842   const intptr_t kNumTemps = 1; |  5815   const intptr_t kNumTemps = 1; | 
|  5843  |  5816  | 
|  5844   LocationSummary* summary = new(zone) LocationSummary( |  5817   LocationSummary* summary = new (zone) | 
|  5845         zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  5818       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  5846  |  5819  | 
|  5847   summary->set_in(0, Location::RequiresRegister()); |  5820   summary->set_in(0, Location::RequiresRegister()); | 
|  5848   summary->set_temp(0, Location::RequiresRegister()); |  5821   summary->set_temp(0, Location::RequiresRegister()); | 
|  5849  |  5822  | 
|  5850   return summary; |  5823   return summary; | 
|  5851 } |  5824 } | 
|  5852  |  5825  | 
|  5853  |  5826  | 
|  5854 void IndirectGotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  5827 void IndirectGotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  5855   Register target_address_reg = locs()->temp_slot(0)->reg(); |  5828   Register target_address_reg = locs()->temp_slot(0)->reg(); | 
|  5856  |  5829  | 
|  5857   // Load code entry point. |  5830   // Load code entry point. | 
|  5858   const intptr_t entry_offset = __ CodeSize(); |  5831   const intptr_t entry_offset = __ CodeSize(); | 
|  5859   if (Utils::IsInt(21, -entry_offset)) { |  5832   if (Utils::IsInt(21, -entry_offset)) { | 
|  5860     __ adr(target_address_reg, Immediate(-entry_offset)); |  5833     __ adr(target_address_reg, Immediate(-entry_offset)); | 
|  5861   } else { |  5834   } else { | 
|  5862     __ adr(target_address_reg, Immediate(0)); |  5835     __ adr(target_address_reg, Immediate(0)); | 
|  5863     __ AddImmediate(target_address_reg, target_address_reg, -entry_offset); |  5836     __ AddImmediate(target_address_reg, target_address_reg, -entry_offset); | 
|  5864   } |  5837   } | 
|  5865  |  5838  | 
|  5866   // Add the offset. |  5839   // Add the offset. | 
|  5867   Register offset_reg = locs()->in(0).reg(); |  5840   Register offset_reg = locs()->in(0).reg(); | 
|  5868   Operand offset_opr = |  5841   Operand offset_opr = (offset()->definition()->representation() == kTagged) | 
|  5869       (offset()->definition()->representation() == kTagged) ? |  5842                            ? Operand(offset_reg, ASR, kSmiTagSize) | 
|  5870       Operand(offset_reg, ASR, kSmiTagSize) : |  5843                            : Operand(offset_reg); | 
|  5871       Operand(offset_reg); |  | 
|  5872   __ add(target_address_reg, target_address_reg, offset_opr); |  5844   __ add(target_address_reg, target_address_reg, offset_opr); | 
|  5873  |  5845  | 
|  5874   // Jump to the absolute address. |  5846   // Jump to the absolute address. | 
|  5875   __ br(target_address_reg); |  5847   __ br(target_address_reg); | 
|  5876 } |  5848 } | 
|  5877  |  5849  | 
|  5878  |  5850  | 
|  5879 LocationSummary* StrictCompareInstr::MakeLocationSummary(Zone* zone, |  5851 LocationSummary* StrictCompareInstr::MakeLocationSummary(Zone* zone, | 
|  5880                                                          bool opt) const { |  5852                                                          bool opt) const { | 
|  5881   const intptr_t kNumInputs = 2; |  5853   const intptr_t kNumInputs = 2; | 
|  5882   const intptr_t kNumTemps = 0; |  5854   const intptr_t kNumTemps = 0; | 
|  5883   if (needs_number_check()) { |  5855   if (needs_number_check()) { | 
|  5884     LocationSummary* locs = new(zone) LocationSummary( |  5856     LocationSummary* locs = new (zone) | 
|  5885         zone, kNumInputs, kNumTemps, LocationSummary::kCall); |  5857         LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 
|  5886     locs->set_in(0, Location::RegisterLocation(R0)); |  5858     locs->set_in(0, Location::RegisterLocation(R0)); | 
|  5887     locs->set_in(1, Location::RegisterLocation(R1)); |  5859     locs->set_in(1, Location::RegisterLocation(R1)); | 
|  5888     locs->set_out(0, Location::RegisterLocation(R0)); |  5860     locs->set_out(0, Location::RegisterLocation(R0)); | 
|  5889     return locs; |  5861     return locs; | 
|  5890   } |  5862   } | 
|  5891   LocationSummary* locs = new(zone) LocationSummary( |  5863   LocationSummary* locs = new (zone) | 
|  5892       zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |  5864       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 
|  5893   locs->set_in(0, Location::RegisterOrConstant(left())); |  5865   locs->set_in(0, Location::RegisterOrConstant(left())); | 
|  5894   // Only one of the inputs can be a constant. Choose register if the first one |  5866   // Only one of the inputs can be a constant. Choose register if the first one | 
|  5895   // is a constant. |  5867   // is a constant. | 
|  5896   locs->set_in(1, locs->in(0).IsConstant() |  5868   locs->set_in(1, locs->in(0).IsConstant() | 
|  5897                       ? Location::RequiresRegister() |  5869                       ? Location::RequiresRegister() | 
|  5898                       : Location::RegisterOrConstant(right())); |  5870                       : Location::RegisterOrConstant(right())); | 
|  5899   locs->set_out(0, Location::RequiresRegister()); |  5871   locs->set_out(0, Location::RequiresRegister()); | 
|  5900   return locs; |  5872   return locs; | 
|  5901 } |  5873 } | 
|  5902  |  5874  | 
|  5903  |  5875  | 
|  5904 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |  5876 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 
|  5905                                                  BranchLabels labels) { |  5877                                                  BranchLabels labels) { | 
|  5906   Location left = locs()->in(0); |  5878   Location left = locs()->in(0); | 
|  5907   Location right = locs()->in(1); |  5879   Location right = locs()->in(1); | 
|  5908   ASSERT(!left.IsConstant() || !right.IsConstant()); |  5880   ASSERT(!left.IsConstant() || !right.IsConstant()); | 
|  5909   Condition true_condition; |  5881   Condition true_condition; | 
|  5910   if (left.IsConstant()) { |  5882   if (left.IsConstant()) { | 
|  5911     true_condition = compiler->EmitEqualityRegConstCompare(right.reg(), |  5883     true_condition = compiler->EmitEqualityRegConstCompare( | 
|  5912                                                            left.constant(), |  5884         right.reg(), left.constant(), needs_number_check(), token_pos()); | 
|  5913                                                            needs_number_check(), |  | 
|  5914                                                            token_pos()); |  | 
|  5915   } else if (right.IsConstant()) { |  5885   } else if (right.IsConstant()) { | 
|  5916     true_condition = compiler->EmitEqualityRegConstCompare(left.reg(), |  5886     true_condition = compiler->EmitEqualityRegConstCompare( | 
|  5917                                                            right.constant(), |  5887         left.reg(), right.constant(), needs_number_check(), token_pos()); | 
|  5918                                                            needs_number_check(), |  | 
|  5919                                                            token_pos()); |  | 
|  5920   } else { |  5888   } else { | 
|  5921     true_condition = compiler->EmitEqualityRegRegCompare(left.reg(), |  5889     true_condition = compiler->EmitEqualityRegRegCompare( | 
|  5922                                                          right.reg(), |  5890         left.reg(), right.reg(), needs_number_check(), token_pos()); | 
|  5923                                                          needs_number_check(), |  | 
|  5924                                                          token_pos()); |  | 
|  5925   } |  5891   } | 
|  5926   if (kind() != Token::kEQ_STRICT) { |  5892   if (kind() != Token::kEQ_STRICT) { | 
|  5927     ASSERT(kind() == Token::kNE_STRICT); |  5893     ASSERT(kind() == Token::kNE_STRICT); | 
|  5928     true_condition = NegateCondition(true_condition); |  5894     true_condition = NegateCondition(true_condition); | 
|  5929   } |  5895   } | 
|  5930   return true_condition; |  5896   return true_condition; | 
|  5931 } |  5897 } | 
|  5932  |  5898  | 
|  5933  |  5899  | 
|  5934 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  5900 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  5935   __ Comment("StrictCompareInstr"); |  5901   __ Comment("StrictCompareInstr"); | 
|  5936   ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |  5902   ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 
|  5937  |  5903  | 
|  5938   Label is_true, is_false; |  5904   Label is_true, is_false; | 
|  5939   BranchLabels labels = { &is_true, &is_false, &is_false }; |  5905   BranchLabels labels = {&is_true, &is_false, &is_false}; | 
|  5940   Condition true_condition = EmitComparisonCode(compiler, labels); |  5906   Condition true_condition = EmitComparisonCode(compiler, labels); | 
|  5941   EmitBranchOnCondition(compiler, true_condition, labels); |  5907   EmitBranchOnCondition(compiler, true_condition, labels); | 
|  5942  |  5908  | 
|  5943   const Register result = locs()->out(0).reg(); |  5909   const Register result = locs()->out(0).reg(); | 
|  5944   Label done; |  5910   Label done; | 
|  5945   __ Bind(&is_false); |  5911   __ Bind(&is_false); | 
|  5946   __ LoadObject(result, Bool::False()); |  5912   __ LoadObject(result, Bool::False()); | 
|  5947   __ b(&done); |  5913   __ b(&done); | 
|  5948   __ Bind(&is_true); |  5914   __ Bind(&is_true); | 
|  5949   __ LoadObject(result, Bool::True()); |  5915   __ LoadObject(result, Bool::True()); | 
|  5950   __ Bind(&done); |  5916   __ Bind(&done); | 
|  5951 } |  5917 } | 
|  5952  |  5918  | 
|  5953  |  5919  | 
|  5954 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |  5920 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 
|  5955                                         BranchInstr* branch) { |  5921                                         BranchInstr* branch) { | 
|  5956   ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |  5922   ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 
|  5957  |  5923  | 
|  5958   BranchLabels labels = compiler->CreateBranchLabels(branch); |  5924   BranchLabels labels = compiler->CreateBranchLabels(branch); | 
|  5959   Condition true_condition = EmitComparisonCode(compiler, labels); |  5925   Condition true_condition = EmitComparisonCode(compiler, labels); | 
|  5960   EmitBranchOnCondition(compiler, true_condition, labels); |  5926   EmitBranchOnCondition(compiler, true_condition, labels); | 
|  5961 } |  5927 } | 
|  5962  |  5928  | 
|  5963  |  5929  | 
|  5964 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, |  5930 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, | 
|  5965                                                          bool opt) const { |  5931                                                          bool opt) const { | 
|  5966   return LocationSummary::Make(zone, |  5932   return LocationSummary::Make(zone, 1, Location::RequiresRegister(), | 
|  5967                                1, |  | 
|  5968                                Location::RequiresRegister(), |  | 
|  5969                                LocationSummary::kNoCall); |  5933                                LocationSummary::kNoCall); | 
|  5970 } |  5934 } | 
|  5971  |  5935  | 
|  5972  |  5936  | 
|  5973 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  5937 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  5974   const Register value = locs()->in(0).reg(); |  5938   const Register value = locs()->in(0).reg(); | 
|  5975   const Register result = locs()->out(0).reg(); |  5939   const Register result = locs()->out(0).reg(); | 
|  5976  |  5940  | 
|  5977   __ LoadObject(result, Bool::True()); |  5941   __ LoadObject(result, Bool::True()); | 
|  5978   __ LoadObject(TMP, Bool::False()); |  5942   __ LoadObject(TMP, Bool::False()); | 
|  5979   __ CompareRegisters(result, value); |  5943   __ CompareRegisters(result, value); | 
|  5980   __ csel(result, TMP, result, EQ); |  5944   __ csel(result, TMP, result, EQ); | 
|  5981 } |  5945 } | 
|  5982  |  5946  | 
|  5983  |  5947  | 
|  5984 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone, |  5948 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone, | 
|  5985                                                           bool opt) const { |  5949                                                           bool opt) const { | 
|  5986   return MakeCallSummary(zone); |  5950   return MakeCallSummary(zone); | 
|  5987 } |  5951 } | 
|  5988  |  5952  | 
|  5989  |  5953  | 
|  5990 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  5954 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  5991   const Code& stub = Code::ZoneHandle( |  5955   const Code& stub = Code::ZoneHandle( | 
|  5992       compiler->zone(), StubCode::GetAllocationStubForClass(cls())); |  5956       compiler->zone(), StubCode::GetAllocationStubForClass(cls())); | 
|  5993   const StubEntry stub_entry(stub); |  5957   const StubEntry stub_entry(stub); | 
|  5994   compiler->GenerateCall(token_pos(), |  5958   compiler->GenerateCall(token_pos(), stub_entry, RawPcDescriptors::kOther, | 
|  5995                          stub_entry, |  | 
|  5996                          RawPcDescriptors::kOther, |  | 
|  5997                          locs()); |  5959                          locs()); | 
|  5998   compiler->AddStubCallTarget(stub); |  5960   compiler->AddStubCallTarget(stub); | 
|  5999   __ Drop(ArgumentCount());  // Discard arguments. |  5961   __ Drop(ArgumentCount());  // Discard arguments. | 
|  6000 } |  5962 } | 
|  6001  |  5963  | 
|  6002  |  5964  | 
|  6003 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  5965 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  6004   ASSERT(!compiler->is_optimizing()); |  5966   ASSERT(!compiler->is_optimizing()); | 
|  6005   __ BranchLinkPatchable(*StubCode::DebugStepCheck_entry()); |  5967   __ BranchLinkPatchable(*StubCode::DebugStepCheck_entry()); | 
|  6006   compiler->AddCurrentDescriptor(stub_kind_, Thread::kNoDeoptId, token_pos()); |  5968   compiler->AddCurrentDescriptor(stub_kind_, Thread::kNoDeoptId, token_pos()); | 
|  6007   compiler->RecordSafepoint(locs()); |  5969   compiler->RecordSafepoint(locs()); | 
|  6008 } |  5970 } | 
|  6009  |  5971  | 
|  6010  |  5972  | 
|  6011 LocationSummary* GrowRegExpStackInstr::MakeLocationSummary( |  5973 LocationSummary* GrowRegExpStackInstr::MakeLocationSummary(Zone* zone, | 
|  6012     Zone* zone, bool opt) const { |  5974                                                            bool opt) const { | 
|  6013   const intptr_t kNumInputs = 1; |  5975   const intptr_t kNumInputs = 1; | 
|  6014   const intptr_t kNumTemps = 0; |  5976   const intptr_t kNumTemps = 0; | 
|  6015   LocationSummary* locs = new(zone) LocationSummary( |  5977   LocationSummary* locs = new (zone) | 
|  6016       zone, kNumInputs, kNumTemps, LocationSummary::kCall); |  5978       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 
|  6017   locs->set_in(0, Location::RegisterLocation(R0)); |  5979   locs->set_in(0, Location::RegisterLocation(R0)); | 
|  6018   locs->set_out(0, Location::RegisterLocation(R0)); |  5980   locs->set_out(0, Location::RegisterLocation(R0)); | 
|  6019   return locs; |  5981   return locs; | 
|  6020 } |  5982 } | 
|  6021  |  5983  | 
|  6022  |  5984  | 
|  6023 void GrowRegExpStackInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |  5985 void GrowRegExpStackInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 
|  6024   const Register typed_data = locs()->in(0).reg(); |  5986   const Register typed_data = locs()->in(0).reg(); | 
|  6025   const Register result = locs()->out(0).reg(); |  5987   const Register result = locs()->out(0).reg(); | 
|  6026   __ PushObject(Object::null_object()); |  5988   __ PushObject(Object::null_object()); | 
|  6027   __ Push(typed_data); |  5989   __ Push(typed_data); | 
|  6028   compiler->GenerateRuntimeCall(TokenPosition::kNoSource, |  5990   compiler->GenerateRuntimeCall(TokenPosition::kNoSource, deopt_id(), | 
|  6029                                 deopt_id(), |  5991                                 kGrowRegExpStackRuntimeEntry, 1, locs()); | 
|  6030                                 kGrowRegExpStackRuntimeEntry, |  | 
|  6031                                 1, |  | 
|  6032                                 locs()); |  | 
|  6033   __ Drop(1); |  5992   __ Drop(1); | 
|  6034   __ Pop(result); |  5993   __ Pop(result); | 
|  6035 } |  5994 } | 
|  6036  |  5995  | 
|  6037  |  5996  | 
|  6038 }  // namespace dart |  5997 }  // namespace dart | 
|  6039  |  5998  | 
|  6040 #endif  // defined TARGET_ARCH_ARM64 |  5999 #endif  // defined TARGET_ARCH_ARM64 | 
| OLD | NEW |