Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(222)

Side by Side Diff: runtime/vm/intermediate_language_ia32.cc

Issue 10543013: More code for ia32, more shared code. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698