Chromium Code Reviews| 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/code_generator.h" | 8 #include "vm/code_generator.h" | 
| 9 | 9 | 
| 10 #include "lib/error.h" | 10 #include "lib/error.h" | 
| (...skipping 769 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 780 __ LoadObject(RBX, function); | 780 __ LoadObject(RBX, function); | 
| 781 __ pushq(RBX); | 781 __ pushq(RBX); | 
| 782 GenerateCallRuntime(AstNode::kNoId, | 782 GenerateCallRuntime(AstNode::kNoId, | 
| 783 0, | 783 0, | 
| 784 kTraceFunctionExitRuntimeEntry); | 784 kTraceFunctionExitRuntimeEntry); | 
| 785 __ popq(RAX); // Remove argument. | 785 __ popq(RAX); // Remove argument. | 
| 786 __ popq(RAX); // Restore result. | 786 __ popq(RAX); // Restore result. | 
| 787 } | 787 } | 
| 788 __ LeaveFrame(); | 788 __ LeaveFrame(); | 
| 789 __ ret(); | 789 __ ret(); | 
| 790 // TODO(hausner): insert generation of of PcDescriptor::kReturn, | 790 | 
| 791 // analogous to 32bit version. | 791 // Generate 8 bytes of NOPs so that the debugger can patch the | 
| 792 // return pattern with a call to the debug stub. | |
| 793 __ nop(1); | |
| 794 __ nop(1); | |
| 795 __ nop(1); | |
| 796 __ nop(1); | |
| 797 __ nop(1); | |
| 798 __ nop(1); | |
| 799 __ nop(1); | |
| 800 __ nop(1); | |
| 
 
regis
2012/02/24 23:32:37
Why not __ nop(8)?
Disassembly would be more compa
 
hausner
2012/02/27 22:03:57
It's simpler to recognize the code pattern when I
 
 | |
| 801 AddCurrentDescriptor(PcDescriptors::kReturn, | |
| 802 node->id(), | |
| 803 node->token_index()); | |
| 804 | |
| 792 | 805 | 
| 793 #ifdef DEBUG | 806 #ifdef DEBUG | 
| 794 __ Bind(&wrong_stack); | 807 __ Bind(&wrong_stack); | 
| 795 __ Stop("Exit stack size does not match the entry stack size."); | 808 __ Stop("Exit stack size does not match the entry stack size."); | 
| 796 #endif // DEBUG. | 809 #endif // DEBUG. | 
| 797 } | 810 } | 
| 798 | 811 | 
| 799 | 812 | 
| 800 void CodeGenerator::VisitReturnNode(ReturnNode* node) { | 813 void CodeGenerator::VisitReturnNode(ReturnNode* node) { | 
| 801 ASSERT(!IsResultNeeded(node)); | 814 ASSERT(!IsResultNeeded(node)); | 
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 888 const Class& cls = Class::Handle(function.signature_class()); | 901 const Class& cls = Class::Handle(function.signature_class()); | 
| 889 ASSERT(!cls.IsNull()); | 902 ASSERT(!cls.IsNull()); | 
| 890 const bool requires_type_arguments = cls.HasTypeArguments(); | 903 const bool requires_type_arguments = cls.HasTypeArguments(); | 
| 891 if (requires_type_arguments) { | 904 if (requires_type_arguments) { | 
| 892 ASSERT(!function.IsImplicitStaticClosureFunction()); | 905 ASSERT(!function.IsImplicitStaticClosureFunction()); | 
| 893 GenerateInstantiatorTypeArguments(node->token_index()); | 906 GenerateInstantiatorTypeArguments(node->token_index()); | 
| 894 } | 907 } | 
| 895 const Code& stub = Code::Handle( | 908 const Code& stub = Code::Handle( | 
| 896 StubCode::GetAllocationStubForClosure(function)); | 909 StubCode::GetAllocationStubForClosure(function)); | 
| 897 const ExternalLabel label(function.ToCString(), stub.EntryPoint()); | 910 const ExternalLabel label(function.ToCString(), stub.EntryPoint()); | 
| 898 GenerateCall(node->token_index(), &label); | 911 GenerateCall(node->token_index(), &label, PcDescriptors::kOther); | 
| 899 if (requires_type_arguments) { | 912 if (requires_type_arguments) { | 
| 900 __ popq(RCX); // Pop type arguments. | 913 __ popq(RCX); // Pop type arguments. | 
| 901 } | 914 } | 
| 902 if (function.IsImplicitInstanceClosureFunction()) { | 915 if (function.IsImplicitInstanceClosureFunction()) { | 
| 903 __ popq(RCX); // Pop receiver. | 916 __ popq(RCX); // Pop receiver. | 
| 904 } | 917 } | 
| 905 if (IsResultNeeded(node)) { | 918 if (IsResultNeeded(node)) { | 
| 906 __ pushq(RAX); | 919 __ pushq(RAX); | 
| 907 } | 920 } | 
| 908 } | 921 } | 
| (...skipping 21 matching lines...) Expand all Loading... | |
| 930 CodeGeneratorState codegen_state(this); | 943 CodeGeneratorState codegen_state(this); | 
| 931 LocalScope* scope = node_sequence->scope(); | 944 LocalScope* scope = node_sequence->scope(); | 
| 932 const intptr_t num_context_variables = | 945 const intptr_t num_context_variables = | 
| 933 (scope != NULL) ? scope->num_context_variables() : 0; | 946 (scope != NULL) ? scope->num_context_variables() : 0; | 
| 934 if (num_context_variables > 0) { | 947 if (num_context_variables > 0) { | 
| 935 // The loop local scope declares variables that are captured. | 948 // The loop local scope declares variables that are captured. | 
| 936 // Allocate and chain a new context. | 949 // Allocate and chain a new context. | 
| 937 __ movq(R10, Immediate(num_context_variables)); | 950 __ movq(R10, Immediate(num_context_variables)); | 
| 938 const ExternalLabel label("alloc_context", | 951 const ExternalLabel label("alloc_context", | 
| 939 StubCode::AllocateContextEntryPoint()); | 952 StubCode::AllocateContextEntryPoint()); | 
| 940 GenerateCall(node_sequence->token_index(), &label); | 953 GenerateCall(node_sequence->token_index(), &label, PcDescriptors::kOther); | 
| 941 | 954 | 
| 942 // Chain the new context in RAX to its parent in CTX. | 955 // Chain the new context in RAX to its parent in CTX. | 
| 943 __ StoreIntoObject(RAX, | 956 __ StoreIntoObject(RAX, | 
| 944 FieldAddress(RAX, Context::parent_offset()), | 957 FieldAddress(RAX, Context::parent_offset()), | 
| 945 CTX); | 958 CTX); | 
| 946 // Set new context as current context. | 959 // Set new context as current context. | 
| 947 __ movq(CTX, RAX); | 960 __ movq(CTX, RAX); | 
| 948 state()->set_context_level(scope->context_level()); | 961 state()->set_context_level(scope->context_level()); | 
| 949 | 962 | 
| 950 // If this node_sequence is the body of the function being compiled, copy | 963 // If this node_sequence is the body of the function being compiled, copy | 
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1009 element->Visit(this); | 1022 element->Visit(this); | 
| 1010 } | 1023 } | 
| 1011 | 1024 | 
| 1012 // Allocate the array. | 1025 // Allocate the array. | 
| 1013 // R10 : Array length as Smi. | 1026 // R10 : Array length as Smi. | 
| 1014 // RBX : element type for the array. | 1027 // RBX : element type for the array. | 
| 1015 __ movq(R10, Immediate(Smi::RawValue(node->length()))); | 1028 __ movq(R10, Immediate(Smi::RawValue(node->length()))); | 
| 1016 const AbstractTypeArguments& element_type = node->type_arguments(); | 1029 const AbstractTypeArguments& element_type = node->type_arguments(); | 
| 1017 ASSERT(element_type.IsNull() || element_type.IsInstantiated()); | 1030 ASSERT(element_type.IsNull() || element_type.IsInstantiated()); | 
| 1018 __ LoadObject(RBX, element_type); | 1031 __ LoadObject(RBX, element_type); | 
| 1019 GenerateCall(node->token_index(), &StubCode::AllocateArrayLabel()); | 1032 GenerateCall(node->token_index(), | 
| 1033 &StubCode::AllocateArrayLabel(), | |
| 1034 PcDescriptors::kOther); | |
| 1020 | 1035 | 
| 1021 // Pop the element values from the stack into the array. | 1036 // Pop the element values from the stack into the array. | 
| 1022 __ leaq(RCX, FieldAddress(RAX, Array::data_offset())); | 1037 __ leaq(RCX, FieldAddress(RAX, Array::data_offset())); | 
| 1023 for (int i = node->length() - 1; i >= 0; i--) { | 1038 for (int i = node->length() - 1; i >= 0; i--) { | 
| 1024 __ popq(Address(RCX, i * kWordSize)); | 1039 __ popq(Address(RCX, i * kWordSize)); | 
| 1025 } | 1040 } | 
| 1026 | 1041 | 
| 1027 if (IsResultNeeded(node)) { | 1042 if (IsResultNeeded(node)) { | 
| 1028 __ pushq(RAX); | 1043 __ pushq(RAX); | 
| 1029 } | 1044 } | 
| (...skipping 1183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2213 } | 2228 } | 
| 2214 | 2229 | 
| 2215 // Could not concatenate at compile time, generate a call to | 2230 // Could not concatenate at compile time, generate a call to | 
| 2216 // interpolation function. | 2231 // interpolation function. | 
| 2217 ArgumentListNode* interpol_arg = new ArgumentListNode(node->token_index()); | 2232 ArgumentListNode* interpol_arg = new ArgumentListNode(node->token_index()); | 
| 2218 interpol_arg->Add(node->values()); | 2233 interpol_arg->Add(node->values()); | 
| 2219 node->values()->Visit(this); | 2234 node->values()->Visit(this); | 
| 2220 __ LoadObject(RBX, interpol_func); | 2235 __ LoadObject(RBX, interpol_func); | 
| 2221 __ LoadObject(R10, ArgumentsDescriptor(interpol_arg->length(), | 2236 __ LoadObject(R10, ArgumentsDescriptor(interpol_arg->length(), | 
| 2222 interpol_arg->names())); | 2237 interpol_arg->names())); | 
| 2223 GenerateCall(node->token_index(), &StubCode::CallStaticFunctionLabel()); | 2238 GenerateCall(node->token_index(), | 
| 2239 &StubCode::CallStaticFunctionLabel(), | |
| 2240 PcDescriptors::kOther); | |
| 2224 __ addq(RSP, Immediate(interpol_arg->length() * kWordSize)); | 2241 __ addq(RSP, Immediate(interpol_arg->length() * kWordSize)); | 
| 2225 // Result is in RAX. | 2242 // Result is in RAX. | 
| 2226 if (IsResultNeeded(node)) { | 2243 if (IsResultNeeded(node)) { | 
| 2227 __ pushq(RAX); | 2244 __ pushq(RAX); | 
| 2228 } | 2245 } | 
| 2229 } | 2246 } | 
| 2230 | 2247 | 
| 2231 | 2248 | 
| 2232 void CodeGenerator::VisitInstanceCallNode(InstanceCallNode* node) { | 2249 void CodeGenerator::VisitInstanceCallNode(InstanceCallNode* node) { | 
| 2233 const int number_of_arguments = node->arguments()->length() + 1; | 2250 const int number_of_arguments = node->arguments()->length() + 1; | 
| (...skipping 16 matching lines...) Expand all Loading... | |
| 2250 __ pushq(RAX); | 2267 __ pushq(RAX); | 
| 2251 } | 2268 } | 
| 2252 } | 2269 } | 
| 2253 | 2270 | 
| 2254 | 2271 | 
| 2255 void CodeGenerator::VisitStaticCallNode(StaticCallNode* node) { | 2272 void CodeGenerator::VisitStaticCallNode(StaticCallNode* node) { | 
| 2256 node->arguments()->Visit(this); | 2273 node->arguments()->Visit(this); | 
| 2257 __ LoadObject(RBX, node->function()); | 2274 __ LoadObject(RBX, node->function()); | 
| 2258 __ LoadObject(R10, ArgumentsDescriptor(node->arguments()->length(), | 2275 __ LoadObject(R10, ArgumentsDescriptor(node->arguments()->length(), | 
| 2259 node->arguments()->names())); | 2276 node->arguments()->names())); | 
| 2260 GenerateCall(node->token_index(), &StubCode::CallStaticFunctionLabel()); | 2277 GenerateCall(node->token_index(), | 
| 2278 &StubCode::CallStaticFunctionLabel(), | |
| 2279 PcDescriptors::kFuncCall); | |
| 2261 __ addq(RSP, Immediate(node->arguments()->length() * kWordSize)); | 2280 __ addq(RSP, Immediate(node->arguments()->length() * kWordSize)); | 
| 2262 // Result is in RAX. | 2281 // Result is in RAX. | 
| 2263 if (IsResultNeeded(node)) { | 2282 if (IsResultNeeded(node)) { | 
| 2264 __ pushq(RAX); | 2283 __ pushq(RAX); | 
| 2265 } | 2284 } | 
| 2266 } | 2285 } | 
| 2267 | 2286 | 
| 2268 | 2287 | 
| 2269 void CodeGenerator::VisitClosureCallNode(ClosureCallNode* node) { | 2288 void CodeGenerator::VisitClosureCallNode(ClosureCallNode* node) { | 
| 2270 // The spec states that the closure is evaluated before the arguments. | 2289 // The spec states that the closure is evaluated before the arguments. | 
| 2271 // Preserve the current context, since it will be overridden by the closure | 2290 // Preserve the current context, since it will be overridden by the closure | 
| 2272 // context during the call. | 2291 // context during the call. | 
| 2273 __ pushq(CTX); | 2292 __ pushq(CTX); | 
| 2274 // Compute the closure object and pass it as first argument to the stub. | 2293 // Compute the closure object and pass it as first argument to the stub. | 
| 2275 node->closure()->Visit(this); | 2294 node->closure()->Visit(this); | 
| 2276 // Now compute the arguments to the call. | 2295 // Now compute the arguments to the call. | 
| 2277 node->arguments()->Visit(this); | 2296 node->arguments()->Visit(this); | 
| 2278 // Set up the number of arguments (excluding the closure) to the ClosureCall | 2297 // Set up the number of arguments (excluding the closure) to the ClosureCall | 
| 2279 // stub which will setup the closure context and jump to the entrypoint of the | 2298 // stub which will setup the closure context and jump to the entrypoint of the | 
| 2280 // closure function (the function will be compiled if it has not already been | 2299 // closure function (the function will be compiled if it has not already been | 
| 2281 // compiled). | 2300 // compiled). | 
| 2282 // NOTE: The stub accesses the closure before the parameter list. | 2301 // NOTE: The stub accesses the closure before the parameter list. | 
| 2283 __ LoadObject(R10, ArgumentsDescriptor(node->arguments()->length(), | 2302 __ LoadObject(R10, ArgumentsDescriptor(node->arguments()->length(), | 
| 2284 node->arguments()->names())); | 2303 node->arguments()->names())); | 
| 2285 GenerateCall(node->token_index(), &StubCode::CallClosureFunctionLabel()); | 2304 GenerateCall(node->token_index(), | 
| 2305 &StubCode::CallClosureFunctionLabel(), | |
| 2306 PcDescriptors::kOther); | |
| 2286 __ addq(RSP, Immediate((node->arguments()->length() + 1) * kWordSize)); | 2307 __ addq(RSP, Immediate((node->arguments()->length() + 1) * kWordSize)); | 
| 2287 // Restore the context. | 2308 // Restore the context. | 
| 2288 __ popq(CTX); | 2309 __ popq(CTX); | 
| 2289 // Result is in RAX. | 2310 // Result is in RAX. | 
| 2290 if (IsResultNeeded(node)) { | 2311 if (IsResultNeeded(node)) { | 
| 2291 __ pushq(RAX); | 2312 __ pushq(RAX); | 
| 2292 } | 2313 } | 
| 2293 } | 2314 } | 
| 2294 | 2315 | 
| 2295 | 2316 | 
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2420 const bool requires_type_arguments = true; // Always first arg to factory. | 2441 const bool requires_type_arguments = true; // Always first arg to factory. | 
| 2421 GenerateTypeArguments(node, requires_type_arguments); | 2442 GenerateTypeArguments(node, requires_type_arguments); | 
| 2422 // The top of stack is an instantiated AbstractTypeArguments object | 2443 // The top of stack is an instantiated AbstractTypeArguments object | 
| 2423 // (or null). | 2444 // (or null). | 
| 2424 int num_args = node->arguments()->length() + 1; // +1 to include type args. | 2445 int num_args = node->arguments()->length() + 1; // +1 to include type args. | 
| 2425 node->arguments()->Visit(this); | 2446 node->arguments()->Visit(this); | 
| 2426 // Call the factory. | 2447 // Call the factory. | 
| 2427 __ LoadObject(RBX, node->constructor()); | 2448 __ LoadObject(RBX, node->constructor()); | 
| 2428 __ LoadObject(R10, ArgumentsDescriptor(num_args, | 2449 __ LoadObject(R10, ArgumentsDescriptor(num_args, | 
| 2429 node->arguments()->names())); | 2450 node->arguments()->names())); | 
| 2430 GenerateCall(node->token_index(), &StubCode::CallStaticFunctionLabel()); | 2451 GenerateCall(node->token_index(), | 
| 2452 &StubCode::CallStaticFunctionLabel(), | |
| 2453 PcDescriptors::kFuncCall); | |
| 2431 // Factory constructor returns object in RAX. | 2454 // Factory constructor returns object in RAX. | 
| 2432 __ addq(RSP, Immediate(num_args * kWordSize)); | 2455 __ addq(RSP, Immediate(num_args * kWordSize)); | 
| 2433 if (IsResultNeeded(node)) { | 2456 if (IsResultNeeded(node)) { | 
| 2434 __ pushq(RAX); | 2457 __ pushq(RAX); | 
| 2435 } | 2458 } | 
| 2436 return; | 2459 return; | 
| 2437 } | 2460 } | 
| 2438 | 2461 | 
| 2439 const Class& cls = Class::ZoneHandle(node->constructor().owner()); | 2462 const Class& cls = Class::ZoneHandle(node->constructor().owner()); | 
| 2440 const bool requires_type_arguments = cls.HasTypeArguments(); | 2463 const bool requires_type_arguments = cls.HasTypeArguments(); | 
| 2441 GenerateTypeArguments(node, requires_type_arguments); | 2464 GenerateTypeArguments(node, requires_type_arguments); | 
| 2442 | 2465 | 
| 2443 // If cls is parameterized, the type arguments and the instantiator's | 2466 // If cls is parameterized, the type arguments and the instantiator's | 
| 2444 // type arguments are on the stack. | 2467 // type arguments are on the stack. | 
| 2445 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls)); | 2468 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls)); | 
| 2446 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); | 2469 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); | 
| 2447 GenerateCall(node->token_index(), &label); | 2470 GenerateCall(node->token_index(), &label, PcDescriptors::kOther); | 
| 2448 if (requires_type_arguments) { | 2471 if (requires_type_arguments) { | 
| 2449 __ popq(RCX); // Pop type arguments. | 2472 __ popq(RCX); // Pop type arguments. | 
| 2450 __ popq(RCX); // Pop instantiator type arguments. | 2473 __ popq(RCX); // Pop instantiator type arguments. | 
| 2451 } | 2474 } | 
| 2452 | 2475 | 
| 2453 if (IsResultNeeded(node)) { | 2476 if (IsResultNeeded(node)) { | 
| 2454 __ pushq(RAX); // Set up return value from allocate. | 2477 __ pushq(RAX); // Set up return value from allocate. | 
| 2455 } | 2478 } | 
| 2456 | 2479 | 
| 2457 // First argument(this) for constructor call which follows. | 2480 // First argument(this) for constructor call which follows. | 
| 2458 __ pushq(RAX); | 2481 __ pushq(RAX); | 
| 2459 // Second argument is the implicit construction phase parameter. | 2482 // Second argument is the implicit construction phase parameter. | 
| 2460 // Run both the constructor initializer list and the constructor body. | 2483 // Run both the constructor initializer list and the constructor body. | 
| 2461 __ PushObject(Smi::ZoneHandle(Smi::New(Function::kCtorPhaseAll))); | 2484 __ PushObject(Smi::ZoneHandle(Smi::New(Function::kCtorPhaseAll))); | 
| 2462 | 2485 | 
| 2463 | 2486 | 
| 2464 // Now setup rest of the arguments for the constructor call. | 2487 // Now setup rest of the arguments for the constructor call. | 
| 2465 node->arguments()->Visit(this); | 2488 node->arguments()->Visit(this); | 
| 2466 | 2489 | 
| 2467 // Call the constructor. | 2490 // Call the constructor. | 
| 2468 // +2 to include implicit receiver and phase arguments. | 2491 // +2 to include implicit receiver and phase arguments. | 
| 2469 int num_args = node->arguments()->length() + 2; | 2492 int num_args = node->arguments()->length() + 2; | 
| 2470 __ LoadObject(RBX, node->constructor()); | 2493 __ LoadObject(RBX, node->constructor()); | 
| 2471 __ LoadObject(R10, ArgumentsDescriptor(num_args, node->arguments()->names())); | 2494 __ LoadObject(R10, ArgumentsDescriptor(num_args, node->arguments()->names())); | 
| 2472 GenerateCall(node->token_index(), &StubCode::CallStaticFunctionLabel()); | 2495 GenerateCall(node->token_index(), | 
| 2496 &StubCode::CallStaticFunctionLabel(), | |
| 2497 PcDescriptors::kFuncCall); | |
| 2473 // Constructors do not return any value. | 2498 // Constructors do not return any value. | 
| 2474 | 2499 | 
| 2475 // Pop out all the other arguments on the stack. | 2500 // Pop out all the other arguments on the stack. | 
| 2476 __ addq(RSP, Immediate(num_args * kWordSize)); | 2501 __ addq(RSP, Immediate(num_args * kWordSize)); | 
| 2477 } | 2502 } | 
| 2478 | 2503 | 
| 2479 | 2504 | 
| 2480 // Expects receiver on stack, returns result in RAX.. | 2505 // Expects receiver on stack, returns result in RAX.. | 
| 2481 void CodeGenerator::GenerateInstanceGetterCall(intptr_t node_id, | 2506 void CodeGenerator::GenerateInstanceGetterCall(intptr_t node_id, | 
| 2482 intptr_t token_index, | 2507 intptr_t token_index, | 
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2556 const Function& function = | 2581 const Function& function = | 
| 2557 Function::ZoneHandle(field_class.LookupStaticFunction(getter_name)); | 2582 Function::ZoneHandle(field_class.LookupStaticFunction(getter_name)); | 
| 2558 if (function.IsNull()) { | 2583 if (function.IsNull()) { | 
| 2559 ErrorMsg(token_index, "Static getter does not exist: %s", | 2584 ErrorMsg(token_index, "Static getter does not exist: %s", | 
| 2560 getter_name.ToCString()); | 2585 getter_name.ToCString()); | 
| 2561 } | 2586 } | 
| 2562 __ LoadObject(RBX, function); | 2587 __ LoadObject(RBX, function); | 
| 2563 const int kNumberOfArguments = 0; | 2588 const int kNumberOfArguments = 0; | 
| 2564 const Array& kNoArgumentNames = Array::Handle(); | 2589 const Array& kNoArgumentNames = Array::Handle(); | 
| 2565 __ LoadObject(R10, ArgumentsDescriptor(kNumberOfArguments, kNoArgumentNames)); | 2590 __ LoadObject(R10, ArgumentsDescriptor(kNumberOfArguments, kNoArgumentNames)); | 
| 2566 GenerateCall(token_index, &StubCode::CallStaticFunctionLabel()); | 2591 GenerateCall(token_index, | 
| 2592 &StubCode::CallStaticFunctionLabel(), | |
| 2593 PcDescriptors::kFuncCall); | |
| 2567 // No arguments were pushed, hence nothing to pop. | 2594 // No arguments were pushed, hence nothing to pop. | 
| 2568 } | 2595 } | 
| 2569 | 2596 | 
| 2570 | 2597 | 
| 2571 // Call to static getter. | 2598 // Call to static getter. | 
| 2572 void CodeGenerator::VisitStaticGetterNode(StaticGetterNode* node) { | 2599 void CodeGenerator::VisitStaticGetterNode(StaticGetterNode* node) { | 
| 2573 GenerateStaticGetterCall(node->token_index(), | 2600 GenerateStaticGetterCall(node->token_index(), | 
| 2574 node->cls(), | 2601 node->cls(), | 
| 2575 node->field_name()); | 2602 node->field_name()); | 
| 2576 // Result is in RAX. | 2603 // Result is in RAX. | 
| 2577 if (IsResultNeeded(node)) { | 2604 if (IsResultNeeded(node)) { | 
| 2578 __ pushq(RAX); | 2605 __ pushq(RAX); | 
| 2579 } | 2606 } | 
| 2580 } | 2607 } | 
| 2581 | 2608 | 
| 2582 | 2609 | 
| 2583 // Expects value on stack. | 2610 // Expects value on stack. | 
| 2584 void CodeGenerator::GenerateStaticSetterCall(intptr_t token_index, | 2611 void CodeGenerator::GenerateStaticSetterCall(intptr_t token_index, | 
| 2585 const Class& field_class, | 2612 const Class& field_class, | 
| 2586 const String& field_name) { | 2613 const String& field_name) { | 
| 2587 const String& setter_name = String::Handle(Field::SetterName(field_name)); | 2614 const String& setter_name = String::Handle(Field::SetterName(field_name)); | 
| 2588 const Function& function = | 2615 const Function& function = | 
| 2589 Function::ZoneHandle(field_class.LookupStaticFunction(setter_name)); | 2616 Function::ZoneHandle(field_class.LookupStaticFunction(setter_name)); | 
| 2590 __ LoadObject(RBX, function); | 2617 __ LoadObject(RBX, function); | 
| 2591 const int kNumberOfArguments = 1; // value. | 2618 const int kNumberOfArguments = 1; // value. | 
| 2592 const Array& kNoArgumentNames = Array::Handle(); | 2619 const Array& kNoArgumentNames = Array::Handle(); | 
| 2593 __ LoadObject(R10, ArgumentsDescriptor(kNumberOfArguments, kNoArgumentNames)); | 2620 __ LoadObject(R10, ArgumentsDescriptor(kNumberOfArguments, kNoArgumentNames)); | 
| 2594 GenerateCall(token_index, &StubCode::CallStaticFunctionLabel()); | 2621 GenerateCall(token_index, | 
| 2622 &StubCode::CallStaticFunctionLabel(), | |
| 2623 PcDescriptors::kFuncCall); | |
| 2595 __ addq(RSP, Immediate(kNumberOfArguments * kWordSize)); | 2624 __ addq(RSP, Immediate(kNumberOfArguments * kWordSize)); | 
| 2596 } | 2625 } | 
| 2597 | 2626 | 
| 2598 | 2627 | 
| 2599 // The call to static setter implements assignment to a static field. | 2628 // The call to static setter implements assignment to a static field. | 
| 2600 // The result of the assignment is the value being stored. | 2629 // The result of the assignment is the value being stored. | 
| 2601 void CodeGenerator::VisitStaticSetterNode(StaticSetterNode* node) { | 2630 void CodeGenerator::VisitStaticSetterNode(StaticSetterNode* node) { | 
| 2602 node->value()->Visit(this); | 2631 node->value()->Visit(this); | 
| 2603 if (IsResultNeeded(node)) { | 2632 if (IsResultNeeded(node)) { | 
| 2604 // Preserve the original value when returning from setter. | 2633 // Preserve the original value when returning from setter. | 
| (...skipping 12 matching lines...) Expand all Loading... | |
| 2617 // Push the result place holder initialized to NULL. | 2646 // Push the result place holder initialized to NULL. | 
| 2618 __ PushObject(Object::ZoneHandle()); | 2647 __ PushObject(Object::ZoneHandle()); | 
| 2619 // Pass a pointer to the first argument in RAX. | 2648 // Pass a pointer to the first argument in RAX. | 
| 2620 if (!node->has_optional_parameters()) { | 2649 if (!node->has_optional_parameters()) { | 
| 2621 __ leaq(RAX, Address(RBP, (1 + node->argument_count()) * kWordSize)); | 2650 __ leaq(RAX, Address(RBP, (1 + node->argument_count()) * kWordSize)); | 
| 2622 } else { | 2651 } else { | 
| 2623 __ leaq(RAX, Address(RBP, -1 * kWordSize)); | 2652 __ leaq(RAX, Address(RBP, -1 * kWordSize)); | 
| 2624 } | 2653 } | 
| 2625 __ movq(RBX, Immediate(reinterpret_cast<uword>(node->native_c_function()))); | 2654 __ movq(RBX, Immediate(reinterpret_cast<uword>(node->native_c_function()))); | 
| 2626 __ movq(R10, Immediate(node->argument_count())); | 2655 __ movq(R10, Immediate(node->argument_count())); | 
| 2627 GenerateCall(node->token_index(), &StubCode::CallNativeCFunctionLabel()); | 2656 GenerateCall(node->token_index(), | 
| 2657 &StubCode::CallNativeCFunctionLabel(), | |
| 2658 PcDescriptors::kOther); | |
| 2628 // Result is on the stack. | 2659 // Result is on the stack. | 
| 2629 if (!IsResultNeeded(node)) { | 2660 if (!IsResultNeeded(node)) { | 
| 2630 __ popq(RAX); | 2661 __ popq(RAX); | 
| 2631 } | 2662 } | 
| 2632 } | 2663 } | 
| 2633 | 2664 | 
| 2634 | 2665 | 
| 2635 void CodeGenerator::VisitCatchClauseNode(CatchClauseNode* node) { | 2666 void CodeGenerator::VisitCatchClauseNode(CatchClauseNode* node) { | 
| 2636 // NOTE: The implicit variables ':saved_context', ':exception_var' | 2667 // NOTE: The implicit variables ':saved_context', ':exception_var' | 
| 2637 // and ':stacktrace_var' can never be captured variables. | 2668 // and ':stacktrace_var' can never be captured variables. | 
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2743 GenerateLoadVariable(CTX, node->context_var()); | 2774 GenerateLoadVariable(CTX, node->context_var()); | 
| 2744 node->finally_block()->Visit(this); | 2775 node->finally_block()->Visit(this); | 
| 2745 | 2776 | 
| 2746 if (try_index >= 0) { | 2777 if (try_index >= 0) { | 
| 2747 state()->set_try_index(try_index); | 2778 state()->set_try_index(try_index); | 
| 2748 } | 2779 } | 
| 2749 } | 2780 } | 
| 2750 | 2781 | 
| 2751 | 2782 | 
| 2752 void CodeGenerator::GenerateCall(intptr_t token_index, | 2783 void CodeGenerator::GenerateCall(intptr_t token_index, | 
| 2753 const ExternalLabel* ext_label) { | 2784 const ExternalLabel* ext_label, | 
| 2785 PcDescriptors::Kind desc_kind) { | |
| 2754 __ call(ext_label); | 2786 __ call(ext_label); | 
| 2755 AddCurrentDescriptor(PcDescriptors::kOther, AstNode::kNoId, token_index); | 2787 AddCurrentDescriptor(desc_kind, AstNode::kNoId, token_index); | 
| 2756 } | 2788 } | 
| 2757 | 2789 | 
| 2758 | 2790 | 
| 2759 void CodeGenerator::GenerateCallRuntime(intptr_t node_id, | 2791 void CodeGenerator::GenerateCallRuntime(intptr_t node_id, | 
| 2760 intptr_t token_index, | 2792 intptr_t token_index, | 
| 2761 const RuntimeEntry& entry) { | 2793 const RuntimeEntry& entry) { | 
| 2762 __ CallRuntimeFromDart(entry); | 2794 __ CallRuntimeFromDart(entry); | 
| 2763 AddCurrentDescriptor(PcDescriptors::kOther, node_id, token_index); | 2795 AddCurrentDescriptor(PcDescriptors::kOther, node_id, token_index); | 
| 2764 } | 2796 } | 
| 2765 | 2797 | 
| (...skipping 25 matching lines...) Expand all Loading... | |
| 2791 const Error& error = Error::Handle( | 2823 const Error& error = Error::Handle( | 
| 2792 Parser::FormatError(script, token_index, "Error", format, args)); | 2824 Parser::FormatError(script, token_index, "Error", format, args)); | 
| 2793 va_end(args); | 2825 va_end(args); | 
| 2794 Isolate::Current()->long_jump_base()->Jump(1, error); | 2826 Isolate::Current()->long_jump_base()->Jump(1, error); | 
| 2795 UNREACHABLE(); | 2827 UNREACHABLE(); | 
| 2796 } | 2828 } | 
| 2797 | 2829 | 
| 2798 } // namespace dart | 2830 } // namespace dart | 
| 2799 | 2831 | 
| 2800 #endif // defined TARGET_ARCH_X64 | 2832 #endif // defined TARGET_ARCH_X64 | 
| OLD | NEW |