| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
| 6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "lib/error.h" |
| 10 #include "vm/flow_graph_compiler.h" | 11 #include "vm/flow_graph_compiler.h" |
| 11 #include "vm/locations.h" | 12 #include "vm/locations.h" |
| 12 #include "vm/object_store.h" | 13 #include "vm/object_store.h" |
| 13 #include "vm/stub_code.h" | 14 #include "vm/stub_code.h" |
| 14 | 15 |
| 15 #define __ compiler->assembler()-> | 16 #define __ compiler->assembler()-> |
| 16 | 17 |
| 17 namespace dart { | 18 namespace dart { |
| 18 | 19 |
| 19 DECLARE_FLAG(int, optimization_counter_threshold); | 20 DECLARE_FLAG(int, optimization_counter_threshold); |
| 20 DECLARE_FLAG(bool, trace_functions); | 21 DECLARE_FLAG(bool, trace_functions); |
| 21 | 22 |
| 22 // True iff. the arguments to a call will be properly pushed and can | |
| 23 // be popped after the call. | |
| 24 template <typename T> static bool VerifyCallComputation(T* comp) { | |
| 25 // Argument values should be consecutive temps. | |
| 26 // | |
| 27 // TODO(kmillikin): implement stack height tracking so we can also assert | |
| 28 // they are on top of the stack. | |
| 29 intptr_t previous = -1; | |
| 30 for (int i = 0; i < comp->ArgumentCount(); ++i) { | |
| 31 Value* val = comp->ArgumentAt(i); | |
| 32 if (!val->IsUse()) return false; | |
| 33 intptr_t current = val->AsUse()->definition()->temp_index(); | |
| 34 if (i != 0) { | |
| 35 if (current != (previous + 1)) return false; | |
| 36 } | |
| 37 previous = current; | |
| 38 } | |
| 39 return true; | |
| 40 } | |
| 41 | |
| 42 | 23 |
| 43 // Generic summary for call instructions that have all arguments pushed | 24 // Generic summary for call instructions that have all arguments pushed |
| 44 // on the stack and return the result in a fixed register EAX. | 25 // on the stack and return the result in a fixed register EAX. |
| 45 static LocationSummary* MakeCallSummary() { | 26 LocationSummary* Computation::MakeCallSummary() { |
| 46 LocationSummary* result = new LocationSummary(0, 0); | 27 LocationSummary* result = new LocationSummary(0, 0); |
| 47 result->set_out(Location::RegisterLocation(EAX)); | 28 result->set_out(Location::RegisterLocation(EAX)); |
| 48 return result; | 29 return result; |
| 49 } | 30 } |
| 50 | 31 |
| 51 | 32 |
| 52 void BindInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 33 void BindInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 53 computation()->EmitNativeCode(compiler); | 34 computation()->EmitNativeCode(compiler); |
| 54 __ pushl(locs()->out().reg()); | 35 __ pushl(locs()->out().reg()); |
| 55 } | 36 } |
| 56 | 37 |
| 57 | 38 |
| 58 void GraphEntryInstr::PrepareEntry(FlowGraphCompiler* compiler) { | |
| 59 // Nothing to do. | |
| 60 } | |
| 61 | |
| 62 | |
| 63 void JoinEntryInstr::PrepareEntry(FlowGraphCompiler* compiler) { | |
| 64 __ Bind(compiler->GetBlockLabel(this)); | |
| 65 } | |
| 66 | |
| 67 | |
| 68 void TargetEntryInstr::PrepareEntry(FlowGraphCompiler* compiler) { | |
| 69 __ Bind(compiler->GetBlockLabel(this)); | |
| 70 if (HasTryIndex()) { | |
| 71 compiler->AddExceptionHandler(try_index(), | |
| 72 compiler->assembler()->CodeSize()); | |
| 73 } | |
| 74 } | |
| 75 | |
| 76 | |
| 77 LocationSummary* ReturnInstr::MakeLocationSummary() const { | 39 LocationSummary* ReturnInstr::MakeLocationSummary() const { |
| 78 const intptr_t kNumInputs = 1; | 40 const intptr_t kNumInputs = 1; |
| 79 const intptr_t kNumTemps = 1; | 41 const intptr_t kNumTemps = 1; |
| 80 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 42 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); |
| 81 locs->set_in(0, Location::RegisterLocation(EAX)); | 43 locs->set_in(0, Location::RegisterLocation(EAX)); |
| 82 locs->set_temp(0, Location::RequiresRegister()); | 44 locs->set_temp(0, Location::RequiresRegister()); |
| 83 return locs; | 45 return locs; |
| 84 } | 46 } |
| 85 | 47 |
| 86 | 48 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 128 // Add a NOP to make return code pattern 5 bytes long for patching | 90 // Add a NOP to make return code pattern 5 bytes long for patching |
| 129 // in breakpoints during debugging. | 91 // in breakpoints during debugging. |
| 130 __ nop(1); | 92 __ nop(1); |
| 131 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, | 93 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, |
| 132 cid(), | 94 cid(), |
| 133 token_index(), | 95 token_index(), |
| 134 CatchClauseNode::kInvalidTryIndex); | 96 CatchClauseNode::kInvalidTryIndex); |
| 135 } | 97 } |
| 136 | 98 |
| 137 | 99 |
| 138 LocationSummary* ThrowInstr::MakeLocationSummary() const { | |
| 139 return NULL; | |
| 140 } | |
| 141 | |
| 142 | |
| 143 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 144 UNIMPLEMENTED(); | |
| 145 } | |
| 146 | |
| 147 | |
| 148 LocationSummary* ReThrowInstr::MakeLocationSummary() const { | |
| 149 return NULL; | |
| 150 } | |
| 151 | |
| 152 | |
| 153 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 154 UNIMPLEMENTED(); | |
| 155 } | |
| 156 | |
| 157 | |
| 158 LocationSummary* BranchInstr::MakeLocationSummary() const { | |
| 159 const int kNumInputs = 1; | |
| 160 const int kNumTemps = 0; | |
| 161 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | |
| 162 locs->set_in(0, Location::RequiresRegister()); | |
| 163 return locs; | |
| 164 } | |
| 165 | |
| 166 | |
| 167 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 168 Register value = locs()->in(0).reg(); | |
| 169 __ CompareObject(value, Bool::ZoneHandle(Bool::True())); | |
| 170 if (compiler->IsNextBlock(false_successor())) { | |
| 171 // If the next block is the false successor we will fall through to it if | |
| 172 // comparison with true fails. | |
| 173 __ j(EQUAL, compiler->GetBlockLabel(true_successor())); | |
| 174 } else { | |
| 175 ASSERT(compiler->IsNextBlock(true_successor())); | |
| 176 // If the next block is the true successor we negate comparison and fall | |
| 177 // through to it. | |
| 178 __ j(NOT_EQUAL, compiler->GetBlockLabel(false_successor())); | |
| 179 } | |
| 180 } | |
| 181 | |
| 182 | |
| 183 LocationSummary* CurrentContextComp::MakeLocationSummary() const { | |
| 184 return LocationSummary::Make(0, Location::RequiresRegister()); | |
| 185 } | |
| 186 | |
| 187 | |
| 188 void CurrentContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 189 __ movl(locs()->out().reg(), CTX); | |
| 190 } | |
| 191 | |
| 192 | |
| 193 LocationSummary* StoreContextComp::MakeLocationSummary() const { | |
| 194 const intptr_t kNumInputs = 1; | |
| 195 const intptr_t kNumTemps = 0; | |
| 196 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); | |
| 197 summary->set_in(0, Location::RegisterLocation(CTX)); | |
| 198 return summary; | |
| 199 } | |
| 200 | |
| 201 | |
| 202 void StoreContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 203 // Nothing to do. Context register were loaded by register allocator. | |
| 204 ASSERT(locs()->in(0).reg() == CTX); | |
| 205 } | |
| 206 | |
| 207 | |
| 208 LocationSummary* StrictCompareComp::MakeLocationSummary() const { | |
| 209 return LocationSummary::Make(2, Location::SameAsFirstInput()); | |
| 210 } | |
| 211 | |
| 212 | |
| 213 void StrictCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 214 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | |
| 215 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | |
| 216 | |
| 217 Register left = locs()->in(0).reg(); | |
| 218 Register right = locs()->in(1).reg(); | |
| 219 Register result = locs()->out().reg(); | |
| 220 | |
| 221 __ cmpl(left, right); | |
| 222 Label load_true, done; | |
| 223 if (kind() == Token::kEQ_STRICT) { | |
| 224 __ j(EQUAL, &load_true, Assembler::kNearJump); | |
| 225 } else { | |
| 226 ASSERT(kind() == Token::kNE_STRICT); | |
| 227 __ j(NOT_EQUAL, &load_true, Assembler::kNearJump); | |
| 228 } | |
| 229 __ LoadObject(result, bool_false); | |
| 230 __ jmp(&done, Assembler::kNearJump); | |
| 231 __ Bind(&load_true); | |
| 232 __ LoadObject(result, bool_true); | |
| 233 __ Bind(&done); | |
| 234 } | |
| 235 | |
| 236 | |
| 237 LocationSummary* ClosureCallComp::MakeLocationSummary() const { | 100 LocationSummary* ClosureCallComp::MakeLocationSummary() const { |
| 238 return MakeCallSummary(); | 101 const intptr_t kNumInputs = 0; |
| 239 } | 102 const intptr_t kNumTemps = 1; |
| 240 | 103 LocationSummary* result = new LocationSummary(kNumInputs, kNumTemps); |
| 241 | 104 result->set_out(Location::RegisterLocation(EAX)); |
| 242 void ClosureCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 105 result->set_temp(0, Location::RegisterLocation(EDX)); // Arg. descriptor. |
| 243 ASSERT(VerifyCallComputation(this)); | 106 return result; |
| 244 // The arguments to the stub include the closure. The arguments | |
| 245 // descriptor describes the closure's arguments (and so does not include | |
| 246 // the closure). | |
| 247 int argument_count = ArgumentCount(); | |
| 248 const Array& arguments_descriptor = | |
| 249 CodeGenerator::ArgumentsDescriptor(argument_count - 1, | |
| 250 argument_names()); | |
| 251 __ LoadObject(EDX, arguments_descriptor); | |
| 252 compiler->GenerateCall(token_index(), | |
| 253 try_index(), | |
| 254 &StubCode::CallClosureFunctionLabel(), | |
| 255 PcDescriptors::kOther); | |
| 256 __ Drop(argument_count); | |
| 257 } | |
| 258 | |
| 259 | |
| 260 LocationSummary* InstanceCallComp::MakeLocationSummary() const { | |
| 261 return MakeCallSummary(); | |
| 262 } | |
| 263 | |
| 264 | |
| 265 void InstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 266 ASSERT(VerifyCallComputation(this)); | |
| 267 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | |
| 268 cid(), | |
| 269 token_index(), | |
| 270 try_index()); | |
| 271 compiler->GenerateInstanceCall(cid(), | |
| 272 token_index(), | |
| 273 try_index(), | |
| 274 function_name(), | |
| 275 ArgumentCount(), | |
| 276 argument_names(), | |
| 277 checked_argument_count()); | |
| 278 } | |
| 279 | |
| 280 | |
| 281 LocationSummary* StaticCallComp::MakeLocationSummary() const { | |
| 282 return MakeCallSummary(); | |
| 283 } | |
| 284 | |
| 285 | |
| 286 void StaticCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 287 ASSERT(VerifyCallComputation(this)); | |
| 288 compiler->GenerateStaticCall(cid(), | |
| 289 token_index(), | |
| 290 try_index(), | |
| 291 function(), | |
| 292 ArgumentCount(), | |
| 293 argument_names()); | |
| 294 } | 107 } |
| 295 | 108 |
| 296 | 109 |
| 297 LocationSummary* LoadLocalComp::MakeLocationSummary() const { | 110 LocationSummary* LoadLocalComp::MakeLocationSummary() const { |
| 298 return LocationSummary::Make(0, Location::RequiresRegister()); | 111 return LocationSummary::Make(0, Location::RequiresRegister()); |
| 299 } | 112 } |
| 300 | 113 |
| 301 | 114 |
| 302 void LoadLocalComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 115 void LoadLocalComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 303 Register result = locs()->out().reg(); | 116 Register result = locs()->out().reg(); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 327 Register result = locs()->out().reg(); | 140 Register result = locs()->out().reg(); |
| 328 if (value().IsSmi()) { | 141 if (value().IsSmi()) { |
| 329 int32_t imm = reinterpret_cast<int32_t>(value().raw()); | 142 int32_t imm = reinterpret_cast<int32_t>(value().raw()); |
| 330 __ movl(result, Immediate(imm)); | 143 __ movl(result, Immediate(imm)); |
| 331 } else { | 144 } else { |
| 332 __ LoadObject(result, value()); | 145 __ LoadObject(result, value()); |
| 333 } | 146 } |
| 334 } | 147 } |
| 335 | 148 |
| 336 | 149 |
| 337 LocationSummary* UseVal::MakeLocationSummary() const { | |
| 338 return NULL; | |
| 339 } | |
| 340 | |
| 341 | |
| 342 void UseVal::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 343 UNIMPLEMENTED(); | |
| 344 } | |
| 345 | |
| 346 | |
| 347 LocationSummary* AssertAssignableComp::MakeLocationSummary() const { | 150 LocationSummary* AssertAssignableComp::MakeLocationSummary() const { |
| 348 LocationSummary* summary = new LocationSummary(3, 0); | 151 LocationSummary* summary = new LocationSummary(3, 0); |
| 349 summary->set_in(0, Location::RegisterLocation(EAX)); | 152 summary->set_in(0, Location::RegisterLocation(EAX)); // Value. |
| 350 summary->set_in(1, Location::RegisterLocation(ECX)); | 153 summary->set_in(1, Location::RegisterLocation(ECX)); // Instantiator. |
| 351 summary->set_in(2, Location::RegisterLocation(EDX)); | 154 summary->set_in(2, Location::RegisterLocation(EDX)); // Type arguments. |
| 352 summary->set_out(Location::RegisterLocation(EAX)); | 155 summary->set_out(Location::RegisterLocation(EAX)); |
| 353 return summary; | 156 return summary; |
| 354 } | 157 } |
| 355 | 158 |
| 356 | 159 |
| 357 void AssertAssignableComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 160 void AssertBooleanComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 358 ASSERT(locs()->in(0).reg() == EAX); // Value. | 161 Register obj = locs()->in(0).reg(); |
| 359 ASSERT(locs()->in(1).reg() == ECX); // Instantiator. | 162 Register result = locs()->out().reg(); |
| 360 ASSERT(locs()->in(2).reg() == EDX); // Instantiator type arguments. | |
| 361 | 163 |
| 362 compiler->GenerateAssertAssignable(cid(), | 164 // Check that the type of the value is allowed in conditional context. |
| 363 token_index(), | 165 // Call the runtime if the object is not bool::true or bool::false. |
| 364 try_index(), | 166 Label done; |
| 365 dst_type(), | 167 __ CompareObject(obj, Bool::ZoneHandle(Bool::True())); |
| 366 dst_name()); | 168 __ j(EQUAL, &done, Assembler::kNearJump); |
| 367 ASSERT(locs()->in(0).reg() == locs()->out().reg()); | 169 __ CompareObject(obj, Bool::ZoneHandle(Bool::False())); |
| 368 } | 170 __ j(EQUAL, &done, Assembler::kNearJump); |
| 369 | 171 |
| 172 __ pushl(Immediate(Smi::RawValue(token_index()))); // Source location. |
| 173 __ pushl(obj); // Push the source object. |
| 174 compiler->GenerateCallRuntime(cid(), |
| 175 token_index(), |
| 176 try_index(), |
| 177 kConditionTypeErrorRuntimeEntry); |
| 178 // We should never return here. |
| 179 __ int3(); |
| 370 | 180 |
| 371 LocationSummary* AssertBooleanComp::MakeLocationSummary() const { | 181 __ Bind(&done); |
| 372 return NULL; | 182 ASSERT(obj == result); |
| 373 } | |
| 374 | |
| 375 | |
| 376 void AssertBooleanComp::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 377 UNIMPLEMENTED(); | |
| 378 } | 183 } |
| 379 | 184 |
| 380 | 185 |
| 381 LocationSummary* EqualityCompareComp::MakeLocationSummary() const { | 186 LocationSummary* EqualityCompareComp::MakeLocationSummary() const { |
| 382 return NULL; | 187 LocationSummary* locs = new LocationSummary(2, 0); |
| 188 locs->set_in(0, Location::RequiresRegister()); |
| 189 locs->set_in(1, Location::RequiresRegister()); |
| 190 locs->set_out(Location::RegisterLocation(EAX)); |
| 191 return locs; |
| 383 } | 192 } |
| 384 | 193 |
| 385 | 194 |
| 386 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 195 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 387 UNIMPLEMENTED(); | 196 Register left = locs()->in(0).reg(); |
| 197 Register right = locs()->in(1).reg(); |
| 198 Register result = locs()->out().reg(); |
| 199 ASSERT(locs()->out().reg() == EAX); |
| 200 |
| 201 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
| 202 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); |
| 203 const Immediate raw_null = |
| 204 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 205 Label done, load_true, non_null_compare; |
| 206 __ cmpl(left, raw_null); |
| 207 __ j(NOT_EQUAL, &non_null_compare, Assembler::kNearJump); |
| 208 // Comparison with NULL is "===". |
| 209 __ cmpl(left, right); |
| 210 __ j(EQUAL, &load_true, Assembler::kNearJump); |
| 211 __ LoadObject(result, bool_false); |
| 212 __ jmp(&done, Assembler::kNearJump); |
| 213 __ Bind(&load_true); |
| 214 __ LoadObject(result, bool_true); |
| 215 __ jmp(&done); |
| 216 |
| 217 __ Bind(&non_null_compare); |
| 218 __ pushl(left); |
| 219 __ pushl(right); |
| 220 const String& operator_name = String::ZoneHandle(String::NewSymbol("==")); |
| 221 const int kNumberOfArguments = 2; |
| 222 const Array& kNoArgumentNames = Array::Handle(); |
| 223 const int kNumArgumentsChecked = 1; |
| 224 |
| 225 compiler->GenerateInstanceCall(cid(), |
| 226 token_index(), |
| 227 try_index(), |
| 228 operator_name, |
| 229 kNumberOfArguments, |
| 230 kNoArgumentNames, |
| 231 kNumArgumentsChecked); |
| 232 __ Bind(&done); |
| 388 } | 233 } |
| 389 | 234 |
| 390 | 235 |
| 391 LocationSummary* NativeCallComp::MakeLocationSummary() const { | 236 LocationSummary* NativeCallComp::MakeLocationSummary() const { |
| 392 LocationSummary* locs = new LocationSummary(0, 3); | 237 LocationSummary* locs = new LocationSummary(0, 3); |
| 393 locs->set_temp(0, Location::RegisterLocation(EAX)); | 238 locs->set_temp(0, Location::RegisterLocation(EAX)); |
| 394 locs->set_temp(1, Location::RegisterLocation(ECX)); | 239 locs->set_temp(1, Location::RegisterLocation(ECX)); |
| 395 locs->set_temp(2, Location::RegisterLocation(EDX)); | 240 locs->set_temp(2, Location::RegisterLocation(EDX)); |
| 396 locs->set_out(Location::RequiresRegister()); | 241 locs->set_out(Location::RequiresRegister()); |
| 397 return locs; | 242 return locs; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 416 __ movl(EDX, Immediate(argument_count())); | 261 __ movl(EDX, Immediate(argument_count())); |
| 417 compiler->GenerateCall(token_index(), | 262 compiler->GenerateCall(token_index(), |
| 418 try_index(), | 263 try_index(), |
| 419 &StubCode::CallNativeCFunctionLabel(), | 264 &StubCode::CallNativeCFunctionLabel(), |
| 420 PcDescriptors::kOther); | 265 PcDescriptors::kOther); |
| 421 __ popl(result); | 266 __ popl(result); |
| 422 } | 267 } |
| 423 | 268 |
| 424 | 269 |
| 425 LocationSummary* StoreIndexedComp::MakeLocationSummary() const { | 270 LocationSummary* StoreIndexedComp::MakeLocationSummary() const { |
| 426 return NULL; | 271 const intptr_t kNumInputs = 3; |
| 272 return LocationSummary::Make(kNumInputs, Location::NoLocation()); |
| 427 } | 273 } |
| 428 | 274 |
| 429 | 275 |
| 430 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 276 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 431 UNIMPLEMENTED(); | 277 Register receiver = locs()->in(0).reg(); |
| 278 Register index = locs()->in(1).reg(); |
| 279 Register value = locs()->in(2).reg(); |
| 280 |
| 281 const String& function_name = |
| 282 String::ZoneHandle(String::NewSymbol(Token::Str(Token::kASSIGN_INDEX))); |
| 283 |
| 284 __ pushl(receiver); |
| 285 __ pushl(index); |
| 286 __ pushl(value); |
| 287 const intptr_t kNumArguments = 3; |
| 288 const intptr_t kNumArgsChecked = 1; // Type-feedback. |
| 289 compiler->GenerateInstanceCall(cid(), |
| 290 token_index(), |
| 291 try_index(), |
| 292 function_name, |
| 293 kNumArguments, |
| 294 Array::ZoneHandle(), // No optional arguments. |
| 295 kNumArgsChecked); |
| 432 } | 296 } |
| 433 | 297 |
| 434 | 298 |
| 435 LocationSummary* InstanceSetterComp::MakeLocationSummary() const { | 299 LocationSummary* InstanceSetterComp::MakeLocationSummary() const { |
| 436 const intptr_t kNumInputs = 2; | 300 const intptr_t kNumInputs = 2; |
| 437 return LocationSummary::Make(kNumInputs, Location::RequiresRegister()); | 301 return LocationSummary::Make(kNumInputs, Location::RequiresRegister()); |
| 438 return NULL; | 302 return NULL; |
| 439 } | 303 } |
| 440 | 304 |
| 441 | 305 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 480 LocationSummary* LoadInstanceFieldComp::MakeLocationSummary() const { | 344 LocationSummary* LoadInstanceFieldComp::MakeLocationSummary() const { |
| 481 return NULL; | 345 return NULL; |
| 482 } | 346 } |
| 483 | 347 |
| 484 | 348 |
| 485 void LoadInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 349 void LoadInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 486 UNIMPLEMENTED(); | 350 UNIMPLEMENTED(); |
| 487 } | 351 } |
| 488 | 352 |
| 489 | 353 |
| 490 LocationSummary* StoreInstanceFieldComp::MakeLocationSummary() const { | |
| 491 return NULL; | |
| 492 } | |
| 493 | |
| 494 | |
| 495 void StoreInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 496 UNIMPLEMENTED(); | |
| 497 } | |
| 498 | |
| 499 | |
| 500 LocationSummary* LoadStaticFieldComp::MakeLocationSummary() const { | 354 LocationSummary* LoadStaticFieldComp::MakeLocationSummary() const { |
| 501 return NULL; | 355 return LocationSummary::Make(0, Location::RequiresRegister()); |
| 502 } | 356 } |
| 503 | 357 |
| 504 | 358 |
| 505 void LoadStaticFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 359 void LoadStaticFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 506 UNIMPLEMENTED(); | 360 Register result = locs()->out().reg(); |
| 507 } | 361 __ LoadObject(result, field()); |
| 508 | 362 __ movl(result, FieldAddress(result, Field::value_offset())); |
| 509 | |
| 510 LocationSummary* StoreStaticFieldComp::MakeLocationSummary() const { | |
| 511 return NULL; | |
| 512 } | |
| 513 | |
| 514 | |
| 515 void StoreStaticFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 516 UNIMPLEMENTED(); | |
| 517 } | |
| 518 | |
| 519 | |
| 520 LocationSummary* BooleanNegateComp::MakeLocationSummary() const { | |
| 521 return NULL; | |
| 522 } | |
| 523 | |
| 524 | |
| 525 void BooleanNegateComp::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 526 UNIMPLEMENTED(); | |
| 527 } | 363 } |
| 528 | 364 |
| 529 | 365 |
| 530 LocationSummary* InstanceOfComp::MakeLocationSummary() const { | 366 LocationSummary* InstanceOfComp::MakeLocationSummary() const { |
| 531 LocationSummary* summary = new LocationSummary(3, 0); | 367 LocationSummary* summary = new LocationSummary(3, 0); |
| 532 summary->set_in(0, Location::RegisterLocation(EAX)); | 368 summary->set_in(0, Location::RegisterLocation(EAX)); |
| 533 summary->set_in(1, Location::RegisterLocation(ECX)); | 369 summary->set_in(1, Location::RegisterLocation(ECX)); |
| 534 summary->set_in(2, Location::RegisterLocation(EDX)); | 370 summary->set_in(2, Location::RegisterLocation(EDX)); |
| 535 summary->set_out(Location::RegisterLocation(EAX)); | 371 summary->set_out(Location::RegisterLocation(EAX)); |
| 536 return summary; | 372 return summary; |
| 537 } | 373 } |
| 538 | 374 |
| 539 | 375 |
| 540 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 376 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 541 ASSERT(locs()->in(0).reg() == EAX); // Value. | 377 ASSERT(locs()->in(0).reg() == EAX); // Value. |
| 542 ASSERT(locs()->in(1).reg() == ECX); // Instantiator. | 378 ASSERT(locs()->in(1).reg() == ECX); // Instantiator. |
| 543 ASSERT(locs()->in(2).reg() == EDX); // Instantiator type arguments. | 379 ASSERT(locs()->in(2).reg() == EDX); // Instantiator type arguments. |
| 544 | 380 |
| 545 compiler->GenerateInstanceOf(cid(), | 381 compiler->GenerateInstanceOf(cid(), |
| 546 token_index(), | 382 token_index(), |
| 547 try_index(), | 383 try_index(), |
| 548 type(), | 384 type(), |
| 549 negate_result()); | 385 negate_result()); |
| 550 ASSERT(locs()->out().reg() == EAX); | 386 ASSERT(locs()->out().reg() == EAX); |
| 551 } | 387 } |
| 552 | 388 |
| 553 | 389 |
| 554 LocationSummary* CreateArrayComp::MakeLocationSummary() const { | 390 LocationSummary* CreateArrayComp::MakeLocationSummary() const { |
| 555 return NULL; | 391 // TODO(regis): The elements of the array could be considered as arguments to |
| 392 // CreateArrayComp, thereby making CreateArrayComp a call. |
| 393 // For VerifyCallComputation to work, CreateArrayComp would need an |
| 394 // ArgumentCount getter and an ArgumentAt getter. |
| 395 const intptr_t kNumInputs = 1; |
| 396 const intptr_t kNumTemps = 1; |
| 397 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); |
| 398 locs->set_in(0, Location::RegisterLocation(ECX)); |
| 399 locs->set_temp(0, Location::RegisterLocation(EDX)); |
| 400 locs->set_out(Location::RegisterLocation(EAX)); |
| 401 return locs; |
| 556 } | 402 } |
| 557 | 403 |
| 558 | 404 |
| 559 void CreateArrayComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 405 void CreateArrayComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 560 UNIMPLEMENTED(); | 406 Register temp_reg = locs()->temp(0).reg(); |
| 407 Register result_reg = locs()->out().reg(); |
| 408 ASSERT(temp_reg == EDX); |
| 409 ASSERT(locs()->in(0).reg() == ECX); |
| 410 // 1. Allocate the array. EDX = length, ECX = element type. |
| 411 __ movl(EDX, Immediate(Smi::RawValue(ElementCount()))); |
| 412 compiler->GenerateCall(token_index(), |
| 413 try_index(), |
| 414 &StubCode::AllocateArrayLabel(), |
| 415 PcDescriptors::kOther); |
| 416 ASSERT(result_reg == EAX); |
| 417 // Pop the element values from the stack into the array. |
| 418 __ leal(temp_reg, FieldAddress(result_reg, Array::data_offset())); |
| 419 for (int i = ElementCount() - 1; i >= 0; --i) { |
| 420 ASSERT(ElementAt(i)->IsUse()); |
| 421 __ popl(Address(temp_reg, i * kWordSize)); |
| 422 } |
| 561 } | 423 } |
| 562 | 424 |
| 563 | 425 |
| 564 LocationSummary* CreateClosureComp::MakeLocationSummary() const { | |
| 565 return MakeCallSummary(); | |
| 566 } | |
| 567 | |
| 568 | |
| 569 void CreateClosureComp::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 570 const Function& closure_function = function(); | |
| 571 const Code& stub = Code::Handle( | |
| 572 StubCode::GetAllocationStubForClosure(closure_function)); | |
| 573 const ExternalLabel label(closure_function.ToCString(), stub.EntryPoint()); | |
| 574 compiler->GenerateCall(token_index(), try_index(), &label, | |
| 575 PcDescriptors::kOther); | |
| 576 __ Drop(2); // Discard type arguments and receiver. | |
| 577 } | |
| 578 | |
| 579 | |
| 580 LocationSummary* AllocateObjectComp::MakeLocationSummary() const { | |
| 581 return MakeCallSummary(); | |
| 582 } | |
| 583 | |
| 584 | |
| 585 void AllocateObjectComp::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 586 const Class& cls = Class::ZoneHandle(constructor().owner()); | |
| 587 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls)); | |
| 588 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); | |
| 589 compiler->GenerateCall(token_index(), | |
| 590 try_index(), | |
| 591 &label, | |
| 592 PcDescriptors::kOther); | |
| 593 __ Drop(arguments().length()); // Discard arguments. | |
| 594 } | |
| 595 | |
| 596 | |
| 597 LocationSummary* | 426 LocationSummary* |
| 598 AllocateObjectWithBoundsCheckComp::MakeLocationSummary() const { | 427 AllocateObjectWithBoundsCheckComp::MakeLocationSummary() const { |
| 599 return LocationSummary::Make(2, Location::RequiresRegister()); | 428 return LocationSummary::Make(2, Location::RequiresRegister()); |
| 600 } | 429 } |
| 601 | 430 |
| 602 | 431 |
| 603 void AllocateObjectWithBoundsCheckComp::EmitNativeCode( | 432 void AllocateObjectWithBoundsCheckComp::EmitNativeCode( |
| 604 FlowGraphCompiler* compiler) { | 433 FlowGraphCompiler* compiler) { |
| 605 const Class& cls = Class::ZoneHandle(constructor().owner()); | 434 const Class& cls = Class::ZoneHandle(constructor().owner()); |
| 606 Register type_arguments = locs()->in(0).reg(); | 435 Register type_arguments = locs()->in(0).reg(); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 629 | 458 |
| 630 | 459 |
| 631 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 460 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 632 Register obj = locs()->in(0).reg(); | 461 Register obj = locs()->in(0).reg(); |
| 633 Register result = locs()->out().reg(); | 462 Register result = locs()->out().reg(); |
| 634 | 463 |
| 635 __ movl(result, FieldAddress(obj, offset_in_bytes())); | 464 __ movl(result, FieldAddress(obj, offset_in_bytes())); |
| 636 } | 465 } |
| 637 | 466 |
| 638 | 467 |
| 639 LocationSummary* StoreVMFieldComp::MakeLocationSummary() const { | |
| 640 return LocationSummary::Make(2, Location::SameAsFirstInput()); | |
| 641 } | |
| 642 | |
| 643 | |
| 644 void StoreVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 645 Register value_reg = locs()->in(0).reg(); | |
| 646 Register dest_reg = locs()->in(1).reg(); | |
| 647 ASSERT(value_reg == locs()->out().reg()); | |
| 648 | |
| 649 __ StoreIntoObject(dest_reg, FieldAddress(dest_reg, offset_in_bytes()), | |
| 650 value_reg); | |
| 651 } | |
| 652 | |
| 653 | |
| 654 LocationSummary* InstantiateTypeArgumentsComp::MakeLocationSummary() const { | 468 LocationSummary* InstantiateTypeArgumentsComp::MakeLocationSummary() const { |
| 655 const intptr_t kNumInputs = 1; | 469 const intptr_t kNumInputs = 1; |
| 656 const intptr_t kNumTemps = 1; | 470 const intptr_t kNumTemps = 1; |
| 657 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 471 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); |
| 658 locs->set_in(0, Location::RequiresRegister()); | 472 locs->set_in(0, Location::RequiresRegister()); |
| 659 locs->set_temp(0, Location::RequiresRegister()); | 473 locs->set_temp(0, Location::RequiresRegister()); |
| 660 locs->set_out(Location::SameAsFirstInput()); | 474 locs->set_out(Location::SameAsFirstInput()); |
| 661 return locs; | 475 return locs; |
| 662 } | 476 } |
| 663 | 477 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 705 kInstantiateTypeArgumentsRuntimeEntry); | 519 kInstantiateTypeArgumentsRuntimeEntry); |
| 706 __ Drop(2); // Drop instantiator and uninstantiated type arguments. | 520 __ Drop(2); // Drop instantiator and uninstantiated type arguments. |
| 707 __ popl(result_reg); // Pop instantiated type arguments. | 521 __ popl(result_reg); // Pop instantiated type arguments. |
| 708 __ Bind(&type_arguments_instantiated); | 522 __ Bind(&type_arguments_instantiated); |
| 709 ASSERT(instantiator_reg == result_reg); | 523 ASSERT(instantiator_reg == result_reg); |
| 710 } | 524 } |
| 711 | 525 |
| 712 | 526 |
| 713 LocationSummary* | 527 LocationSummary* |
| 714 ExtractConstructorTypeArgumentsComp::MakeLocationSummary() const { | 528 ExtractConstructorTypeArgumentsComp::MakeLocationSummary() const { |
| 715 return NULL; | 529 const intptr_t kNumInputs = 1; |
| 530 const intptr_t kNumTemps = 1; |
| 531 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); |
| 532 locs->set_in(0, Location::RequiresRegister()); |
| 533 locs->set_out(Location::SameAsFirstInput()); |
| 534 locs->set_temp(0, Location::RequiresRegister()); |
| 535 return locs; |
| 716 } | 536 } |
| 717 | 537 |
| 718 | 538 |
| 719 void ExtractConstructorTypeArgumentsComp::EmitNativeCode( | 539 void ExtractConstructorTypeArgumentsComp::EmitNativeCode( |
| 720 FlowGraphCompiler* compiler) { | 540 FlowGraphCompiler* compiler) { |
| 721 UNIMPLEMENTED(); | 541 Register instantiator_reg = locs()->in(0).reg(); |
| 542 Register result_reg = locs()->out().reg(); |
| 543 ASSERT(instantiator_reg == result_reg); |
| 544 Register temp_reg = locs()->temp(0).reg(); |
| 545 |
| 546 // instantiator_reg is the instantiator type argument vector, i.e. an |
| 547 // AbstractTypeArguments object (or null). |
| 548 // If the instantiator is null and if the type argument vector |
| 549 // instantiated from null becomes a vector of Dynamic, then use null as |
| 550 // the type arguments. |
| 551 Label type_arguments_instantiated; |
| 552 const intptr_t len = type_arguments().Length(); |
| 553 if (type_arguments().IsRawInstantiatedRaw(len)) { |
| 554 const Immediate raw_null = |
| 555 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 556 __ cmpl(instantiator_reg, raw_null); |
| 557 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 558 } |
| 559 // Instantiate non-null type arguments. |
| 560 if (type_arguments().IsUninstantiatedIdentity()) { |
| 561 // Check if the instantiator type argument vector is a TypeArguments of a |
| 562 // matching length and, if so, use it as the instantiated type_arguments. |
| 563 // No need to check instantiator_reg for null here, because a null |
| 564 // instantiator will have the wrong class (Null instead of TypeArguments). |
| 565 Label type_arguments_uninstantiated; |
| 566 __ CompareClassId(instantiator_reg, kTypeArguments, temp_reg); |
| 567 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); |
| 568 Immediate arguments_length = |
| 569 Immediate(Smi::RawValue(type_arguments().Length())); |
| 570 __ cmpl(FieldAddress(instantiator_reg, TypeArguments::length_offset()), |
| 571 arguments_length); |
| 572 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 573 __ Bind(&type_arguments_uninstantiated); |
| 574 } |
| 575 // In the non-factory case, we rely on the allocation stub to |
| 576 // instantiate the type arguments. |
| 577 __ LoadObject(result_reg, type_arguments()); |
| 578 // result_reg: uninstantiated type arguments. |
| 579 __ Bind(&type_arguments_instantiated); |
| 580 // result_reg: uninstantiated or instantiated type arguments. |
| 722 } | 581 } |
| 723 | 582 |
| 724 | 583 |
| 725 LocationSummary* | 584 LocationSummary* |
| 726 ExtractConstructorInstantiatorComp::MakeLocationSummary() const { | 585 ExtractConstructorInstantiatorComp::MakeLocationSummary() const { |
| 727 return NULL; | 586 const intptr_t kNumInputs = 1; |
| 587 const intptr_t kNumTemps = 1; |
| 588 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); |
| 589 locs->set_in(0, Location::RequiresRegister()); |
| 590 locs->set_out(Location::SameAsFirstInput()); |
| 591 locs->set_temp(0, Location::RequiresRegister()); |
| 592 return locs; |
| 728 } | 593 } |
| 729 | 594 |
| 730 | 595 |
| 731 void ExtractConstructorInstantiatorComp::EmitNativeCode( | 596 void ExtractConstructorInstantiatorComp::EmitNativeCode( |
| 732 FlowGraphCompiler* compiler) { | 597 FlowGraphCompiler* compiler) { |
| 733 UNIMPLEMENTED(); | 598 ASSERT(instantiator()->IsUse()); |
| 599 Register instantiator_reg = locs()->in(0).reg(); |
| 600 ASSERT(locs()->out().reg() == instantiator_reg); |
| 601 Register temp_reg = locs()->temp(0).reg(); |
| 602 |
| 603 // instantiator_reg is the instantiator AbstractTypeArguments object |
| 604 // (or null). If the instantiator is null and if the type argument vector |
| 605 // instantiated from null becomes a vector of Dynamic, then use null as |
| 606 // the type arguments and do not pass the instantiator. |
| 607 Label done; |
| 608 const intptr_t len = type_arguments().Length(); |
| 609 if (type_arguments().IsRawInstantiatedRaw(len)) { |
| 610 const Immediate raw_null = |
| 611 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 612 Label instantiator_not_null; |
| 613 __ cmpl(instantiator_reg, raw_null); |
| 614 __ j(NOT_EQUAL, &instantiator_not_null, Assembler::kNearJump); |
| 615 // Null was used in VisitExtractConstructorTypeArguments as the |
| 616 // instantiated type arguments, no proper instantiator needed. |
| 617 __ movl(instantiator_reg, |
| 618 Immediate(Smi::RawValue(StubCode::kNoInstantiator))); |
| 619 __ jmp(&done); |
| 620 __ Bind(&instantiator_not_null); |
| 621 } |
| 622 // Instantiate non-null type arguments. |
| 623 if (type_arguments().IsUninstantiatedIdentity()) { |
| 624 // TODO(regis): The following emitted code is duplicated in |
| 625 // VisitExtractConstructorTypeArguments above. The reason is that the code |
| 626 // is split between two computations, so that each one produces a |
| 627 // single value, rather than producing a pair of values. |
| 628 // If this becomes an issue, we should expose these tests at the IL level. |
| 629 |
| 630 // Check if the instantiator type argument vector is a TypeArguments of a |
| 631 // matching length and, if so, use it as the instantiated type_arguments. |
| 632 // No need to check the instantiator (RAX) for null here, because a null |
| 633 // instantiator will have the wrong class (Null instead of TypeArguments). |
| 634 __ CompareClassId(instantiator_reg, kTypeArguments, temp_reg); |
| 635 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
| 636 Immediate arguments_length = |
| 637 Immediate(Smi::RawValue(type_arguments().Length())); |
| 638 __ cmpl(FieldAddress(instantiator_reg, TypeArguments::length_offset()), |
| 639 arguments_length); |
| 640 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
| 641 // The instantiator was used in VisitExtractConstructorTypeArguments as the |
| 642 // instantiated type arguments, no proper instantiator needed. |
| 643 __ movl(instantiator_reg, |
| 644 Immediate(Smi::RawValue(StubCode::kNoInstantiator))); |
| 645 } |
| 646 __ Bind(&done); |
| 647 // instantiator_reg: instantiator or kNoInstantiator. |
| 734 } | 648 } |
| 735 | 649 |
| 736 | 650 |
| 737 LocationSummary* AllocateContextComp::MakeLocationSummary() const { | 651 LocationSummary* AllocateContextComp::MakeLocationSummary() const { |
| 738 const intptr_t kNumInputs = 0; | 652 const intptr_t kNumInputs = 0; |
| 739 const intptr_t kNumTemps = 1; | 653 const intptr_t kNumTemps = 1; |
| 740 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 654 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); |
| 741 locs->set_temp(0, Location::RegisterLocation(EDX)); | 655 locs->set_temp(0, Location::RegisterLocation(EDX)); |
| 742 locs->set_out(Location::RegisterLocation(EAX)); | 656 locs->set_out(Location::RegisterLocation(EAX)); |
| 743 return locs; | 657 return locs; |
| 744 } | 658 } |
| 745 | 659 |
| 746 | 660 |
| 747 void AllocateContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 661 void AllocateContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 748 ASSERT(locs()->temp(0).reg() == EDX); | 662 ASSERT(locs()->temp(0).reg() == EDX); |
| 749 ASSERT(locs()->out().reg() == EAX); | 663 ASSERT(locs()->out().reg() == EAX); |
| 750 | 664 |
| 751 __ movl(EDX, Immediate(num_context_variables())); | 665 __ movl(EDX, Immediate(num_context_variables())); |
| 752 const ExternalLabel label("alloc_context", | 666 const ExternalLabel label("alloc_context", |
| 753 StubCode::AllocateContextEntryPoint()); | 667 StubCode::AllocateContextEntryPoint()); |
| 754 compiler->GenerateCall(token_index(), | 668 compiler->GenerateCall(token_index(), |
| 755 try_index(), | 669 try_index(), |
| 756 &label, | 670 &label, |
| 757 PcDescriptors::kOther); | 671 PcDescriptors::kOther); |
| 758 } | 672 } |
| 759 | 673 |
| 760 | 674 |
| 761 LocationSummary* ChainContextComp::MakeLocationSummary() const { | |
| 762 return LocationSummary::Make(1, Location::NoLocation()); | |
| 763 } | |
| 764 | |
| 765 | |
| 766 void ChainContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 767 Register context_value = locs()->in(0).reg(); | |
| 768 | |
| 769 // Chain the new context in context_value to its parent in CTX. | |
| 770 __ StoreIntoObject(context_value, | |
| 771 FieldAddress(context_value, Context::parent_offset()), | |
| 772 CTX); | |
| 773 // Set new context as current context. | |
| 774 __ movl(CTX, context_value); | |
| 775 } | |
| 776 | |
| 777 | |
| 778 LocationSummary* CloneContextComp::MakeLocationSummary() const { | 675 LocationSummary* CloneContextComp::MakeLocationSummary() const { |
| 779 return LocationSummary::Make(1, Location::RequiresRegister()); | 676 return LocationSummary::Make(1, Location::RequiresRegister()); |
| 780 } | 677 } |
| 781 | 678 |
| 782 | 679 |
| 783 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 680 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 784 Register context_value = locs()->in(0).reg(); | 681 Register context_value = locs()->in(0).reg(); |
| 785 Register result = locs()->out().reg(); | 682 Register result = locs()->out().reg(); |
| 786 | 683 |
| 787 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 684 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 940 UNREACHABLE(); | 837 UNREACHABLE(); |
| 941 } | 838 } |
| 942 } | 839 } |
| 943 | 840 |
| 944 | 841 |
| 945 } // namespace dart | 842 } // namespace dart |
| 946 | 843 |
| 947 #undef __ | 844 #undef __ |
| 948 | 845 |
| 949 #endif // defined TARGET_ARCH_X64 | 846 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |