| 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 13 matching lines...) Expand all Loading... |
| 24 | 24 |
| 25 FlowGraphCompiler::FlowGraphCompiler( | 25 FlowGraphCompiler::FlowGraphCompiler( |
| 26 Assembler* assembler, | 26 Assembler* assembler, |
| 27 const ParsedFunction& parsed_function, | 27 const ParsedFunction& parsed_function, |
| 28 const GrowableArray<BlockEntryInstr*>& block_order) | 28 const GrowableArray<BlockEntryInstr*>& block_order) |
| 29 : FlowGraphVisitor(block_order), | 29 : FlowGraphVisitor(block_order), |
| 30 assembler_(assembler), | 30 assembler_(assembler), |
| 31 parsed_function_(parsed_function), | 31 parsed_function_(parsed_function), |
| 32 block_info_(block_order.length()), | 32 block_info_(block_order.length()), |
| 33 current_block_(NULL), | 33 current_block_(NULL), |
| 34 pc_descriptors_list_(new DescriptorList()) { | 34 pc_descriptors_list_(new DescriptorList()), |
| 35 exception_handlers_list_(new ExceptionHandlerList()) { |
| 35 for (int i = 0; i < block_order.length(); ++i) { | 36 for (int i = 0; i < block_order.length(); ++i) { |
| 36 block_info_.Add(new BlockInfo()); | 37 block_info_.Add(new BlockInfo()); |
| 37 } | 38 } |
| 38 } | 39 } |
| 39 | 40 |
| 40 | 41 |
| 41 FlowGraphCompiler::~FlowGraphCompiler() { | 42 FlowGraphCompiler::~FlowGraphCompiler() { |
| 42 // BlockInfos are zone-allocated, so their destructors are not called. | 43 // BlockInfos are zone-allocated, so their destructors are not called. |
| 43 // Verify the labels explicitly here. | 44 // Verify the labels explicitly here. |
| 44 for (int i = 0; i < block_info_.length(); ++i) { | 45 for (int i = 0; i < block_info_.length(); ++i) { |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 132 static bool VerifyValues(Value* v1, Value* v2) { | 133 static bool VerifyValues(Value* v1, Value* v2) { |
| 133 if (v1->IsTemp() && v2->IsTemp()) { | 134 if (v1->IsTemp() && v2->IsTemp()) { |
| 134 return (v1->AsTemp()->index() + 1) == v2->AsTemp()->index(); | 135 return (v1->AsTemp()->index() + 1) == v2->AsTemp()->index(); |
| 135 } | 136 } |
| 136 return true; | 137 return true; |
| 137 } | 138 } |
| 138 | 139 |
| 139 | 140 |
| 140 void FlowGraphCompiler::EmitInstanceCall(intptr_t node_id, | 141 void FlowGraphCompiler::EmitInstanceCall(intptr_t node_id, |
| 141 intptr_t token_index, | 142 intptr_t token_index, |
| 143 intptr_t try_index, |
| 142 const String& function_name, | 144 const String& function_name, |
| 143 intptr_t argument_count, | 145 intptr_t argument_count, |
| 144 const Array& argument_names, | 146 const Array& argument_names, |
| 145 intptr_t checked_argument_count) { | 147 intptr_t checked_argument_count) { |
| 146 ICData& ic_data = | 148 ICData& ic_data = |
| 147 ICData::ZoneHandle(ICData::New(parsed_function_.function(), | 149 ICData::ZoneHandle(ICData::New(parsed_function_.function(), |
| 148 function_name, | 150 function_name, |
| 149 node_id, | 151 node_id, |
| 150 checked_argument_count)); | 152 checked_argument_count)); |
| 151 const Array& arguments_descriptor = | 153 const Array& arguments_descriptor = |
| 152 CodeGenerator::ArgumentsDescriptor(argument_count, argument_names); | 154 CodeGenerator::ArgumentsDescriptor(argument_count, argument_names); |
| 153 __ LoadObject(RBX, ic_data); | 155 __ LoadObject(RBX, ic_data); |
| 154 __ LoadObject(R10, arguments_descriptor); | 156 __ LoadObject(R10, arguments_descriptor); |
| 155 | 157 |
| 156 uword label_address = 0; | 158 uword label_address = 0; |
| 157 switch (checked_argument_count) { | 159 switch (checked_argument_count) { |
| 158 case 1: | 160 case 1: |
| 159 label_address = StubCode::OneArgCheckInlineCacheEntryPoint(); | 161 label_address = StubCode::OneArgCheckInlineCacheEntryPoint(); |
| 160 break; | 162 break; |
| 161 case 2: | 163 case 2: |
| 162 label_address = StubCode::TwoArgsCheckInlineCacheEntryPoint(); | 164 label_address = StubCode::TwoArgsCheckInlineCacheEntryPoint(); |
| 163 break; | 165 break; |
| 164 default: | 166 default: |
| 165 UNIMPLEMENTED(); | 167 UNIMPLEMENTED(); |
| 166 } | 168 } |
| 167 ExternalLabel target_label("InlineCache", label_address); | 169 ExternalLabel target_label("InlineCache", label_address); |
| 168 __ call(&target_label); | 170 __ call(&target_label); |
| 169 AddCurrentDescriptor(PcDescriptors::kIcCall, node_id, token_index); | 171 AddCurrentDescriptor(PcDescriptors::kIcCall, node_id, token_index, try_index); |
| 170 __ addq(RSP, Immediate(argument_count * kWordSize)); | 172 __ addq(RSP, Immediate(argument_count * kWordSize)); |
| 171 } | 173 } |
| 172 | 174 |
| 173 | 175 |
| 174 void FlowGraphCompiler::EmitStaticCall(intptr_t token_index, | 176 void FlowGraphCompiler::EmitStaticCall(intptr_t token_index, |
| 177 intptr_t try_index, |
| 175 const Function& function, | 178 const Function& function, |
| 176 intptr_t argument_count, | 179 intptr_t argument_count, |
| 177 const Array& argument_names) { | 180 const Array& argument_names) { |
| 178 const Array& arguments_descriptor = | 181 const Array& arguments_descriptor = |
| 179 CodeGenerator::ArgumentsDescriptor(argument_count, argument_names); | 182 CodeGenerator::ArgumentsDescriptor(argument_count, argument_names); |
| 180 __ LoadObject(RBX, function); | 183 __ LoadObject(RBX, function); |
| 181 __ LoadObject(R10, arguments_descriptor); | 184 __ LoadObject(R10, arguments_descriptor); |
| 182 | 185 |
| 183 GenerateCall(token_index, | 186 GenerateCall(token_index, |
| 187 try_index, |
| 184 &StubCode::CallStaticFunctionLabel(), | 188 &StubCode::CallStaticFunctionLabel(), |
| 185 PcDescriptors::kFuncCall); | 189 PcDescriptors::kFuncCall); |
| 186 __ addq(RSP, Immediate(argument_count * kWordSize)); | 190 __ addq(RSP, Immediate(argument_count * kWordSize)); |
| 187 } | 191 } |
| 188 | 192 |
| 189 | 193 |
| 190 void FlowGraphCompiler::VisitCurrentContext(CurrentContextComp* comp) { | 194 void FlowGraphCompiler::VisitCurrentContext(CurrentContextComp* comp) { |
| 191 __ movq(RAX, CTX); | 195 __ movq(RAX, CTX); |
| 192 } | 196 } |
| 193 | 197 |
| 194 | 198 |
| 195 void FlowGraphCompiler::VisitStoreContext(StoreContextComp* comp) { | 199 void FlowGraphCompiler::VisitStoreContext(StoreContextComp* comp) { |
| 196 LoadValue(CTX, comp->value()); | 200 LoadValue(CTX, comp->value()); |
| 197 } | 201 } |
| 198 | 202 |
| 199 | 203 |
| 200 void FlowGraphCompiler::VisitClosureCall(ClosureCallComp* comp) { | 204 void FlowGraphCompiler::VisitClosureCall(ClosureCallComp* comp) { |
| 201 ASSERT(comp->context()->IsTemp()); | 205 ASSERT(comp->context()->IsTemp()); |
| 202 ASSERT(VerifyCallComputation(comp)); | 206 ASSERT(VerifyCallComputation(comp)); |
| 203 // The arguments to the stub include the closure. The arguments | 207 // The arguments to the stub include the closure. The arguments |
| 204 // descriptor describes the closure's arguments (and so does not include | 208 // descriptor describes the closure's arguments (and so does not include |
| 205 // the closure). | 209 // the closure). |
| 206 int argument_count = comp->ArgumentCount(); | 210 int argument_count = comp->ArgumentCount(); |
| 207 const Array& arguments_descriptor = | 211 const Array& arguments_descriptor = |
| 208 CodeGenerator::ArgumentsDescriptor(argument_count - 1, | 212 CodeGenerator::ArgumentsDescriptor(argument_count - 1, |
| 209 comp->argument_names()); | 213 comp->argument_names()); |
| 210 __ LoadObject(R10, arguments_descriptor); | 214 __ LoadObject(R10, arguments_descriptor); |
| 211 | 215 |
| 212 GenerateCall(comp->token_index(), | 216 GenerateCall(comp->token_index(), |
| 217 comp->try_index(), |
| 213 &StubCode::CallClosureFunctionLabel(), | 218 &StubCode::CallClosureFunctionLabel(), |
| 214 PcDescriptors::kOther); | 219 PcDescriptors::kOther); |
| 215 __ addq(RSP, Immediate(argument_count * kWordSize)); | 220 __ addq(RSP, Immediate(argument_count * kWordSize)); |
| 216 __ popq(CTX); | 221 __ popq(CTX); |
| 217 } | 222 } |
| 218 | 223 |
| 219 | 224 |
| 220 void FlowGraphCompiler::VisitInstanceCall(InstanceCallComp* comp) { | 225 void FlowGraphCompiler::VisitInstanceCall(InstanceCallComp* comp) { |
| 221 ASSERT(VerifyCallComputation(comp)); | 226 ASSERT(VerifyCallComputation(comp)); |
| 222 EmitInstanceCall(comp->node_id(), | 227 EmitInstanceCall(comp->node_id(), |
| 223 comp->token_index(), | 228 comp->token_index(), |
| 229 comp->try_index(), |
| 224 comp->function_name(), | 230 comp->function_name(), |
| 225 comp->ArgumentCount(), | 231 comp->ArgumentCount(), |
| 226 comp->argument_names(), | 232 comp->argument_names(), |
| 227 comp->checked_argument_count()); | 233 comp->checked_argument_count()); |
| 228 } | 234 } |
| 229 | 235 |
| 230 | 236 |
| 231 void FlowGraphCompiler::VisitStrictCompare(StrictCompareComp* comp) { | 237 void FlowGraphCompiler::VisitStrictCompare(StrictCompareComp* comp) { |
| 232 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 238 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
| 233 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | 239 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 244 __ jmp(&done, Assembler::kNearJump); | 250 __ jmp(&done, Assembler::kNearJump); |
| 245 __ Bind(&load_true); | 251 __ Bind(&load_true); |
| 246 __ LoadObject(RAX, bool_true); | 252 __ LoadObject(RAX, bool_true); |
| 247 __ Bind(&done); | 253 __ Bind(&done); |
| 248 } | 254 } |
| 249 | 255 |
| 250 | 256 |
| 251 void FlowGraphCompiler::VisitStaticCall(StaticCallComp* comp) { | 257 void FlowGraphCompiler::VisitStaticCall(StaticCallComp* comp) { |
| 252 ASSERT(VerifyCallComputation(comp)); | 258 ASSERT(VerifyCallComputation(comp)); |
| 253 EmitStaticCall(comp->token_index(), | 259 EmitStaticCall(comp->token_index(), |
| 260 comp->try_index(), |
| 254 comp->function(), | 261 comp->function(), |
| 255 comp->ArgumentCount(), | 262 comp->ArgumentCount(), |
| 256 comp->argument_names()); | 263 comp->argument_names()); |
| 257 } | 264 } |
| 258 | 265 |
| 259 | 266 |
| 260 void FlowGraphCompiler::VisitLoadLocal(LoadLocalComp* comp) { | 267 void FlowGraphCompiler::VisitLoadLocal(LoadLocalComp* comp) { |
| 261 if (comp->local().is_captured()) { | 268 if (comp->local().is_captured()) { |
| 262 // The variable lives in the context. | 269 // The variable lives in the context. |
| 263 intptr_t delta = comp->context_level() - | 270 intptr_t delta = comp->context_level() - |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 307 __ PushObject(Object::ZoneHandle()); | 314 __ PushObject(Object::ZoneHandle()); |
| 308 // Pass a pointer to the first argument in RAX. | 315 // Pass a pointer to the first argument in RAX. |
| 309 if (!comp->has_optional_parameters()) { | 316 if (!comp->has_optional_parameters()) { |
| 310 __ leaq(RAX, Address(RBP, (1 + comp->argument_count()) * kWordSize)); | 317 __ leaq(RAX, Address(RBP, (1 + comp->argument_count()) * kWordSize)); |
| 311 } else { | 318 } else { |
| 312 __ leaq(RAX, Address(RBP, -1 * kWordSize)); | 319 __ leaq(RAX, Address(RBP, -1 * kWordSize)); |
| 313 } | 320 } |
| 314 __ movq(RBX, Immediate(reinterpret_cast<uword>(comp->native_c_function()))); | 321 __ movq(RBX, Immediate(reinterpret_cast<uword>(comp->native_c_function()))); |
| 315 __ movq(R10, Immediate(comp->argument_count())); | 322 __ movq(R10, Immediate(comp->argument_count())); |
| 316 GenerateCall(comp->token_index(), | 323 GenerateCall(comp->token_index(), |
| 324 comp->try_index(), |
| 317 &StubCode::CallNativeCFunctionLabel(), | 325 &StubCode::CallNativeCFunctionLabel(), |
| 318 PcDescriptors::kOther); | 326 PcDescriptors::kOther); |
| 319 __ popq(RAX); | 327 __ popq(RAX); |
| 320 } | 328 } |
| 321 | 329 |
| 322 | 330 |
| 323 void FlowGraphCompiler::VisitLoadInstanceField(LoadInstanceFieldComp* comp) { | 331 void FlowGraphCompiler::VisitLoadInstanceField(LoadInstanceFieldComp* comp) { |
| 324 LoadValue(RAX, comp->instance()); | 332 LoadValue(RAX, comp->instance()); |
| 325 __ movq(RAX, FieldAddress(RAX, comp->field().Offset())); | 333 __ movq(RAX, FieldAddress(RAX, comp->field().Offset())); |
| 326 } | 334 } |
| (...skipping 28 matching lines...) Expand all Loading... |
| 355 String::ZoneHandle(String::NewSymbol(Token::Str(Token::kASSIGN_INDEX))); | 363 String::ZoneHandle(String::NewSymbol(Token::Str(Token::kASSIGN_INDEX))); |
| 356 | 364 |
| 357 // Insert a copy of the third (last) argument under the arguments. | 365 // Insert a copy of the third (last) argument under the arguments. |
| 358 __ popq(RAX); // Value. | 366 __ popq(RAX); // Value. |
| 359 __ popq(RBX); // Index. | 367 __ popq(RBX); // Index. |
| 360 __ popq(RCX); // Receiver. | 368 __ popq(RCX); // Receiver. |
| 361 __ pushq(RAX); | 369 __ pushq(RAX); |
| 362 __ pushq(RCX); | 370 __ pushq(RCX); |
| 363 __ pushq(RBX); | 371 __ pushq(RBX); |
| 364 __ pushq(RAX); | 372 __ pushq(RAX); |
| 365 EmitInstanceCall(comp->node_id(), comp->token_index(), function_name, 3, | 373 EmitInstanceCall(comp->node_id(), |
| 366 Array::ZoneHandle(), 1); | 374 comp->token_index(), |
| 375 comp->try_index(), |
| 376 function_name, |
| 377 3, |
| 378 Array::ZoneHandle(), |
| 379 1); |
| 367 __ popq(RAX); | 380 __ popq(RAX); |
| 368 } | 381 } |
| 369 | 382 |
| 370 | 383 |
| 371 void FlowGraphCompiler::VisitInstanceSetter(InstanceSetterComp* comp) { | 384 void FlowGraphCompiler::VisitInstanceSetter(InstanceSetterComp* comp) { |
| 372 // Preserve the second argument under the arguments as the result of the | 385 // Preserve the second argument under the arguments as the result of the |
| 373 // computation, then call the setter. | 386 // computation, then call the setter. |
| 374 const String& function_name = | 387 const String& function_name = |
| 375 String::ZoneHandle(Field::SetterSymbol(comp->field_name())); | 388 String::ZoneHandle(Field::SetterSymbol(comp->field_name())); |
| 376 | 389 |
| 377 // Insert a copy of the second (last) argument under the arguments. | 390 // Insert a copy of the second (last) argument under the arguments. |
| 378 __ popq(RAX); // Value. | 391 __ popq(RAX); // Value. |
| 379 __ popq(RBX); // Receiver. | 392 __ popq(RBX); // Receiver. |
| 380 __ pushq(RAX); | 393 __ pushq(RAX); |
| 381 __ pushq(RBX); | 394 __ pushq(RBX); |
| 382 __ pushq(RAX); | 395 __ pushq(RAX); |
| 383 EmitInstanceCall(comp->node_id(), comp->token_index(), function_name, 2, | 396 EmitInstanceCall(comp->node_id(), |
| 384 Array::ZoneHandle(), 1); | 397 comp->token_index(), |
| 398 comp->try_index(), |
| 399 function_name, |
| 400 2, |
| 401 Array::ZoneHandle(), |
| 402 1); |
| 385 __ popq(RAX); | 403 __ popq(RAX); |
| 386 } | 404 } |
| 387 | 405 |
| 388 | 406 |
| 389 void FlowGraphCompiler::VisitStaticSetter(StaticSetterComp* comp) { | 407 void FlowGraphCompiler::VisitStaticSetter(StaticSetterComp* comp) { |
| 390 // Preserve the argument as the result of the computation, | 408 // Preserve the argument as the result of the computation, |
| 391 // then call the setter. | 409 // then call the setter. |
| 392 | 410 |
| 393 // Duplicate the argument. | 411 // Duplicate the argument. |
| 394 __ movq(RAX, Address(RSP, 0)); | 412 __ movq(RAX, Address(RSP, 0)); |
| 395 __ pushq(RAX); | 413 __ pushq(RAX); |
| 396 EmitStaticCall(comp->token_index(), comp->setter_function(), 1, | 414 EmitStaticCall(comp->token_index(), |
| 415 comp->try_index(), |
| 416 comp->setter_function(), |
| 417 1, |
| 397 Array::ZoneHandle()); | 418 Array::ZoneHandle()); |
| 398 __ popq(RAX); | 419 __ popq(RAX); |
| 399 } | 420 } |
| 400 | 421 |
| 401 | 422 |
| 402 void FlowGraphCompiler::VisitBooleanNegate(BooleanNegateComp* comp) { | 423 void FlowGraphCompiler::VisitBooleanNegate(BooleanNegateComp* comp) { |
| 403 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 424 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
| 404 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | 425 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); |
| 405 Label done; | 426 Label done; |
| 406 LoadValue(RDX, comp->value()); | 427 LoadValue(RDX, comp->value()); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 432 // - NULL -> return false. | 453 // - NULL -> return false. |
| 433 // - Smi -> compile time subtype check (only if dst class is not parameterized). | 454 // - Smi -> compile time subtype check (only if dst class is not parameterized). |
| 434 // - Class equality (only if class is not parameterized). | 455 // - Class equality (only if class is not parameterized). |
| 435 // Inputs: | 456 // Inputs: |
| 436 // - RAX: object. | 457 // - RAX: object. |
| 437 // Destroys RCX. | 458 // Destroys RCX. |
| 438 // Returns: | 459 // Returns: |
| 439 // - true or false in RAX. | 460 // - true or false in RAX. |
| 440 void FlowGraphCompiler::GenerateInstanceOf(intptr_t node_id, | 461 void FlowGraphCompiler::GenerateInstanceOf(intptr_t node_id, |
| 441 intptr_t token_index, | 462 intptr_t token_index, |
| 463 intptr_t try_index, |
| 442 const AbstractType& type, | 464 const AbstractType& type, |
| 443 bool negate_result) { | 465 bool negate_result) { |
| 444 ASSERT(type.IsFinalized() && !type.IsMalformed()); | 466 ASSERT(type.IsFinalized() && !type.IsMalformed()); |
| 445 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 467 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
| 446 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | 468 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); |
| 447 | 469 |
| 448 // All instances are of a subtype of the Object type. | 470 // All instances are of a subtype of the Object type. |
| 449 const Type& object_type = | 471 const Type& object_type = |
| 450 Type::Handle(Isolate::Current()->object_store()->object_type()); | 472 Type::Handle(Isolate::Current()->object_store()->object_type()); |
| 451 Error& malformed_error = Error::Handle(); | 473 Error& malformed_error = Error::Handle(); |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 560 Immediate(reinterpret_cast<int64_t>(Smi::New(node_id))); | 582 Immediate(reinterpret_cast<int64_t>(Smi::New(node_id))); |
| 561 __ pushq(location); // Push the source location. | 583 __ pushq(location); // Push the source location. |
| 562 __ pushq(node_id_as_smi); | 584 __ pushq(node_id_as_smi); |
| 563 __ pushq(RAX); // Push the instance. | 585 __ pushq(RAX); // Push the instance. |
| 564 __ PushObject(type); // Push the type. | 586 __ PushObject(type); // Push the type. |
| 565 if (!type.IsInstantiated()) { | 587 if (!type.IsInstantiated()) { |
| 566 GenerateInstantiatorTypeArguments(token_index); | 588 GenerateInstantiatorTypeArguments(token_index); |
| 567 } else { | 589 } else { |
| 568 __ pushq(raw_null); // Null instantiator. | 590 __ pushq(raw_null); // Null instantiator. |
| 569 } | 591 } |
| 570 GenerateCallRuntime(node_id, token_index, kInstanceofRuntimeEntry); | 592 GenerateCallRuntime(node_id, token_index, try_index, kInstanceofRuntimeEntry); |
| 571 // Pop the two parameters supplied to the runtime entry. The result of the | 593 // Pop the two parameters supplied to the runtime entry. The result of the |
| 572 // instanceof runtime call will be left as the result of the operation. | 594 // instanceof runtime call will be left as the result of the operation. |
| 573 __ addq(RSP, Immediate(5 * kWordSize)); | 595 __ addq(RSP, Immediate(5 * kWordSize)); |
| 574 if (negate_result) { | 596 if (negate_result) { |
| 575 Label negate_done; | 597 Label negate_done; |
| 576 __ popq(RDX); | 598 __ popq(RDX); |
| 577 __ LoadObject(RAX, bool_true); | 599 __ LoadObject(RAX, bool_true); |
| 578 __ cmpq(RDX, RAX); | 600 __ cmpq(RDX, RAX); |
| 579 __ j(NOT_EQUAL, &negate_done, Assembler::kNearJump); | 601 __ j(NOT_EQUAL, &negate_done, Assembler::kNearJump); |
| 580 __ LoadObject(RAX, bool_false); | 602 __ LoadObject(RAX, bool_false); |
| 581 __ Bind(&negate_done); | 603 __ Bind(&negate_done); |
| 582 __ pushq(RAX); | 604 __ pushq(RAX); |
| 583 } | 605 } |
| 584 __ Bind(&done); | 606 __ Bind(&done); |
| 585 __ popq(RAX); | 607 __ popq(RAX); |
| 586 } | 608 } |
| 587 | 609 |
| 588 | 610 |
| 589 void FlowGraphCompiler::VisitInstanceOf(InstanceOfComp* comp) { | 611 void FlowGraphCompiler::VisitInstanceOf(InstanceOfComp* comp) { |
| 590 __ popq(RAX); | 612 __ popq(RAX); |
| 591 GenerateInstanceOf(comp->node_id(), | 613 GenerateInstanceOf(comp->node_id(), |
| 592 comp->token_index(), | 614 comp->token_index(), |
| 615 comp->try_index(), |
| 593 comp->type(), | 616 comp->type(), |
| 594 comp->negate_result()); | 617 comp->negate_result()); |
| 595 } | 618 } |
| 596 | 619 |
| 597 | 620 |
| 598 void FlowGraphCompiler::VisitAllocateObject(AllocateObjectComp* comp) { | 621 void FlowGraphCompiler::VisitAllocateObject(AllocateObjectComp* comp) { |
| 599 const Class& cls = Class::ZoneHandle(comp->constructor().owner()); | 622 const Class& cls = Class::ZoneHandle(comp->constructor().owner()); |
| 600 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls)); | 623 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls)); |
| 601 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); | 624 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); |
| 602 GenerateCall(comp->token_index(), &label, PcDescriptors::kOther); | 625 GenerateCall(comp->token_index(), comp->try_index(), &label, |
| 626 PcDescriptors::kOther); |
| 603 for (intptr_t i = 0; i < comp->arguments().length(); i++) { | 627 for (intptr_t i = 0; i < comp->arguments().length(); i++) { |
| 604 __ popq(RCX); // Discard allocation argument | 628 __ popq(RCX); // Discard allocation argument |
| 605 } | 629 } |
| 606 } | 630 } |
| 607 | 631 |
| 608 | 632 |
| 609 void FlowGraphCompiler::VisitCreateArray(CreateArrayComp* comp) { | 633 void FlowGraphCompiler::VisitCreateArray(CreateArrayComp* comp) { |
| 610 // 1. Allocate the array. R10 = length, RBX = element type. | 634 // 1. Allocate the array. R10 = length, RBX = element type. |
| 611 __ movq(R10, Immediate(Smi::RawValue(comp->ElementCount()))); | 635 __ movq(R10, Immediate(Smi::RawValue(comp->ElementCount()))); |
| 612 const AbstractTypeArguments& element_type = comp->type_arguments(); | 636 const AbstractTypeArguments& element_type = comp->type_arguments(); |
| 613 ASSERT(element_type.IsNull() || element_type.IsInstantiated()); | 637 ASSERT(element_type.IsNull() || element_type.IsInstantiated()); |
| 614 __ LoadObject(RBX, element_type); | 638 __ LoadObject(RBX, element_type); |
| 615 GenerateCall(comp->token_index(), | 639 GenerateCall(comp->token_index(), |
| 640 comp->try_index(), |
| 616 &StubCode::AllocateArrayLabel(), | 641 &StubCode::AllocateArrayLabel(), |
| 617 PcDescriptors::kOther); | 642 PcDescriptors::kOther); |
| 618 | 643 |
| 619 // 2. Initialize the array in RAX with the element values. | 644 // 2. Initialize the array in RAX with the element values. |
| 620 __ leaq(RCX, FieldAddress(RAX, Array::data_offset())); | 645 __ leaq(RCX, FieldAddress(RAX, Array::data_offset())); |
| 621 for (int i = comp->ElementCount() - 1; i >= 0; --i) { | 646 for (int i = comp->ElementCount() - 1; i >= 0; --i) { |
| 622 if (comp->ElementAt(i)->IsTemp()) { | 647 if (comp->ElementAt(i)->IsTemp()) { |
| 623 __ popq(Address(RCX, i * kWordSize)); | 648 __ popq(Address(RCX, i * kWordSize)); |
| 624 } else { | 649 } else { |
| 625 LoadValue(RDX, comp->ElementAt(i)); | 650 LoadValue(RDX, comp->ElementAt(i)); |
| 626 __ movq(Address(RCX, i * kWordSize), RDX); | 651 __ movq(Address(RCX, i * kWordSize), RDX); |
| 627 } | 652 } |
| 628 } | 653 } |
| 629 } | 654 } |
| 630 | 655 |
| 631 | 656 |
| 632 void FlowGraphCompiler::VisitCreateClosure(CreateClosureComp* comp) { | 657 void FlowGraphCompiler::VisitCreateClosure(CreateClosureComp* comp) { |
| 633 const Function& function = comp->function(); | 658 const Function& function = comp->function(); |
| 634 const Code& stub = Code::Handle( | 659 const Code& stub = Code::Handle( |
| 635 StubCode::GetAllocationStubForClosure(function)); | 660 StubCode::GetAllocationStubForClosure(function)); |
| 636 const ExternalLabel label(function.ToCString(), stub.EntryPoint()); | 661 const ExternalLabel label(function.ToCString(), stub.EntryPoint()); |
| 637 GenerateCall(comp->token_index(), &label, PcDescriptors::kOther); | 662 GenerateCall(comp->token_index(), comp->try_index(), &label, |
| 663 PcDescriptors::kOther); |
| 638 | 664 |
| 639 const Class& cls = Class::Handle(function.signature_class()); | 665 const Class& cls = Class::Handle(function.signature_class()); |
| 640 if (cls.HasTypeArguments()) { | 666 if (cls.HasTypeArguments()) { |
| 641 __ popq(RCX); // Discard type arguments. | 667 __ popq(RCX); // Discard type arguments. |
| 642 } | 668 } |
| 643 if (function.IsImplicitInstanceClosureFunction()) { | 669 if (function.IsImplicitInstanceClosureFunction()) { |
| 644 __ popq(RCX); // Discard receiver. | 670 __ popq(RCX); // Discard receiver. |
| 645 } | 671 } |
| 646 } | 672 } |
| 647 | 673 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 685 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 711 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 686 __ Bind(&type_arguments_uninstantiated); | 712 __ Bind(&type_arguments_uninstantiated); |
| 687 } | 713 } |
| 688 // A runtime call to instantiate the type arguments is required before | 714 // A runtime call to instantiate the type arguments is required before |
| 689 // calling the factory. | 715 // calling the factory. |
| 690 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 716 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 691 __ PushObject(comp->type_arguments()); | 717 __ PushObject(comp->type_arguments()); |
| 692 __ pushq(RAX); // Push instantiator type arguments. | 718 __ pushq(RAX); // Push instantiator type arguments. |
| 693 GenerateCallRuntime(comp->node_id(), | 719 GenerateCallRuntime(comp->node_id(), |
| 694 comp->token_index(), | 720 comp->token_index(), |
| 721 comp->try_index(), |
| 695 kInstantiateTypeArgumentsRuntimeEntry); | 722 kInstantiateTypeArgumentsRuntimeEntry); |
| 696 __ popq(RAX); // Pop instantiator type arguments. | 723 __ popq(RAX); // Pop instantiator type arguments. |
| 697 __ popq(RAX); // Pop uninstantiated type arguments. | 724 __ popq(RAX); // Pop uninstantiated type arguments. |
| 698 __ popq(RAX); // Pop instantiated type arguments. | 725 __ popq(RAX); // Pop instantiated type arguments. |
| 699 __ Bind(&type_arguments_instantiated); | 726 __ Bind(&type_arguments_instantiated); |
| 700 // RAX: Instantiated type arguments. | 727 // RAX: Instantiated type arguments. |
| 701 } | 728 } |
| 702 | 729 |
| 703 | 730 |
| 704 void FlowGraphCompiler::VisitExtractConstructorTypeArguments( | 731 void FlowGraphCompiler::VisitExtractConstructorTypeArguments( |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 794 } | 821 } |
| 795 __ Bind(&done); | 822 __ Bind(&done); |
| 796 // RAX: instantiator or kNoInstantiator. | 823 // RAX: instantiator or kNoInstantiator. |
| 797 } | 824 } |
| 798 | 825 |
| 799 | 826 |
| 800 void FlowGraphCompiler::VisitAllocateContext(AllocateContextComp* comp) { | 827 void FlowGraphCompiler::VisitAllocateContext(AllocateContextComp* comp) { |
| 801 __ movq(R10, Immediate(comp->num_context_variables())); | 828 __ movq(R10, Immediate(comp->num_context_variables())); |
| 802 const ExternalLabel label("alloc_context", | 829 const ExternalLabel label("alloc_context", |
| 803 StubCode::AllocateContextEntryPoint()); | 830 StubCode::AllocateContextEntryPoint()); |
| 804 GenerateCall(comp->token_index(), &label, PcDescriptors::kOther); | 831 GenerateCall(comp->token_index(), comp->try_index(), &label, |
| 832 PcDescriptors::kOther); |
| 805 } | 833 } |
| 806 | 834 |
| 807 | 835 |
| 808 void FlowGraphCompiler::VisitChainContext(ChainContextComp* comp) { | 836 void FlowGraphCompiler::VisitChainContext(ChainContextComp* comp) { |
| 809 __ popq(RAX); | 837 __ popq(RAX); |
| 810 // Chain the new context in RAX to its parent in CTX. | 838 // Chain the new context in RAX to its parent in CTX. |
| 811 __ StoreIntoObject(RAX, | 839 __ StoreIntoObject(RAX, |
| 812 FieldAddress(RAX, Context::parent_offset()), | 840 FieldAddress(RAX, Context::parent_offset()), |
| 813 CTX); | 841 CTX); |
| 814 // Set new context as current context. | 842 // Set new context as current context. |
| 815 __ movq(CTX, RAX); | 843 __ movq(CTX, RAX); |
| 816 } | 844 } |
| 817 | 845 |
| 818 | 846 |
| 819 void FlowGraphCompiler::VisitCloneContext(CloneContextComp* comp) { | 847 void FlowGraphCompiler::VisitCloneContext(CloneContextComp* comp) { |
| 820 __ popq(RAX); // Get context value from stack. | 848 __ popq(RAX); // Get context value from stack. |
| 821 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 849 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 822 __ pushq(RAX); | 850 __ pushq(RAX); |
| 823 GenerateCallRuntime(comp->node_id(), | 851 GenerateCallRuntime(comp->node_id(), |
| 824 comp->token_index(), | 852 comp->token_index(), |
| 853 comp->try_index(), |
| 825 kCloneContextRuntimeEntry); | 854 kCloneContextRuntimeEntry); |
| 826 __ popq(RAX); // Remove argument. | 855 __ popq(RAX); // Remove argument. |
| 827 __ popq(RAX); // Get result (cloned context). | 856 __ popq(RAX); // Get result (cloned context). |
| 828 } | 857 } |
| 829 | 858 |
| 830 | 859 |
| 860 // Restore stack and initialize the two exception variables: |
| 861 // exception and stack trace variables. |
| 862 void FlowGraphCompiler::VisitCatchEntry(CatchEntryComp* comp) { |
| 863 // Restore RSP from RBP as we are coming from a throw and the code for |
| 864 // popping arguments has not been run. |
| 865 const intptr_t locals_space_size = StackSize() * kWordSize; |
| 866 ASSERT(locals_space_size >= 0); |
| 867 __ movq(RSP, RBP); |
| 868 __ subq(RSP, Immediate(locals_space_size)); |
| 869 |
| 870 ASSERT(!comp->exception_var().is_captured()); |
| 871 ASSERT(!comp->stacktrace_var().is_captured()); |
| 872 __ movq(Address(RBP, comp->exception_var().index() * kWordSize), |
| 873 kExceptionObjectReg); |
| 874 __ movq(Address(RBP, comp->stacktrace_var().index() * kWordSize), |
| 875 kStackTraceObjectReg); |
| 876 } |
| 877 |
| 878 |
| 831 void FlowGraphCompiler::VisitBlocks() { | 879 void FlowGraphCompiler::VisitBlocks() { |
| 832 for (intptr_t i = 0; i < block_order_.length(); ++i) { | 880 for (intptr_t i = 0; i < block_order_.length(); ++i) { |
| 833 // Compile the block entry. | 881 // Compile the block entry. |
| 834 current_block_ = block_order_[i]; | 882 current_block_ = block_order_[i]; |
| 835 Instruction* instr = current_block()->Accept(this); | 883 Instruction* instr = current_block()->Accept(this); |
| 836 // Compile all successors until an exit, branch, or a block entry. | 884 // Compile all successors until an exit, branch, or a block entry. |
| 837 while ((instr != NULL) && !instr->IsBlockEntry()) { | 885 while ((instr != NULL) && !instr->IsBlockEntry()) { |
| 838 instr = instr->Accept(this); | 886 instr = instr->Accept(this); |
| 839 } | 887 } |
| 840 | 888 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 852 } | 900 } |
| 853 | 901 |
| 854 | 902 |
| 855 void FlowGraphCompiler::VisitJoinEntry(JoinEntryInstr* instr) { | 903 void FlowGraphCompiler::VisitJoinEntry(JoinEntryInstr* instr) { |
| 856 __ Bind(&block_info_[instr->postorder_number()]->label); | 904 __ Bind(&block_info_[instr->postorder_number()]->label); |
| 857 } | 905 } |
| 858 | 906 |
| 859 | 907 |
| 860 void FlowGraphCompiler::VisitTargetEntry(TargetEntryInstr* instr) { | 908 void FlowGraphCompiler::VisitTargetEntry(TargetEntryInstr* instr) { |
| 861 __ Bind(&block_info_[instr->postorder_number()]->label); | 909 __ Bind(&block_info_[instr->postorder_number()]->label); |
| 910 if (instr->HasTryIndex()) { |
| 911 exception_handlers_list_->AddHandler(instr->try_index(), |
| 912 assembler_->CodeSize()); |
| 913 // Bailout("Untested CatchEntry"); |
| 914 } |
| 862 } | 915 } |
| 863 | 916 |
| 864 | 917 |
| 865 void FlowGraphCompiler::VisitPickTemp(PickTempInstr* instr) { | 918 void FlowGraphCompiler::VisitPickTemp(PickTempInstr* instr) { |
| 866 // Semantics is to copy a stack-allocated temporary to the top of stack. | 919 // Semantics is to copy a stack-allocated temporary to the top of stack. |
| 867 // Destination index d is assumed the new top of stack after the | 920 // Destination index d is assumed the new top of stack after the |
| 868 // operation, so d-1 is the current top of stack and so d-s-1 is the | 921 // operation, so d-1 is the current top of stack and so d-s-1 is the |
| 869 // offset to source index s. | 922 // offset to source index s. |
| 870 intptr_t offset = instr->destination() - instr->source() - 1; | 923 intptr_t offset = instr->destination() - instr->source() - 1; |
| 871 ASSERT(offset >= 0); | 924 ASSERT(offset >= 0); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 910 #endif // DEBUG. | 963 #endif // DEBUG. |
| 911 | 964 |
| 912 if (FLAG_trace_functions) { | 965 if (FLAG_trace_functions) { |
| 913 __ pushq(RAX); // Preserve result. | 966 __ pushq(RAX); // Preserve result. |
| 914 const Function& function = | 967 const Function& function = |
| 915 Function::ZoneHandle(parsed_function_.function().raw()); | 968 Function::ZoneHandle(parsed_function_.function().raw()); |
| 916 __ LoadObject(RBX, function); | 969 __ LoadObject(RBX, function); |
| 917 __ pushq(RBX); | 970 __ pushq(RBX); |
| 918 GenerateCallRuntime(AstNode::kNoId, | 971 GenerateCallRuntime(AstNode::kNoId, |
| 919 0, | 972 0, |
| 973 CatchClauseNode::kInvalidTryIndex, |
| 920 kTraceFunctionExitRuntimeEntry); | 974 kTraceFunctionExitRuntimeEntry); |
| 921 __ popq(RAX); // Remove argument. | 975 __ popq(RAX); // Remove argument. |
| 922 __ popq(RAX); // Restore result. | 976 __ popq(RAX); // Restore result. |
| 923 } | 977 } |
| 924 __ LeaveFrame(); | 978 __ LeaveFrame(); |
| 925 __ ret(); | 979 __ ret(); |
| 926 | 980 |
| 927 // Generate 8 bytes of NOPs so that the debugger can patch the | 981 // Generate 8 bytes of NOPs so that the debugger can patch the |
| 928 // return pattern with a call to the debug stub. | 982 // return pattern with a call to the debug stub. |
| 929 __ nop(1); | 983 __ nop(1); |
| 930 __ nop(1); | 984 __ nop(1); |
| 931 __ nop(1); | 985 __ nop(1); |
| 932 __ nop(1); | 986 __ nop(1); |
| 933 __ nop(1); | 987 __ nop(1); |
| 934 __ nop(1); | 988 __ nop(1); |
| 935 __ nop(1); | 989 __ nop(1); |
| 936 __ nop(1); | 990 __ nop(1); |
| 937 AddCurrentDescriptor(PcDescriptors::kReturn, | 991 AddCurrentDescriptor(PcDescriptors::kReturn, |
| 938 AstNode::kNoId, | 992 AstNode::kNoId, |
| 939 instr->token_index()); | 993 instr->token_index(), |
| 994 CatchClauseNode::kInvalidTryIndex); // try-index. |
| 940 } | 995 } |
| 941 | 996 |
| 942 | 997 |
| 943 void FlowGraphCompiler::VisitThrow(ThrowInstr* instr) { | 998 void FlowGraphCompiler::VisitThrow(ThrowInstr* instr) { |
| 944 LoadValue(RAX, instr->exception()); | 999 LoadValue(RAX, instr->exception()); |
| 945 __ pushq(RAX); | 1000 __ pushq(RAX); |
| 946 GenerateCallRuntime(instr->node_id(), | 1001 GenerateCallRuntime(instr->node_id(), |
| 947 instr->token_index(), | 1002 instr->token_index(), |
| 1003 instr->try_index(), |
| 948 kThrowRuntimeEntry); | 1004 kThrowRuntimeEntry); |
| 949 __ int3(); | 1005 __ int3(); |
| 950 } | 1006 } |
| 951 | 1007 |
| 952 | 1008 |
| 953 void FlowGraphCompiler::VisitReThrow(ReThrowInstr* instr) { | 1009 void FlowGraphCompiler::VisitReThrow(ReThrowInstr* instr) { |
| 954 LoadValue(RBX, instr->stack_trace()); | 1010 LoadValue(RBX, instr->stack_trace()); |
| 955 LoadValue(RAX, instr->exception()); | 1011 LoadValue(RAX, instr->exception()); |
| 956 __ pushq(RAX); | 1012 __ pushq(RAX); |
| 957 __ pushq(RBX); | 1013 __ pushq(RBX); |
| 958 GenerateCallRuntime( | 1014 GenerateCallRuntime(instr->node_id(), |
| 959 instr->node_id(), instr->token_index(), kReThrowRuntimeEntry); | 1015 instr->token_index(), |
| 1016 instr->try_index(), |
| 1017 kReThrowRuntimeEntry); |
| 960 Bailout("ReThrow Untested"); | 1018 Bailout("ReThrow Untested"); |
| 961 } | 1019 } |
| 962 | 1020 |
| 963 | 1021 |
| 964 | 1022 |
| 965 void FlowGraphCompiler::VisitBranch(BranchInstr* instr) { | 1023 void FlowGraphCompiler::VisitBranch(BranchInstr* instr) { |
| 966 // Determine if the true branch is fall through (!negated) or the false | 1024 // Determine if the true branch is fall through (!negated) or the false |
| 967 // branch is. They cannot both be backwards branches. | 1025 // branch is. They cannot both be backwards branches. |
| 968 intptr_t index = reverse_index(current_block()->postorder_number()); | 1026 intptr_t index = reverse_index(current_block()->postorder_number()); |
| 969 bool negated = (block_order_[index + 1] == instr->false_successor()); | 1027 bool negated = (block_order_[index + 1] == instr->false_successor()); |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1102 const Immediate raw_null = | 1160 const Immediate raw_null = |
| 1103 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1161 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1104 Label all_arguments_processed; | 1162 Label all_arguments_processed; |
| 1105 __ cmpq(Address(RDI, 0), raw_null); | 1163 __ cmpq(Address(RDI, 0), raw_null); |
| 1106 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); | 1164 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); |
| 1107 | 1165 |
| 1108 __ Bind(&wrong_num_arguments); | 1166 __ Bind(&wrong_num_arguments); |
| 1109 if (function.IsClosureFunction()) { | 1167 if (function.IsClosureFunction()) { |
| 1110 GenerateCallRuntime(AstNode::kNoId, | 1168 GenerateCallRuntime(AstNode::kNoId, |
| 1111 0, | 1169 0, |
| 1170 CatchClauseNode::kInvalidTryIndex, |
| 1112 kClosureArgumentMismatchRuntimeEntry); | 1171 kClosureArgumentMismatchRuntimeEntry); |
| 1113 } else { | 1172 } else { |
| 1114 // Invoke noSuchMethod function. | 1173 // Invoke noSuchMethod function. |
| 1115 const int kNumArgsChecked = 1; | 1174 const int kNumArgsChecked = 1; |
| 1116 ICData& ic_data = ICData::ZoneHandle(); | 1175 ICData& ic_data = ICData::ZoneHandle(); |
| 1117 ic_data = ICData::New(parsed_function_.function(), | 1176 ic_data = ICData::New(parsed_function_.function(), |
| 1118 String::Handle(function.name()), | 1177 String::Handle(function.name()), |
| 1119 AstNode::kNoId, | 1178 AstNode::kNoId, |
| 1120 kNumArgsChecked); | 1179 kNumArgsChecked); |
| 1121 __ LoadObject(RBX, ic_data); | 1180 __ LoadObject(RBX, ic_data); |
| 1122 // RBP : points to previous frame pointer. | 1181 // RBP : points to previous frame pointer. |
| 1123 // RBP + 8 : points to return address. | 1182 // RBP + 8 : points to return address. |
| 1124 // RBP + 16 : address of last argument (arg n-1). | 1183 // RBP + 16 : address of last argument (arg n-1). |
| 1125 // RSP + 16 + 8*(n-1) : address of first argument (arg 0). | 1184 // RSP + 16 + 8*(n-1) : address of first argument (arg 0). |
| 1126 // RBX : ic-data. | 1185 // RBX : ic-data. |
| 1127 // R10 : arguments descriptor array. | 1186 // R10 : arguments descriptor array. |
| 1128 __ call(&StubCode::CallNoSuchMethodFunctionLabel()); | 1187 __ call(&StubCode::CallNoSuchMethodFunctionLabel()); |
| 1129 } | 1188 } |
| 1130 | 1189 |
| 1131 if (FLAG_trace_functions) { | 1190 if (FLAG_trace_functions) { |
| 1132 __ pushq(RAX); // Preserve result. | 1191 __ pushq(RAX); // Preserve result. |
| 1133 __ PushObject(Function::ZoneHandle(function.raw())); | 1192 __ PushObject(Function::ZoneHandle(function.raw())); |
| 1134 GenerateCallRuntime(AstNode::kNoId, | 1193 GenerateCallRuntime(AstNode::kNoId, |
| 1135 0, | 1194 0, |
| 1195 CatchClauseNode::kInvalidTryIndex, |
| 1136 kTraceFunctionExitRuntimeEntry); | 1196 kTraceFunctionExitRuntimeEntry); |
| 1137 __ popq(RAX); // Remove argument. | 1197 __ popq(RAX); // Remove argument. |
| 1138 __ popq(RAX); // Restore result. | 1198 __ popq(RAX); // Restore result. |
| 1139 } | 1199 } |
| 1140 __ LeaveFrame(); | 1200 __ LeaveFrame(); |
| 1141 __ ret(); | 1201 __ ret(); |
| 1142 | 1202 |
| 1143 __ Bind(&all_arguments_processed); | 1203 __ Bind(&all_arguments_processed); |
| 1144 // Nullify originally passed arguments only after they have been copied and | 1204 // Nullify originally passed arguments only after they have been copied and |
| 1145 // checked, otherwise noSuchMethod would not see their original values. | 1205 // checked, otherwise noSuchMethod would not see their original values. |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1186 if (check_arguments) { | 1246 if (check_arguments) { |
| 1187 // Check that num_fixed <= argc <= num_params. | 1247 // Check that num_fixed <= argc <= num_params. |
| 1188 Label argc_in_range; | 1248 Label argc_in_range; |
| 1189 // Total number of args is the first Smi in args descriptor array (R10). | 1249 // Total number of args is the first Smi in args descriptor array (R10). |
| 1190 __ movq(RAX, FieldAddress(R10, Array::data_offset())); | 1250 __ movq(RAX, FieldAddress(R10, Array::data_offset())); |
| 1191 __ cmpq(RAX, Immediate(Smi::RawValue(parameter_count))); | 1251 __ cmpq(RAX, Immediate(Smi::RawValue(parameter_count))); |
| 1192 __ j(EQUAL, &argc_in_range, Assembler::kNearJump); | 1252 __ j(EQUAL, &argc_in_range, Assembler::kNearJump); |
| 1193 if (function.IsClosureFunction()) { | 1253 if (function.IsClosureFunction()) { |
| 1194 GenerateCallRuntime(AstNode::kNoId, | 1254 GenerateCallRuntime(AstNode::kNoId, |
| 1195 function.token_index(), | 1255 function.token_index(), |
| 1256 CatchClauseNode::kInvalidTryIndex, |
| 1196 kClosureArgumentMismatchRuntimeEntry); | 1257 kClosureArgumentMismatchRuntimeEntry); |
| 1197 } else { | 1258 } else { |
| 1198 __ Stop("Wrong number of arguments"); | 1259 __ Stop("Wrong number of arguments"); |
| 1199 } | 1260 } |
| 1200 __ Bind(&argc_in_range); | 1261 __ Bind(&argc_in_range); |
| 1201 } | 1262 } |
| 1202 } else { | 1263 } else { |
| 1203 CopyParameters(); | 1264 CopyParameters(); |
| 1204 } | 1265 } |
| 1205 | 1266 |
| 1206 // Initialize locals to null. | 1267 // Initialize locals to null. |
| 1207 if (local_count > 0) { | 1268 if (local_count > 0) { |
| 1208 __ movq(RAX, Immediate(reinterpret_cast<intptr_t>(Object::null()))); | 1269 __ movq(RAX, Immediate(reinterpret_cast<intptr_t>(Object::null()))); |
| 1209 const int base = parsed_function_.first_stack_local_index(); | 1270 const int base = parsed_function_.first_stack_local_index(); |
| 1210 for (int i = 0; i < local_count; ++i) { | 1271 for (int i = 0; i < local_count; ++i) { |
| 1211 // Subtract index i (locals lie at lower addresses than RBP). | 1272 // Subtract index i (locals lie at lower addresses than RBP). |
| 1212 __ movq(Address(RBP, (base - i) * kWordSize), RAX); | 1273 __ movq(Address(RBP, (base - i) * kWordSize), RAX); |
| 1213 } | 1274 } |
| 1214 } | 1275 } |
| 1215 | 1276 |
| 1216 // Generate stack overflow check. | 1277 // Generate stack overflow check. |
| 1217 __ movq(TMP, Immediate(Isolate::Current()->stack_limit_address())); | 1278 __ movq(TMP, Immediate(Isolate::Current()->stack_limit_address())); |
| 1218 __ cmpq(RSP, Address(TMP, 0)); | 1279 __ cmpq(RSP, Address(TMP, 0)); |
| 1219 Label no_stack_overflow; | 1280 Label no_stack_overflow; |
| 1220 __ j(ABOVE, &no_stack_overflow, Assembler::kNearJump); | 1281 __ j(ABOVE, &no_stack_overflow, Assembler::kNearJump); |
| 1221 GenerateCallRuntime(AstNode::kNoId, | 1282 GenerateCallRuntime(AstNode::kNoId, |
| 1222 function.token_index(), | 1283 function.token_index(), |
| 1284 CatchClauseNode::kInvalidTryIndex, |
| 1223 kStackOverflowRuntimeEntry); | 1285 kStackOverflowRuntimeEntry); |
| 1224 __ Bind(&no_stack_overflow); | 1286 __ Bind(&no_stack_overflow); |
| 1225 | 1287 |
| 1226 if (FLAG_print_scopes) { | 1288 if (FLAG_print_scopes) { |
| 1227 // Print the function scope (again) after generating the prologue in order | 1289 // Print the function scope (again) after generating the prologue in order |
| 1228 // to see annotations such as allocation indices of locals. | 1290 // to see annotations such as allocation indices of locals. |
| 1229 if (FLAG_print_ast) { | 1291 if (FLAG_print_ast) { |
| 1230 // Second printing. | 1292 // Second printing. |
| 1231 OS::Print("Annotated "); | 1293 OS::Print("Annotated "); |
| 1232 } | 1294 } |
| 1233 AstPrinter::PrintFunctionScope(parsed_function_); | 1295 AstPrinter::PrintFunctionScope(parsed_function_); |
| 1234 } | 1296 } |
| 1235 | 1297 |
| 1236 VisitBlocks(); | 1298 VisitBlocks(); |
| 1237 | 1299 |
| 1238 __ int3(); | 1300 __ int3(); |
| 1239 // Emit function patching code. This will be swapped with the first 13 bytes | 1301 // Emit function patching code. This will be swapped with the first 13 bytes |
| 1240 // at entry point. | 1302 // at entry point. |
| 1241 pc_descriptors_list_->AddDescriptor(PcDescriptors::kPatchCode, | 1303 pc_descriptors_list_->AddDescriptor(PcDescriptors::kPatchCode, |
| 1242 assembler_->CodeSize(), | 1304 assembler_->CodeSize(), |
| 1243 AstNode::kNoId, | 1305 AstNode::kNoId, |
| 1244 0, | 1306 0, |
| 1245 -1); | 1307 -1); |
| 1246 __ jmp(&StubCode::FixCallersTargetLabel()); | 1308 __ jmp(&StubCode::FixCallersTargetLabel()); |
| 1247 } | 1309 } |
| 1248 | 1310 |
| 1249 | 1311 |
| 1250 // Infrastructure copied from class CodeGenerator. | 1312 // Infrastructure copied from class CodeGenerator. |
| 1251 void FlowGraphCompiler::GenerateCall(intptr_t token_index, | 1313 void FlowGraphCompiler::GenerateCall(intptr_t token_index, |
| 1314 intptr_t try_index, |
| 1252 const ExternalLabel* label, | 1315 const ExternalLabel* label, |
| 1253 PcDescriptors::Kind kind) { | 1316 PcDescriptors::Kind kind) { |
| 1254 __ call(label); | 1317 __ call(label); |
| 1255 AddCurrentDescriptor(kind, AstNode::kNoId, token_index); | 1318 AddCurrentDescriptor(kind, AstNode::kNoId, token_index, try_index); |
| 1256 } | 1319 } |
| 1257 | 1320 |
| 1258 | 1321 |
| 1259 void FlowGraphCompiler::GenerateCallRuntime(intptr_t node_id, | 1322 void FlowGraphCompiler::GenerateCallRuntime(intptr_t node_id, |
| 1260 intptr_t token_index, | 1323 intptr_t token_index, |
| 1324 intptr_t try_index, |
| 1261 const RuntimeEntry& entry) { | 1325 const RuntimeEntry& entry) { |
| 1262 __ CallRuntimeFromDart(entry); | 1326 __ CallRuntimeFromDart(entry); |
| 1263 AddCurrentDescriptor(PcDescriptors::kOther, node_id, token_index); | 1327 AddCurrentDescriptor(PcDescriptors::kOther, node_id, token_index, try_index); |
| 1264 } | 1328 } |
| 1265 | 1329 |
| 1266 | 1330 |
| 1267 // Uses current pc position and try-index. | 1331 // Uses current pc position and try-index. |
| 1268 void FlowGraphCompiler::AddCurrentDescriptor(PcDescriptors::Kind kind, | 1332 void FlowGraphCompiler::AddCurrentDescriptor(PcDescriptors::Kind kind, |
| 1269 intptr_t node_id, | 1333 intptr_t node_id, |
| 1270 intptr_t token_index) { | 1334 intptr_t token_index, |
| 1335 intptr_t try_index) { |
| 1271 pc_descriptors_list_->AddDescriptor(kind, | 1336 pc_descriptors_list_->AddDescriptor(kind, |
| 1272 assembler_->CodeSize(), | 1337 assembler_->CodeSize(), |
| 1273 node_id, | 1338 node_id, |
| 1274 token_index, | 1339 token_index, |
| 1275 CatchClauseNode::kInvalidTryIndex); | 1340 try_index); |
| 1276 } | 1341 } |
| 1277 | 1342 |
| 1278 | 1343 |
| 1279 void FlowGraphCompiler::FinalizePcDescriptors(const Code& code) { | 1344 void FlowGraphCompiler::FinalizePcDescriptors(const Code& code) { |
| 1280 ASSERT(pc_descriptors_list_ != NULL); | 1345 ASSERT(pc_descriptors_list_ != NULL); |
| 1281 const PcDescriptors& descriptors = PcDescriptors::Handle( | 1346 const PcDescriptors& descriptors = PcDescriptors::Handle( |
| 1282 pc_descriptors_list_->FinalizePcDescriptors(code.EntryPoint())); | 1347 pc_descriptors_list_->FinalizePcDescriptors(code.EntryPoint())); |
| 1283 descriptors.Verify(parsed_function_.function().is_optimizable()); | 1348 descriptors.Verify(parsed_function_.function().is_optimizable()); |
| 1284 code.set_pc_descriptors(descriptors); | 1349 code.set_pc_descriptors(descriptors); |
| 1285 } | 1350 } |
| 1286 | 1351 |
| 1287 | 1352 |
| 1288 void FlowGraphCompiler::FinalizeVarDescriptors(const Code& code) { | 1353 void FlowGraphCompiler::FinalizeVarDescriptors(const Code& code) { |
| 1289 const LocalVarDescriptors& var_descs = LocalVarDescriptors::Handle( | 1354 const LocalVarDescriptors& var_descs = LocalVarDescriptors::Handle( |
| 1290 parsed_function_.node_sequence()->scope()->GetVarDescriptors()); | 1355 parsed_function_.node_sequence()->scope()->GetVarDescriptors()); |
| 1291 code.set_var_descriptors(var_descs); | 1356 code.set_var_descriptors(var_descs); |
| 1292 } | 1357 } |
| 1293 | 1358 |
| 1294 | 1359 |
| 1295 void FlowGraphCompiler::FinalizeExceptionHandlers(const Code& code) { | 1360 void FlowGraphCompiler::FinalizeExceptionHandlers(const Code& code) { |
| 1296 // We don't compile exception handlers yet. | 1361 ASSERT(exception_handlers_list_ != NULL); |
| 1297 code.set_exception_handlers( | 1362 const ExceptionHandlers& handlers = ExceptionHandlers::Handle( |
| 1298 ExceptionHandlers::Handle(ExceptionHandlers::New(0))); | 1363 exception_handlers_list_->FinalizeExceptionHandlers(code.EntryPoint())); |
| 1364 code.set_exception_handlers(handlers); |
| 1299 } | 1365 } |
| 1300 | 1366 |
| 1301 | 1367 |
| 1302 } // namespace dart | 1368 } // namespace dart |
| 1303 | 1369 |
| 1304 #endif // defined TARGET_ARCH_X64 | 1370 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |