| 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/flow_graph_compiler.h" | 8 #include "vm/flow_graph_compiler.h" |
| 9 | 9 |
| 10 #include "vm/ast_printer.h" | 10 #include "vm/ast_printer.h" |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 63 | 63 |
| 64 | 64 |
| 65 void FlowGraphCompiler::GenerateAssertAssignable(intptr_t node_id, | 65 void FlowGraphCompiler::GenerateAssertAssignable(intptr_t node_id, |
| 66 intptr_t token_index, | 66 intptr_t token_index, |
| 67 const AbstractType& dst_type, | 67 const AbstractType& dst_type, |
| 68 const String& dst_name) { | 68 const String& dst_name) { |
| 69 Bailout("GenerateAssertAssignable"); | 69 Bailout("GenerateAssertAssignable"); |
| 70 } | 70 } |
| 71 | 71 |
| 72 | 72 |
| 73 void FlowGraphCompiler::LoadValue(Value* value) { | 73 void FlowGraphCompiler::LoadValue(Register dst, Value* value) { |
| 74 if (value->IsConstant()) { | 74 if (value->IsConstant()) { |
| 75 ConstantVal* constant = value->AsConstant(); | 75 ConstantVal* constant = value->AsConstant(); |
| 76 if (constant->instance().IsSmi()) { | 76 if (constant->instance().IsSmi()) { |
| 77 int64_t imm = reinterpret_cast<int64_t>(constant->instance().raw()); | 77 int64_t imm = reinterpret_cast<int64_t>(constant->instance().raw()); |
| 78 __ movq(RAX, Immediate(imm)); | 78 __ movq(dst, Immediate(imm)); |
| 79 } else { | 79 } else { |
| 80 __ LoadObject(RAX, value->AsConstant()->instance()); | 80 __ LoadObject(dst, value->AsConstant()->instance()); |
| 81 } | 81 } |
| 82 } else { | 82 } else { |
| 83 ASSERT(value->IsTemp()); | 83 ASSERT(value->IsTemp()); |
| 84 __ popq(RAX); | 84 __ popq(dst); |
| 85 } | 85 } |
| 86 } | 86 } |
| 87 | 87 |
| 88 | 88 |
| 89 void FlowGraphCompiler::VisitTemp(TempVal* val) { | 89 void FlowGraphCompiler::VisitTemp(TempVal* val) { |
| 90 LoadValue(val); | 90 LoadValue(RAX, val); |
| 91 } | 91 } |
| 92 | 92 |
| 93 | 93 |
| 94 void FlowGraphCompiler::VisitConstant(ConstantVal* val) { | 94 void FlowGraphCompiler::VisitConstant(ConstantVal* val) { |
| 95 LoadValue(val); | 95 LoadValue(RAX, val); |
| 96 } | 96 } |
| 97 | 97 |
| 98 | 98 |
| 99 void FlowGraphCompiler::VisitAssertAssignable(AssertAssignableComp* comp) { | 99 void FlowGraphCompiler::VisitAssertAssignable(AssertAssignableComp* comp) { |
| 100 Bailout("AssertAssignableComp"); | 100 Bailout("AssertAssignableComp"); |
| 101 } | 101 } |
| 102 | 102 |
| 103 | 103 |
| 104 // True iff. the arguments to a call will be properly pushed and can | 104 // True iff. the arguments to a call will be properly pushed and can |
| 105 // be popped after the call. | 105 // be popped after the call. |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 203 Bailout("load of context variable"); | 203 Bailout("load of context variable"); |
| 204 } | 204 } |
| 205 __ movq(RAX, Address(RBP, comp->local().index() * kWordSize)); | 205 __ movq(RAX, Address(RBP, comp->local().index() * kWordSize)); |
| 206 } | 206 } |
| 207 | 207 |
| 208 | 208 |
| 209 void FlowGraphCompiler::VisitStoreLocal(StoreLocalComp* comp) { | 209 void FlowGraphCompiler::VisitStoreLocal(StoreLocalComp* comp) { |
| 210 if (comp->local().is_captured()) { | 210 if (comp->local().is_captured()) { |
| 211 Bailout("store to context variable"); | 211 Bailout("store to context variable"); |
| 212 } | 212 } |
| 213 LoadValue(comp->value()); | 213 LoadValue(RAX, comp->value()); |
| 214 __ movq(Address(RBP, comp->local().index() * kWordSize), RAX); | 214 __ movq(Address(RBP, comp->local().index() * kWordSize), RAX); |
| 215 } | 215 } |
| 216 | 216 |
| 217 | 217 |
| 218 void FlowGraphCompiler::VisitNativeCall(NativeCallComp* comp) { | 218 void FlowGraphCompiler::VisitNativeCall(NativeCallComp* comp) { |
| 219 Bailout("NativeCallComp"); | 219 Bailout("NativeCallComp"); |
| 220 } | 220 } |
| 221 | 221 |
| 222 | 222 |
| 223 void FlowGraphCompiler::VisitLoadInstanceField(LoadInstanceFieldComp* comp) { | 223 void FlowGraphCompiler::VisitLoadInstanceField(LoadInstanceFieldComp* comp) { |
| 224 LoadValue(comp->instance()); // -> RAX. | 224 LoadValue(RAX, comp->instance()); |
| 225 __ movq(RAX, FieldAddress(RAX, comp->field().Offset())); | 225 __ movq(RAX, FieldAddress(RAX, comp->field().Offset())); |
| 226 } | 226 } |
| 227 | 227 |
| 228 | 228 |
| 229 void FlowGraphCompiler::VisitStoreInstanceField(StoreInstanceFieldComp* comp) { | 229 void FlowGraphCompiler::VisitStoreInstanceField(StoreInstanceFieldComp* comp) { |
| 230 VerifyValues(comp->instance(), comp->value()); | 230 VerifyValues(comp->instance(), comp->value()); |
| 231 LoadValue(comp->value()); | 231 LoadValue(RDX, comp->value()); |
| 232 __ movq(R10, RAX); | 232 LoadValue(RAX, comp->instance()); |
| 233 LoadValue(comp->instance()); // -> RAX. | 233 __ StoreIntoObject(RAX, FieldAddress(RAX, comp->field().Offset()), RDX); |
| 234 __ StoreIntoObject(RAX, FieldAddress(RAX, comp->field().Offset()), R10); | |
| 235 } | 234 } |
| 236 | 235 |
| 237 | 236 |
| 238 | 237 |
| 239 void FlowGraphCompiler::VisitLoadStaticField(LoadStaticFieldComp* comp) { | 238 void FlowGraphCompiler::VisitLoadStaticField(LoadStaticFieldComp* comp) { |
| 240 __ LoadObject(RDX, comp->field()); | 239 __ LoadObject(RDX, comp->field()); |
| 241 __ movq(RAX, FieldAddress(RDX, Field::value_offset())); | 240 __ movq(RAX, FieldAddress(RDX, Field::value_offset())); |
| 242 } | 241 } |
| 243 | 242 |
| 244 | 243 |
| 245 void FlowGraphCompiler::VisitStoreStaticField(StoreStaticFieldComp* comp) { | 244 void FlowGraphCompiler::VisitStoreStaticField(StoreStaticFieldComp* comp) { |
| 246 LoadValue(comp->value()); | 245 LoadValue(RAX, comp->value()); |
| 247 __ LoadObject(RDX, comp->field()); | 246 __ LoadObject(RDX, comp->field()); |
| 248 __ StoreIntoObject(RDX, FieldAddress(RDX, Field::value_offset()), RAX); | 247 __ StoreIntoObject(RDX, FieldAddress(RDX, Field::value_offset()), RAX); |
| 249 } | 248 } |
| 250 | 249 |
| 251 | 250 |
| 252 void FlowGraphCompiler::VisitStoreIndexed(StoreIndexedComp* comp) { | 251 void FlowGraphCompiler::VisitStoreIndexed(StoreIndexedComp* comp) { |
| 253 // Call operator []= but preserve the third argument value under the | 252 // Call operator []= but preserve the third argument value under the |
| 254 // arguments as the result of the computation. | 253 // arguments as the result of the computation. |
| 255 const String& function_name = | 254 const String& function_name = |
| 256 String::ZoneHandle(String::NewSymbol(Token::Str(Token::kASSIGN_INDEX))); | 255 String::ZoneHandle(String::NewSymbol(Token::Str(Token::kASSIGN_INDEX))); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 284 EmitInstanceCall(comp->node_id(), comp->token_index(), function_name, 2, | 283 EmitInstanceCall(comp->node_id(), comp->token_index(), function_name, 2, |
| 285 Array::ZoneHandle(), 1); | 284 Array::ZoneHandle(), 1); |
| 286 __ popq(RAX); | 285 __ popq(RAX); |
| 287 } | 286 } |
| 288 | 287 |
| 289 | 288 |
| 290 void FlowGraphCompiler::VisitBooleanNegate(BooleanNegateComp* comp) { | 289 void FlowGraphCompiler::VisitBooleanNegate(BooleanNegateComp* comp) { |
| 291 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 290 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
| 292 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | 291 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); |
| 293 Label done; | 292 Label done; |
| 294 LoadValue(comp->value()); | 293 LoadValue(RDX, comp->value()); |
| 295 __ movq(RDX, RAX); | |
| 296 __ LoadObject(RAX, bool_true); | 294 __ LoadObject(RAX, bool_true); |
| 297 __ cmpq(RAX, RDX); | 295 __ cmpq(RAX, RDX); |
| 298 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 296 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
| 299 __ LoadObject(RAX, bool_false); | 297 __ LoadObject(RAX, bool_false); |
| 300 __ Bind(&done); | 298 __ Bind(&done); |
| 301 } | 299 } |
| 302 | 300 |
| 303 | 301 |
| 304 void FlowGraphCompiler::VisitInstanceOf(InstanceOfComp* comp) { | 302 void FlowGraphCompiler::VisitInstanceOf(InstanceOfComp* comp) { |
| 305 Bailout("InstanceOf"); | 303 Bailout("InstanceOf"); |
| 306 } | 304 } |
| 307 | 305 |
| 308 | 306 |
| 307 void FlowGraphCompiler::VisitCreateArray(CreateArrayComp* comp) { |
| 308 // 1. Allocate the array. R10 = length, RBX = element type. |
| 309 __ movq(R10, Immediate(Smi::RawValue(comp->ElementCount()))); |
| 310 const AbstractTypeArguments& element_type = comp->type_arguments(); |
| 311 ASSERT(element_type.IsNull() || element_type.IsInstantiated()); |
| 312 __ LoadObject(RBX, element_type); |
| 313 GenerateCall(comp->token_index(), |
| 314 &StubCode::AllocateArrayLabel(), |
| 315 PcDescriptors::kOther); |
| 316 |
| 317 // 2. Initialize the array in RAX with the element values. |
| 318 __ leaq(RCX, FieldAddress(RAX, Array::data_offset())); |
| 319 for (int i = comp->ElementCount() - 1; i >= 0; --i) { |
| 320 if (comp->ElementAt(i)->IsTemp()) { |
| 321 __ popq(Address(RCX, i * kWordSize)); |
| 322 } else { |
| 323 LoadValue(RDX, comp->ElementAt(i)); |
| 324 __ movq(Address(RCX, i * kWordSize), RDX); |
| 325 } |
| 326 } |
| 327 } |
| 328 |
| 329 |
| 309 void FlowGraphCompiler::VisitBlocks( | 330 void FlowGraphCompiler::VisitBlocks( |
| 310 const GrowableArray<BlockEntryInstr*>& blocks) { | 331 const GrowableArray<BlockEntryInstr*>& blocks) { |
| 311 for (intptr_t i = blocks.length() - 1; i >= 0; --i) { | 332 for (intptr_t i = blocks.length() - 1; i >= 0; --i) { |
| 312 // Compile the block entry. | 333 // Compile the block entry. |
| 313 current_block_ = blocks[i]; | 334 current_block_ = blocks[i]; |
| 314 Instruction* instr = current_block()->Accept(this); | 335 Instruction* instr = current_block()->Accept(this); |
| 315 // Compile all successors until an exit, branch, or a block entry. | 336 // Compile all successors until an exit, branch, or a block entry. |
| 316 while ((instr != NULL) && !instr->IsBlockEntry()) { | 337 while ((instr != NULL) && !instr->IsBlockEntry()) { |
| 317 instr = instr->Accept(this); | 338 instr = instr->Accept(this); |
| 318 } | 339 } |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 367 } | 388 } |
| 368 | 389 |
| 369 | 390 |
| 370 void FlowGraphCompiler::VisitBind(BindInstr* instr) { | 391 void FlowGraphCompiler::VisitBind(BindInstr* instr) { |
| 371 instr->computation()->Accept(this); | 392 instr->computation()->Accept(this); |
| 372 __ pushq(RAX); | 393 __ pushq(RAX); |
| 373 } | 394 } |
| 374 | 395 |
| 375 | 396 |
| 376 void FlowGraphCompiler::VisitReturn(ReturnInstr* instr) { | 397 void FlowGraphCompiler::VisitReturn(ReturnInstr* instr) { |
| 377 LoadValue(instr->value()); | 398 LoadValue(RAX, instr->value()); |
| 378 | 399 |
| 379 #ifdef DEBUG | 400 #ifdef DEBUG |
| 380 // Check that the entry stack size matches the exit stack size. | 401 // Check that the entry stack size matches the exit stack size. |
| 381 __ movq(R10, RBP); | 402 __ movq(R10, RBP); |
| 382 __ subq(R10, RSP); | 403 __ subq(R10, RSP); |
| 383 __ cmpq(R10, Immediate(stack_local_count() * kWordSize)); | 404 __ cmpq(R10, Immediate(stack_local_count() * kWordSize)); |
| 384 Label stack_ok; | 405 Label stack_ok; |
| 385 __ j(EQUAL, &stack_ok, Assembler::kNearJump); | 406 __ j(EQUAL, &stack_ok, Assembler::kNearJump); |
| 386 __ Stop("Exit stack size does not match the entry stack size."); | 407 __ Stop("Exit stack size does not match the entry stack size."); |
| 387 __ Bind(&stack_ok); | 408 __ Bind(&stack_ok); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 420 | 441 |
| 421 void FlowGraphCompiler::VisitBranch(BranchInstr* instr) { | 442 void FlowGraphCompiler::VisitBranch(BranchInstr* instr) { |
| 422 // Determine if the true branch is fall through (!negated) or the false | 443 // Determine if the true branch is fall through (!negated) or the false |
| 423 // branch is. They cannot both be backwards branches. | 444 // branch is. They cannot both be backwards branches. |
| 424 intptr_t index = blocks_->length() - current_block()->block_number() - 1; | 445 intptr_t index = blocks_->length() - current_block()->block_number() - 1; |
| 425 ASSERT(index > 0); | 446 ASSERT(index > 0); |
| 426 | 447 |
| 427 bool negated = ((*blocks_)[index - 1] == instr->false_successor()); | 448 bool negated = ((*blocks_)[index - 1] == instr->false_successor()); |
| 428 ASSERT(!negated == ((*blocks_)[index - 1] == instr->true_successor())); | 449 ASSERT(!negated == ((*blocks_)[index - 1] == instr->true_successor())); |
| 429 | 450 |
| 430 LoadValue(instr->value()); | 451 LoadValue(RAX, instr->value()); |
| 431 __ LoadObject(RDX, Bool::ZoneHandle(Bool::True())); | 452 __ LoadObject(RDX, Bool::ZoneHandle(Bool::True())); |
| 432 __ cmpq(RAX, RDX); | 453 __ cmpq(RAX, RDX); |
| 433 if (negated) { | 454 if (negated) { |
| 434 __ j(EQUAL, &block_info_[instr->true_successor()->block_number()]->label); | 455 __ j(EQUAL, &block_info_[instr->true_successor()->block_number()]->label); |
| 435 } else { | 456 } else { |
| 436 __ j(NOT_EQUAL, | 457 __ j(NOT_EQUAL, |
| 437 &block_info_[instr->false_successor()->block_number()]->label); | 458 &block_info_[instr->false_successor()->block_number()]->label); |
| 438 } | 459 } |
| 439 } | 460 } |
| 440 | 461 |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 572 void FlowGraphCompiler::FinalizeExceptionHandlers(const Code& code) { | 593 void FlowGraphCompiler::FinalizeExceptionHandlers(const Code& code) { |
| 573 // We don't compile exception handlers yet. | 594 // We don't compile exception handlers yet. |
| 574 code.set_exception_handlers( | 595 code.set_exception_handlers( |
| 575 ExceptionHandlers::Handle(ExceptionHandlers::New(0))); | 596 ExceptionHandlers::Handle(ExceptionHandlers::New(0))); |
| 576 } | 597 } |
| 577 | 598 |
| 578 | 599 |
| 579 } // namespace dart | 600 } // namespace dart |
| 580 | 601 |
| 581 #endif // defined TARGET_ARCH_X64 | 602 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |