| 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_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| 11 #include "vm/flow_graph_compiler.h" | 11 #include "vm/flow_graph_compiler.h" |
| 12 #include "vm/locations.h" | 12 #include "vm/locations.h" |
| 13 #include "vm/object_store.h" | 13 #include "vm/object_store.h" |
| 14 #include "vm/parser.h" | 14 #include "vm/parser.h" |
| 15 #include "vm/stub_code.h" | 15 #include "vm/stub_code.h" |
| 16 | 16 |
| 17 #define __ compiler->assembler()-> | 17 #define __ compiler->assembler()-> |
| 18 | 18 |
| 19 namespace dart { | 19 namespace dart { |
| 20 | 20 |
| 21 DECLARE_FLAG(int, optimization_counter_threshold); | 21 DECLARE_FLAG(int, optimization_counter_threshold); |
| 22 DECLARE_FLAG(bool, trace_functions); | 22 DECLARE_FLAG(bool, trace_functions); |
| 23 | 23 |
| 24 | 24 |
| 25 // True iff. the arguments to a call will be properly pushed and can | |
| 26 // be popped after the call. | |
| 27 template <typename T> static bool VerifyCallComputation(T* comp) { | |
| 28 // Argument values should be consecutive temps. | |
| 29 // | |
| 30 // TODO(kmillikin): implement stack height tracking so we can also assert | |
| 31 // they are on top of the stack. | |
| 32 intptr_t previous = -1; | |
| 33 for (int i = 0; i < comp->ArgumentCount(); ++i) { | |
| 34 Value* val = comp->ArgumentAt(i); | |
| 35 if (!val->IsUse()) return false; | |
| 36 intptr_t current = val->AsUse()->definition()->temp_index(); | |
| 37 if (i != 0) { | |
| 38 if (current != (previous + 1)) return false; | |
| 39 } | |
| 40 previous = current; | |
| 41 } | |
| 42 return true; | |
| 43 } | |
| 44 | |
| 45 | |
| 46 // Truee iff. the v2 is above v1 on stack, or one of them is constant. | |
| 47 static bool VerifyValues(Value* v1, Value* v2) { | |
| 48 ASSERT(v1->IsUse() && v2->IsUse()); | |
| 49 return (v1->AsUse()->definition()->temp_index() + 1) == | |
| 50 v2->AsUse()->definition()->temp_index(); | |
| 51 } | |
| 52 | |
| 53 | |
| 54 void BindInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 25 void BindInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 55 computation()->EmitNativeCode(compiler); | 26 computation()->EmitNativeCode(compiler); |
| 56 __ pushq(locs()->out().reg()); | 27 __ pushq(locs()->out().reg()); |
| 57 } | 28 } |
| 58 | 29 |
| 59 | 30 |
| 60 void GraphEntryInstr::PrepareEntry(FlowGraphCompiler* compiler) { | |
| 61 // Nothing to do. | |
| 62 } | |
| 63 | |
| 64 | |
| 65 void JoinEntryInstr::PrepareEntry(FlowGraphCompiler* compiler) { | |
| 66 __ Bind(compiler->GetBlockLabel(this)); | |
| 67 } | |
| 68 | |
| 69 | |
| 70 void TargetEntryInstr::PrepareEntry(FlowGraphCompiler* compiler) { | |
| 71 __ Bind(compiler->GetBlockLabel(this)); | |
| 72 if (HasTryIndex()) { | |
| 73 compiler->AddExceptionHandler(try_index(), | |
| 74 compiler->assembler()->CodeSize()); | |
| 75 } | |
| 76 } | |
| 77 | |
| 78 | |
| 79 LocationSummary* ThrowInstr::MakeLocationSummary() const { | |
| 80 const int kNumInputs = 0; | |
| 81 const int kNumTemps = 0; | |
| 82 return new LocationSummary(kNumInputs, kNumTemps); | |
| 83 } | |
| 84 | |
| 85 | |
| 86 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 87 ASSERT(exception()->IsUse()); | |
| 88 compiler->GenerateCallRuntime(cid(), | |
| 89 token_index(), | |
| 90 try_index(), | |
| 91 kThrowRuntimeEntry); | |
| 92 __ int3(); | |
| 93 } | |
| 94 | |
| 95 | |
| 96 LocationSummary* ReThrowInstr::MakeLocationSummary() const { | |
| 97 const int kNumInputs = 0; | |
| 98 const int kNumTemps = 0; | |
| 99 return new LocationSummary(kNumInputs, kNumTemps); | |
| 100 } | |
| 101 | |
| 102 | |
| 103 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 104 ASSERT(exception()->IsUse()); | |
| 105 ASSERT(stack_trace()->IsUse()); | |
| 106 compiler->GenerateCallRuntime(cid(), | |
| 107 token_index(), | |
| 108 try_index(), | |
| 109 kReThrowRuntimeEntry); | |
| 110 __ int3(); | |
| 111 } | |
| 112 | |
| 113 | |
| 114 LocationSummary* BranchInstr::MakeLocationSummary() const { | |
| 115 const int kNumInputs = 1; | |
| 116 const int kNumTemps = 0; | |
| 117 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | |
| 118 locs->set_in(0, Location::RequiresRegister()); | |
| 119 return locs; | |
| 120 } | |
| 121 | |
| 122 | |
| 123 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 124 Register value = locs()->in(0).reg(); | |
| 125 | |
| 126 __ CompareObject(value, Bool::ZoneHandle(Bool::True())); | |
| 127 if (compiler->IsNextBlock(false_successor())) { | |
| 128 // If the next block is the false successor we will fall through to it if | |
| 129 // comparison with true fails. | |
| 130 __ j(EQUAL, compiler->GetBlockLabel(true_successor())); | |
| 131 } else { | |
| 132 ASSERT(compiler->IsNextBlock(true_successor())); | |
| 133 // If the next block is the true successor we negate comparison and fall | |
| 134 // through to it. | |
| 135 __ j(NOT_EQUAL, compiler->GetBlockLabel(false_successor())); | |
| 136 } | |
| 137 } | |
| 138 | |
| 139 | |
| 140 LocationSummary* ReturnInstr::MakeLocationSummary() const { | 31 LocationSummary* ReturnInstr::MakeLocationSummary() const { |
| 141 const intptr_t kNumInputs = 1; | 32 const intptr_t kNumInputs = 1; |
| 142 const intptr_t kNumTemps = 1; | 33 const intptr_t kNumTemps = 1; |
| 143 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 34 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); |
| 144 locs->set_in(0, Location::RegisterLocation(RAX)); | 35 locs->set_in(0, Location::RegisterLocation(RAX)); |
| 145 locs->set_temp(0, Location::RequiresRegister()); | 36 locs->set_temp(0, Location::RequiresRegister()); |
| 146 return locs; | 37 return locs; |
| 147 } | 38 } |
| 148 | 39 |
| 149 | 40 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 __ nop(1); | 90 __ nop(1); |
| 200 __ nop(1); | 91 __ nop(1); |
| 201 __ nop(1); | 92 __ nop(1); |
| 202 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, | 93 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, |
| 203 cid(), | 94 cid(), |
| 204 token_index(), | 95 token_index(), |
| 205 CatchClauseNode::kInvalidTryIndex); | 96 CatchClauseNode::kInvalidTryIndex); |
| 206 } | 97 } |
| 207 | 98 |
| 208 | 99 |
| 209 LocationSummary* CurrentContextComp::MakeLocationSummary() const { | |
| 210 return LocationSummary::Make(0, Location::RequiresRegister()); | |
| 211 } | |
| 212 | |
| 213 | |
| 214 void CurrentContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 215 __ movq(locs()->out().reg(), CTX); | |
| 216 } | |
| 217 | |
| 218 | |
| 219 LocationSummary* StoreContextComp::MakeLocationSummary() const { | |
| 220 LocationSummary* summary = new LocationSummary(1, 0); | |
| 221 summary->set_in(0, Location::RegisterLocation(CTX)); | |
| 222 return summary; | |
| 223 } | |
| 224 | |
| 225 | |
| 226 void StoreContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 227 // Nothing to do. Context register were loaded by register allocator. | |
| 228 ASSERT(locs()->in(0).reg() == CTX); | |
| 229 } | |
| 230 | |
| 231 | |
| 232 LocationSummary* StrictCompareComp::MakeLocationSummary() const { | |
| 233 return LocationSummary::Make(2, Location::SameAsFirstInput()); | |
| 234 } | |
| 235 | |
| 236 | |
| 237 void StrictCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 238 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | |
| 239 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | |
| 240 | |
| 241 Register left = locs()->in(0).reg(); | |
| 242 Register right = locs()->in(1).reg(); | |
| 243 Register result = locs()->out().reg(); | |
| 244 | |
| 245 __ cmpq(left, right); | |
| 246 Label load_true, done; | |
| 247 if (kind() == Token::kEQ_STRICT) { | |
| 248 __ j(EQUAL, &load_true, Assembler::kNearJump); | |
| 249 } else { | |
| 250 ASSERT(kind() == Token::kNE_STRICT); | |
| 251 __ j(NOT_EQUAL, &load_true, Assembler::kNearJump); | |
| 252 } | |
| 253 __ LoadObject(result, bool_false); | |
| 254 __ jmp(&done, Assembler::kNearJump); | |
| 255 __ Bind(&load_true); | |
| 256 __ LoadObject(result, bool_true); | |
| 257 __ Bind(&done); | |
| 258 } | |
| 259 | |
| 260 | |
| 261 // Generic summary for call instructions that have all arguments pushed | 100 // Generic summary for call instructions that have all arguments pushed |
| 262 // on the stack and return the result in a fixed register RAX. | 101 // on the stack and return the result in a fixed register RAX. |
| 263 static LocationSummary* MakeCallSummary() { | 102 LocationSummary* Computation::MakeCallSummary() { |
| 264 LocationSummary* result = new LocationSummary(0, 0); | 103 LocationSummary* result = new LocationSummary(0, 0); |
| 265 result->set_out(Location::RegisterLocation(RAX)); | 104 result->set_out(Location::RegisterLocation(RAX)); |
| 266 return result; | 105 return result; |
| 267 } | 106 } |
| 268 | 107 |
| 269 | 108 |
| 270 LocationSummary* ClosureCallComp::MakeLocationSummary() const { | 109 LocationSummary* ClosureCallComp::MakeLocationSummary() const { |
| 271 return MakeCallSummary(); | 110 const intptr_t kNumInputs = 0; |
| 272 } | 111 const intptr_t kNumTemps = 1; |
| 273 | 112 LocationSummary* result = new LocationSummary(kNumInputs, kNumTemps); |
| 274 | 113 result->set_out(Location::RegisterLocation(RAX)); |
| 275 void ClosureCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 114 result->set_temp(0, Location::RegisterLocation(R10)); // Arg. descriptor. |
| 276 ASSERT(VerifyCallComputation(this)); | 115 return result; |
| 277 // The arguments to the stub include the closure. The arguments | |
| 278 // descriptor describes the closure's arguments (and so does not include | |
| 279 // the closure). | |
| 280 int argument_count = ArgumentCount(); | |
| 281 const Array& arguments_descriptor = | |
| 282 CodeGenerator::ArgumentsDescriptor(argument_count - 1, | |
| 283 argument_names()); | |
| 284 __ LoadObject(R10, arguments_descriptor); | |
| 285 | |
| 286 compiler->GenerateCall(token_index(), | |
| 287 try_index(), | |
| 288 &StubCode::CallClosureFunctionLabel(), | |
| 289 PcDescriptors::kOther); | |
| 290 __ Drop(argument_count); | |
| 291 } | |
| 292 | |
| 293 | |
| 294 LocationSummary* InstanceCallComp::MakeLocationSummary() const { | |
| 295 return MakeCallSummary(); | |
| 296 } | |
| 297 | |
| 298 | |
| 299 void InstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 300 ASSERT(VerifyCallComputation(this)); | |
| 301 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | |
| 302 cid(), | |
| 303 token_index(), | |
| 304 try_index()); | |
| 305 compiler->GenerateInstanceCall(cid(), | |
| 306 token_index(), | |
| 307 try_index(), | |
| 308 function_name(), | |
| 309 ArgumentCount(), | |
| 310 argument_names(), | |
| 311 checked_argument_count()); | |
| 312 } | |
| 313 | |
| 314 | |
| 315 LocationSummary* StaticCallComp::MakeLocationSummary() const { | |
| 316 return MakeCallSummary(); | |
| 317 } | |
| 318 | |
| 319 | |
| 320 void StaticCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 321 ASSERT(VerifyCallComputation(this)); | |
| 322 compiler->GenerateStaticCall(cid(), | |
| 323 token_index(), | |
| 324 try_index(), | |
| 325 function(), | |
| 326 ArgumentCount(), | |
| 327 argument_names()); | |
| 328 } | 116 } |
| 329 | 117 |
| 330 | 118 |
| 331 LocationSummary* LoadLocalComp::MakeLocationSummary() const { | 119 LocationSummary* LoadLocalComp::MakeLocationSummary() const { |
| 332 return LocationSummary::Make(0, Location::RequiresRegister()); | 120 return LocationSummary::Make(0, Location::RequiresRegister()); |
| 333 } | 121 } |
| 334 | 122 |
| 335 | 123 |
| 336 void LoadLocalComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 124 void LoadLocalComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 337 Register result = locs()->out().reg(); | 125 Register result = locs()->out().reg(); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 361 Register result = locs()->out().reg(); | 149 Register result = locs()->out().reg(); |
| 362 if (value().IsSmi()) { | 150 if (value().IsSmi()) { |
| 363 int64_t imm = reinterpret_cast<int64_t>(value().raw()); | 151 int64_t imm = reinterpret_cast<int64_t>(value().raw()); |
| 364 __ movq(result, Immediate(imm)); | 152 __ movq(result, Immediate(imm)); |
| 365 } else { | 153 } else { |
| 366 __ LoadObject(result, value()); | 154 __ LoadObject(result, value()); |
| 367 } | 155 } |
| 368 } | 156 } |
| 369 | 157 |
| 370 | 158 |
| 371 LocationSummary* UseVal::MakeLocationSummary() const { | |
| 372 return NULL; | |
| 373 } | |
| 374 | |
| 375 | |
| 376 void UseVal::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 377 UNIMPLEMENTED(); | |
| 378 } | |
| 379 | |
| 380 | |
| 381 LocationSummary* AssertAssignableComp::MakeLocationSummary() const { | 159 LocationSummary* AssertAssignableComp::MakeLocationSummary() const { |
| 382 LocationSummary* summary = new LocationSummary(3, 0); | 160 LocationSummary* summary = new LocationSummary(3, 0); |
| 383 summary->set_in(0, Location::RegisterLocation(RAX)); | 161 summary->set_in(0, Location::RegisterLocation(RAX)); // Value. |
| 384 summary->set_in(1, Location::RegisterLocation(RCX)); | 162 summary->set_in(1, Location::RegisterLocation(RCX)); // Instantiator. |
| 385 summary->set_in(2, Location::RegisterLocation(RDX)); | 163 summary->set_in(2, Location::RegisterLocation(RDX)); // Type arguments. |
| 386 summary->set_out(Location::RegisterLocation(RAX)); | 164 summary->set_out(Location::RegisterLocation(RAX)); |
| 387 return summary; | 165 return summary; |
| 388 } | 166 } |
| 389 | 167 |
| 390 | 168 |
| 391 void AssertAssignableComp::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 392 ASSERT(locs()->in(0).reg() == RAX); // Value. | |
| 393 ASSERT(locs()->in(1).reg() == RCX); // Instantiator. | |
| 394 ASSERT(locs()->in(2).reg() == RDX); // Instantiator type arguments. | |
| 395 | |
| 396 compiler->GenerateAssertAssignable(cid(), | |
| 397 token_index(), | |
| 398 try_index(), | |
| 399 dst_type(), | |
| 400 dst_name()); | |
| 401 ASSERT(locs()->in(0).reg() == locs()->out().reg()); | |
| 402 } | |
| 403 | |
| 404 | |
| 405 LocationSummary* AssertBooleanComp::MakeLocationSummary() const { | |
| 406 return LocationSummary::Make(1, Location::SameAsFirstInput()); | |
| 407 } | |
| 408 | |
| 409 | |
| 410 void AssertBooleanComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 169 void AssertBooleanComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 411 Register obj = locs()->in(0).reg(); | 170 Register obj = locs()->in(0).reg(); |
| 412 Register result = locs()->out().reg(); | 171 Register result = locs()->out().reg(); |
| 413 | 172 |
| 414 // Check that the type of the value is allowed in conditional context. | 173 // Check that the type of the value is allowed in conditional context. |
| 415 // Call the runtime if the object is not bool::true or bool::false. | 174 // Call the runtime if the object is not bool::true or bool::false. |
| 416 Label done; | 175 Label done; |
| 417 __ CompareObject(obj, Bool::ZoneHandle(Bool::True())); | 176 __ CompareObject(obj, Bool::ZoneHandle(Bool::True())); |
| 418 __ j(EQUAL, &done, Assembler::kNearJump); | 177 __ j(EQUAL, &done, Assembler::kNearJump); |
| 419 __ CompareObject(obj, Bool::ZoneHandle(Bool::False())); | 178 __ CompareObject(obj, Bool::ZoneHandle(Bool::False())); |
| 420 __ j(EQUAL, &done, Assembler::kNearJump); | 179 __ j(EQUAL, &done, Assembler::kNearJump); |
| 421 | 180 |
| 422 __ pushq(Immediate(Smi::RawValue(token_index()))); // Source location. | 181 __ pushq(Immediate(Smi::RawValue(token_index()))); // Source location. |
| 423 __ pushq(obj); // Push the source object. | 182 __ pushq(obj); // Push the source object. |
| 424 compiler->GenerateCallRuntime(cid(), | 183 compiler->GenerateCallRuntime(cid(), |
| 425 token_index(), | 184 token_index(), |
| 426 try_index(), | 185 try_index(), |
| 427 kConditionTypeErrorRuntimeEntry); | 186 kConditionTypeErrorRuntimeEntry); |
| 428 // We should never return here. | 187 // We should never return here. |
| 429 __ int3(); | 188 __ int3(); |
| 430 | 189 |
| 431 __ Bind(&done); | 190 __ Bind(&done); |
| 432 ASSERT(obj == result); | 191 ASSERT(obj == result); |
| 433 } | 192 } |
| 434 | 193 |
| 435 | 194 |
| 436 LocationSummary* EqualityCompareComp::MakeLocationSummary() const { | 195 LocationSummary* EqualityCompareComp::MakeLocationSummary() const { |
| 437 LocationSummary* locs = new LocationSummary(2, 0); | 196 LocationSummary* locs = new LocationSummary(2, 0); |
| 438 locs->set_in(0, Location::RegisterLocation(RAX)); | 197 locs->set_in(0, Location::RequiresRegister()); |
| 439 locs->set_in(1, Location::RequiresRegister()); | 198 locs->set_in(1, Location::RequiresRegister()); |
| 440 locs->set_out(Location::RegisterLocation(RAX)); | 199 locs->set_out(Location::RegisterLocation(RAX)); |
| 441 return locs; | 200 return locs; |
| 442 } | 201 } |
| 443 | 202 |
| 444 | 203 |
| 445 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 204 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 446 Register left = locs()->in(0).reg(); | 205 Register left = locs()->in(0).reg(); |
| 447 Register right = locs()->in(1).reg(); | 206 Register right = locs()->in(1).reg(); |
| 448 Register result = locs()->out().reg(); | 207 Register result = locs()->out().reg(); |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 620 | 379 |
| 621 | 380 |
| 622 void LoadInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 381 void LoadInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 623 Register instance = locs()->in(0).reg(); | 382 Register instance = locs()->in(0).reg(); |
| 624 Register result = locs()->out().reg(); | 383 Register result = locs()->out().reg(); |
| 625 | 384 |
| 626 __ movq(result, FieldAddress(instance, field().Offset())); | 385 __ movq(result, FieldAddress(instance, field().Offset())); |
| 627 } | 386 } |
| 628 | 387 |
| 629 | 388 |
| 630 LocationSummary* StoreInstanceFieldComp::MakeLocationSummary() const { | |
| 631 return LocationSummary::Make(2, Location::RequiresRegister()); | |
| 632 } | |
| 633 | |
| 634 | |
| 635 void StoreInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 636 ASSERT(VerifyValues(instance(), value())); | |
| 637 Register instance = locs()->in(0).reg(); | |
| 638 Register value = locs()->in(1).reg(); | |
| 639 Register result = locs()->out().reg(); | |
| 640 | |
| 641 __ StoreIntoObject(instance, FieldAddress(instance, field().Offset()), | |
| 642 value); | |
| 643 // TODO(fschneider): Consider eliminating this move by specifying a | |
| 644 // SameAsSecondInput for the result. | |
| 645 if (result != value) { | |
| 646 __ movq(result, value); | |
| 647 } | |
| 648 } | |
| 649 | |
| 650 | |
| 651 LocationSummary* LoadStaticFieldComp::MakeLocationSummary() const { | 389 LocationSummary* LoadStaticFieldComp::MakeLocationSummary() const { |
| 652 return LocationSummary::Make(0, Location::RequiresRegister()); | 390 return LocationSummary::Make(0, Location::RequiresRegister()); |
| 653 } | 391 } |
| 654 | 392 |
| 655 | 393 |
| 656 void LoadStaticFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 394 void LoadStaticFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 657 Register result = locs()->out().reg(); | 395 Register result = locs()->out().reg(); |
| 658 __ LoadObject(result, field()); | 396 __ LoadObject(result, field()); |
| 659 __ movq(result, FieldAddress(result, Field::value_offset())); | 397 __ movq(result, FieldAddress(result, Field::value_offset())); |
| 660 } | 398 } |
| 661 | 399 |
| 662 | 400 |
| 663 LocationSummary* StoreStaticFieldComp::MakeLocationSummary() const { | |
| 664 LocationSummary* locs = new LocationSummary(1, 1); | |
| 665 locs->set_in(0, Location::RequiresRegister()); | |
| 666 locs->set_temp(0, Location::RequiresRegister()); | |
| 667 locs->set_out(Location::SameAsFirstInput()); | |
| 668 return locs; | |
| 669 } | |
| 670 | |
| 671 | |
| 672 void StoreStaticFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 673 Register value = locs()->in(0).reg(); | |
| 674 Register temp = locs()->temp(0).reg(); | |
| 675 ASSERT(locs()->out().reg() == value); | |
| 676 | |
| 677 __ LoadObject(temp, field()); | |
| 678 __ StoreIntoObject(temp, FieldAddress(temp, Field::value_offset()), value); | |
| 679 } | |
| 680 | |
| 681 | |
| 682 LocationSummary* BooleanNegateComp::MakeLocationSummary() const { | |
| 683 return LocationSummary::Make(1, Location::RequiresRegister()); | |
| 684 } | |
| 685 | |
| 686 | |
| 687 void BooleanNegateComp::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 688 Register value = locs()->in(0).reg(); | |
| 689 Register result = locs()->out().reg(); | |
| 690 | |
| 691 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | |
| 692 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | |
| 693 Label done; | |
| 694 __ LoadObject(result, bool_true); | |
| 695 __ cmpq(result, value); | |
| 696 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | |
| 697 __ LoadObject(result, bool_false); | |
| 698 __ Bind(&done); | |
| 699 } | |
| 700 | |
| 701 | |
| 702 LocationSummary* InstanceOfComp::MakeLocationSummary() const { | 401 LocationSummary* InstanceOfComp::MakeLocationSummary() const { |
| 703 LocationSummary* summary = new LocationSummary(3, 0); | 402 LocationSummary* summary = new LocationSummary(3, 0); |
| 704 summary->set_in(0, Location::RegisterLocation(RAX)); | 403 summary->set_in(0, Location::RegisterLocation(RAX)); |
| 705 summary->set_in(1, Location::RegisterLocation(RCX)); | 404 summary->set_in(1, Location::RegisterLocation(RCX)); |
| 706 summary->set_in(2, Location::RegisterLocation(RDX)); | 405 summary->set_in(2, Location::RegisterLocation(RDX)); |
| 707 summary->set_out(Location::RegisterLocation(RAX)); | 406 summary->set_out(Location::RegisterLocation(RAX)); |
| 708 return summary; | 407 return summary; |
| 709 } | 408 } |
| 710 | 409 |
| 711 | 410 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 743 Register result_reg = locs()->out().reg(); | 442 Register result_reg = locs()->out().reg(); |
| 744 | 443 |
| 745 // 1. Allocate the array. R10 = length, RBX = element type. | 444 // 1. Allocate the array. R10 = length, RBX = element type. |
| 746 ASSERT(temp_reg == R10); | 445 ASSERT(temp_reg == R10); |
| 747 ASSERT(locs()->in(0).reg() == RBX); | 446 ASSERT(locs()->in(0).reg() == RBX); |
| 748 __ movq(temp_reg, Immediate(Smi::RawValue(ElementCount()))); | 447 __ movq(temp_reg, Immediate(Smi::RawValue(ElementCount()))); |
| 749 compiler->GenerateCall(token_index(), | 448 compiler->GenerateCall(token_index(), |
| 750 try_index(), | 449 try_index(), |
| 751 &StubCode::AllocateArrayLabel(), | 450 &StubCode::AllocateArrayLabel(), |
| 752 PcDescriptors::kOther); | 451 PcDescriptors::kOther); |
| 753 | 452 ASSERT(result_reg == RAX); |
| 754 // 2. Initialize the array in result_reg with the element values. | 453 // 2. Initialize the array in result_reg with the element values. |
| 755 __ leaq(temp_reg, FieldAddress(result_reg, Array::data_offset())); | 454 __ leaq(temp_reg, FieldAddress(result_reg, Array::data_offset())); |
| 756 for (int i = ElementCount() - 1; i >= 0; --i) { | 455 for (int i = ElementCount() - 1; i >= 0; --i) { |
| 757 ASSERT(ElementAt(i)->IsUse()); | 456 ASSERT(ElementAt(i)->IsUse()); |
| 758 __ popq(Address(temp_reg, i * kWordSize)); | 457 __ popq(Address(temp_reg, i * kWordSize)); |
| 759 } | 458 } |
| 760 } | 459 } |
| 761 | 460 |
| 762 | 461 |
| 763 LocationSummary* CreateClosureComp::MakeLocationSummary() const { | |
| 764 return MakeCallSummary(); | |
| 765 } | |
| 766 | |
| 767 | |
| 768 void CreateClosureComp::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 769 const Function& closure_function = function(); | |
| 770 const Code& stub = Code::Handle( | |
| 771 StubCode::GetAllocationStubForClosure(closure_function)); | |
| 772 const ExternalLabel label(closure_function.ToCString(), stub.EntryPoint()); | |
| 773 compiler->GenerateCall(token_index(), try_index(), &label, | |
| 774 PcDescriptors::kOther); | |
| 775 __ Drop(2); // Discard type arguments and receiver. | |
| 776 } | |
| 777 | |
| 778 | |
| 779 LocationSummary* AllocateObjectComp::MakeLocationSummary() const { | |
| 780 return MakeCallSummary(); | |
| 781 } | |
| 782 | |
| 783 | |
| 784 void AllocateObjectComp::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 785 const Class& cls = Class::ZoneHandle(constructor().owner()); | |
| 786 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls)); | |
| 787 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); | |
| 788 compiler->GenerateCall(token_index(), | |
| 789 try_index(), | |
| 790 &label, | |
| 791 PcDescriptors::kOther); | |
| 792 __ Drop(arguments().length()); // Discard arguments. | |
| 793 } | |
| 794 | |
| 795 | |
| 796 LocationSummary* AllocateObjectWithBoundsCheckComp:: | 462 LocationSummary* AllocateObjectWithBoundsCheckComp:: |
| 797 MakeLocationSummary() const { | 463 MakeLocationSummary() const { |
| 798 return LocationSummary::Make(2, Location::RequiresRegister()); | 464 return LocationSummary::Make(2, Location::RequiresRegister()); |
| 799 } | 465 } |
| 800 | 466 |
| 801 | 467 |
| 802 void AllocateObjectWithBoundsCheckComp::EmitNativeCode( | 468 void AllocateObjectWithBoundsCheckComp::EmitNativeCode( |
| 803 FlowGraphCompiler* compiler) { | 469 FlowGraphCompiler* compiler) { |
| 804 const Class& cls = Class::ZoneHandle(constructor().owner()); | 470 const Class& cls = Class::ZoneHandle(constructor().owner()); |
| 805 Register type_arguments = locs()->in(0).reg(); | 471 Register type_arguments = locs()->in(0).reg(); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 829 | 495 |
| 830 | 496 |
| 831 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 497 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 832 Register obj = locs()->in(0).reg(); | 498 Register obj = locs()->in(0).reg(); |
| 833 Register result = locs()->out().reg(); | 499 Register result = locs()->out().reg(); |
| 834 | 500 |
| 835 __ movq(result, FieldAddress(obj, offset_in_bytes())); | 501 __ movq(result, FieldAddress(obj, offset_in_bytes())); |
| 836 } | 502 } |
| 837 | 503 |
| 838 | 504 |
| 839 LocationSummary* StoreVMFieldComp::MakeLocationSummary() const { | |
| 840 return LocationSummary::Make(2, Location::SameAsFirstInput()); | |
| 841 } | |
| 842 | |
| 843 | |
| 844 void StoreVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 845 Register value_reg = locs()->in(0).reg(); | |
| 846 Register dest_reg = locs()->in(1).reg(); | |
| 847 ASSERT(value_reg == locs()->out().reg()); | |
| 848 | |
| 849 __ StoreIntoObject(dest_reg, FieldAddress(dest_reg, offset_in_bytes()), | |
| 850 value_reg); | |
| 851 } | |
| 852 | |
| 853 | |
| 854 LocationSummary* InstantiateTypeArgumentsComp::MakeLocationSummary() const { | 505 LocationSummary* InstantiateTypeArgumentsComp::MakeLocationSummary() const { |
| 855 const intptr_t kNumInputs = 1; | 506 const intptr_t kNumInputs = 1; |
| 856 const intptr_t kNumTemps = 0; | 507 const intptr_t kNumTemps = 0; |
| 857 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 508 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); |
| 858 locs->set_in(0, Location::RequiresRegister()); | 509 locs->set_in(0, Location::RequiresRegister()); |
| 859 locs->set_out(Location::SameAsFirstInput()); | 510 locs->set_out(Location::SameAsFirstInput()); |
| 860 return locs; | 511 return locs; |
| 861 } | 512 } |
| 862 | 513 |
| 863 | 514 |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1045 __ movq(R10, Immediate(num_context_variables())); | 696 __ movq(R10, Immediate(num_context_variables())); |
| 1046 const ExternalLabel label("alloc_context", | 697 const ExternalLabel label("alloc_context", |
| 1047 StubCode::AllocateContextEntryPoint()); | 698 StubCode::AllocateContextEntryPoint()); |
| 1048 compiler->GenerateCall(token_index(), | 699 compiler->GenerateCall(token_index(), |
| 1049 try_index(), | 700 try_index(), |
| 1050 &label, | 701 &label, |
| 1051 PcDescriptors::kOther); | 702 PcDescriptors::kOther); |
| 1052 } | 703 } |
| 1053 | 704 |
| 1054 | 705 |
| 1055 LocationSummary* ChainContextComp::MakeLocationSummary() const { | |
| 1056 return LocationSummary::Make(1, Location::NoLocation()); | |
| 1057 } | |
| 1058 | |
| 1059 | |
| 1060 void ChainContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 1061 Register context_value = locs()->in(0).reg(); | |
| 1062 | |
| 1063 // Chain the new context in context_value to its parent in CTX. | |
| 1064 __ StoreIntoObject(context_value, | |
| 1065 FieldAddress(context_value, Context::parent_offset()), | |
| 1066 CTX); | |
| 1067 // Set new context as current context. | |
| 1068 __ movq(CTX, context_value); | |
| 1069 } | |
| 1070 | |
| 1071 | |
| 1072 LocationSummary* CloneContextComp::MakeLocationSummary() const { | 706 LocationSummary* CloneContextComp::MakeLocationSummary() const { |
| 1073 return LocationSummary::Make(1, Location::RequiresRegister()); | 707 return LocationSummary::Make(1, Location::RequiresRegister()); |
| 1074 } | 708 } |
| 1075 | 709 |
| 1076 | 710 |
| 1077 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 711 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1078 Register context_value = locs()->in(0).reg(); | 712 Register context_value = locs()->in(0).reg(); |
| 1079 Register result = locs()->out().reg(); | 713 Register result = locs()->out().reg(); |
| 1080 | 714 |
| 1081 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 715 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1429 } else { | 1063 } else { |
| 1430 UNREACHABLE(); | 1064 UNREACHABLE(); |
| 1431 } | 1065 } |
| 1432 } | 1066 } |
| 1433 | 1067 |
| 1434 } // namespace dart | 1068 } // namespace dart |
| 1435 | 1069 |
| 1436 #undef __ | 1070 #undef __ |
| 1437 | 1071 |
| 1438 #endif // defined TARGET_ARCH_X64 | 1072 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |