| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
| 6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
| 7 | 7 |
| 8 #include "vm/code_generator.h" | 8 #include "vm/code_generator.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 774 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 785 kTraceFunctionExitRuntimeEntry); | 785 kTraceFunctionExitRuntimeEntry); |
| 786 __ popl(EAX); // Remove argument. | 786 __ popl(EAX); // Remove argument. |
| 787 __ popl(EAX); // Restore result. | 787 __ popl(EAX); // Restore result. |
| 788 } | 788 } |
| 789 __ LeaveFrame(); | 789 __ LeaveFrame(); |
| 790 __ ret(); | 790 __ ret(); |
| 791 // Add a NOP to make return code pattern 5 bytes long for patching | 791 // Add a NOP to make return code pattern 5 bytes long for patching |
| 792 // in breakpoints during debugging. | 792 // in breakpoints during debugging. |
| 793 __ nop(1); | 793 __ nop(1); |
| 794 AddCurrentDescriptor(PcDescriptors::kReturn, | 794 AddCurrentDescriptor(PcDescriptors::kReturn, |
| 795 AstNode::kNoId, | 795 node->id(), |
| 796 node->token_index()); | 796 node->token_index()); |
| 797 | 797 |
| 798 #ifdef DEBUG | 798 #ifdef DEBUG |
| 799 __ Bind(&wrong_stack); | 799 __ Bind(&wrong_stack); |
| 800 __ Stop("Exit stack size does not match the entry stack size."); | 800 __ Stop("Exit stack size does not match the entry stack size."); |
| 801 #endif // DEBUG. | 801 #endif // DEBUG. |
| 802 } | 802 } |
| 803 | 803 |
| 804 | 804 |
| 805 void CodeGenerator::VisitReturnNode(ReturnNode* node) { | 805 void CodeGenerator::VisitReturnNode(ReturnNode* node) { |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 893 const Class& cls = Class::Handle(function.signature_class()); | 893 const Class& cls = Class::Handle(function.signature_class()); |
| 894 ASSERT(!cls.IsNull()); | 894 ASSERT(!cls.IsNull()); |
| 895 const bool requires_type_arguments = cls.HasTypeArguments(); | 895 const bool requires_type_arguments = cls.HasTypeArguments(); |
| 896 if (requires_type_arguments) { | 896 if (requires_type_arguments) { |
| 897 ASSERT(!function.IsImplicitStaticClosureFunction()); | 897 ASSERT(!function.IsImplicitStaticClosureFunction()); |
| 898 GenerateInstantiatorTypeArguments(node->token_index()); | 898 GenerateInstantiatorTypeArguments(node->token_index()); |
| 899 } | 899 } |
| 900 const Code& stub = Code::Handle( | 900 const Code& stub = Code::Handle( |
| 901 StubCode::GetAllocationStubForClosure(function)); | 901 StubCode::GetAllocationStubForClosure(function)); |
| 902 const ExternalLabel label(function.ToCString(), stub.EntryPoint()); | 902 const ExternalLabel label(function.ToCString(), stub.EntryPoint()); |
| 903 GenerateCall(node->token_index(), &label); | 903 GenerateCall(node->token_index(), &label, PcDescriptors::kOther); |
| 904 if (requires_type_arguments) { | 904 if (requires_type_arguments) { |
| 905 __ popl(ECX); // Pop type arguments. | 905 __ popl(ECX); // Pop type arguments. |
| 906 } | 906 } |
| 907 if (function.IsImplicitInstanceClosureFunction()) { | 907 if (function.IsImplicitInstanceClosureFunction()) { |
| 908 __ popl(ECX); // Pop receiver. | 908 __ popl(ECX); // Pop receiver. |
| 909 } | 909 } |
| 910 if (IsResultNeeded(node)) { | 910 if (IsResultNeeded(node)) { |
| 911 __ pushl(EAX); | 911 __ pushl(EAX); |
| 912 } | 912 } |
| 913 } | 913 } |
| (...skipping 21 matching lines...) Expand all Loading... |
| 935 CodeGeneratorState codegen_state(this); | 935 CodeGeneratorState codegen_state(this); |
| 936 LocalScope* scope = node_sequence->scope(); | 936 LocalScope* scope = node_sequence->scope(); |
| 937 const intptr_t num_context_variables = | 937 const intptr_t num_context_variables = |
| 938 (scope != NULL) ? scope->num_context_variables() : 0; | 938 (scope != NULL) ? scope->num_context_variables() : 0; |
| 939 if (num_context_variables > 0) { | 939 if (num_context_variables > 0) { |
| 940 // The loop local scope declares variables that are captured. | 940 // The loop local scope declares variables that are captured. |
| 941 // Allocate and chain a new context. | 941 // Allocate and chain a new context. |
| 942 __ movl(EDX, Immediate(num_context_variables)); | 942 __ movl(EDX, Immediate(num_context_variables)); |
| 943 const ExternalLabel label("alloc_context", | 943 const ExternalLabel label("alloc_context", |
| 944 StubCode::AllocateContextEntryPoint()); | 944 StubCode::AllocateContextEntryPoint()); |
| 945 GenerateCall(node_sequence->token_index(), &label); | 945 GenerateCall(node_sequence->token_index(), &label, PcDescriptors::kOther); |
| 946 | 946 |
| 947 // Chain the new context in EAX to its parent in CTX. | 947 // Chain the new context in EAX to its parent in CTX. |
| 948 __ StoreIntoObject(EAX, FieldAddress(EAX, Context::parent_offset()), CTX); | 948 __ StoreIntoObject(EAX, FieldAddress(EAX, Context::parent_offset()), CTX); |
| 949 // Set new context as current context. | 949 // Set new context as current context. |
| 950 __ movl(CTX, EAX); | 950 __ movl(CTX, EAX); |
| 951 state()->set_context_level(scope->context_level()); | 951 state()->set_context_level(scope->context_level()); |
| 952 | 952 |
| 953 // If this node_sequence is the body of the function being compiled, copy | 953 // If this node_sequence is the body of the function being compiled, copy |
| 954 // the captured parameters from the frame into the context. | 954 // the captured parameters from the frame into the context. |
| 955 if (node_sequence == parsed_function_.node_sequence()) { | 955 if (node_sequence == parsed_function_.node_sequence()) { |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1012 element->Visit(this); | 1012 element->Visit(this); |
| 1013 } | 1013 } |
| 1014 | 1014 |
| 1015 // Allocate the array. | 1015 // Allocate the array. |
| 1016 // EDX : Array length as Smi. | 1016 // EDX : Array length as Smi. |
| 1017 // ECX : element type for the array. | 1017 // ECX : element type for the array. |
| 1018 __ movl(EDX, Immediate(Smi::RawValue(node->length()))); | 1018 __ movl(EDX, Immediate(Smi::RawValue(node->length()))); |
| 1019 const AbstractTypeArguments& element_type = node->type_arguments(); | 1019 const AbstractTypeArguments& element_type = node->type_arguments(); |
| 1020 ASSERT(element_type.IsNull() || element_type.IsInstantiated()); | 1020 ASSERT(element_type.IsNull() || element_type.IsInstantiated()); |
| 1021 __ LoadObject(ECX, element_type); | 1021 __ LoadObject(ECX, element_type); |
| 1022 GenerateCall(node->token_index(), &StubCode::AllocateArrayLabel()); | 1022 GenerateCall(node->token_index(), |
| 1023 &StubCode::AllocateArrayLabel(), |
| 1024 PcDescriptors::kOther); |
| 1023 | 1025 |
| 1024 // Pop the element values from the stack into the array. | 1026 // Pop the element values from the stack into the array. |
| 1025 __ leal(ECX, FieldAddress(EAX, Array::data_offset())); | 1027 __ leal(ECX, FieldAddress(EAX, Array::data_offset())); |
| 1026 for (int i = node->length() - 1; i >= 0; i--) { | 1028 for (int i = node->length() - 1; i >= 0; i--) { |
| 1027 __ popl(Address(ECX, i * kWordSize)); | 1029 __ popl(Address(ECX, i * kWordSize)); |
| 1028 } | 1030 } |
| 1029 | 1031 |
| 1030 if (IsResultNeeded(node)) { | 1032 if (IsResultNeeded(node)) { |
| 1031 __ pushl(EAX); | 1033 __ pushl(EAX); |
| 1032 } | 1034 } |
| (...skipping 1184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2217 } | 2219 } |
| 2218 | 2220 |
| 2219 // Could not concatenate at compile time, generate a call to | 2221 // Could not concatenate at compile time, generate a call to |
| 2220 // interpolation function. | 2222 // interpolation function. |
| 2221 ArgumentListNode* interpol_arg = new ArgumentListNode(node->token_index()); | 2223 ArgumentListNode* interpol_arg = new ArgumentListNode(node->token_index()); |
| 2222 interpol_arg->Add(node->values()); | 2224 interpol_arg->Add(node->values()); |
| 2223 node->values()->Visit(this); | 2225 node->values()->Visit(this); |
| 2224 __ LoadObject(ECX, interpol_func); | 2226 __ LoadObject(ECX, interpol_func); |
| 2225 __ LoadObject(EDX, ArgumentsDescriptor(interpol_arg->length(), | 2227 __ LoadObject(EDX, ArgumentsDescriptor(interpol_arg->length(), |
| 2226 interpol_arg->names())); | 2228 interpol_arg->names())); |
| 2227 GenerateCall(node->token_index(), &StubCode::CallStaticFunctionLabel()); | 2229 GenerateCall(node->token_index(), |
| 2230 &StubCode::CallStaticFunctionLabel(), |
| 2231 PcDescriptors::kFuncCall); |
| 2228 __ addl(ESP, Immediate(interpol_arg->length() * kWordSize)); | 2232 __ addl(ESP, Immediate(interpol_arg->length() * kWordSize)); |
| 2229 // Result is in EAX. | 2233 // Result is in EAX. |
| 2230 if (IsResultNeeded(node)) { | 2234 if (IsResultNeeded(node)) { |
| 2231 __ pushl(EAX); | 2235 __ pushl(EAX); |
| 2232 } | 2236 } |
| 2233 } | 2237 } |
| 2234 | 2238 |
| 2235 | 2239 |
| 2236 void CodeGenerator::VisitInstanceCallNode(InstanceCallNode* node) { | 2240 void CodeGenerator::VisitInstanceCallNode(InstanceCallNode* node) { |
| 2237 const int number_of_arguments = node->arguments()->length() + 1; | 2241 const int number_of_arguments = node->arguments()->length() + 1; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2254 __ pushl(EAX); | 2258 __ pushl(EAX); |
| 2255 } | 2259 } |
| 2256 } | 2260 } |
| 2257 | 2261 |
| 2258 | 2262 |
| 2259 void CodeGenerator::VisitStaticCallNode(StaticCallNode* node) { | 2263 void CodeGenerator::VisitStaticCallNode(StaticCallNode* node) { |
| 2260 node->arguments()->Visit(this); | 2264 node->arguments()->Visit(this); |
| 2261 __ LoadObject(ECX, node->function()); | 2265 __ LoadObject(ECX, node->function()); |
| 2262 __ LoadObject(EDX, ArgumentsDescriptor(node->arguments()->length(), | 2266 __ LoadObject(EDX, ArgumentsDescriptor(node->arguments()->length(), |
| 2263 node->arguments()->names())); | 2267 node->arguments()->names())); |
| 2264 GenerateCall(node->token_index(), &StubCode::CallStaticFunctionLabel()); | 2268 GenerateCall(node->token_index(), |
| 2269 &StubCode::CallStaticFunctionLabel(), |
| 2270 PcDescriptors::kFuncCall); |
| 2265 __ addl(ESP, Immediate(node->arguments()->length() * kWordSize)); | 2271 __ addl(ESP, Immediate(node->arguments()->length() * kWordSize)); |
| 2266 // Result is in EAX. | 2272 // Result is in EAX. |
| 2267 if (IsResultNeeded(node)) { | 2273 if (IsResultNeeded(node)) { |
| 2268 __ pushl(EAX); | 2274 __ pushl(EAX); |
| 2269 } | 2275 } |
| 2270 } | 2276 } |
| 2271 | 2277 |
| 2272 | 2278 |
| 2273 void CodeGenerator::VisitClosureCallNode(ClosureCallNode* node) { | 2279 void CodeGenerator::VisitClosureCallNode(ClosureCallNode* node) { |
| 2274 // The spec states that the closure is evaluated before the arguments. | 2280 // The spec states that the closure is evaluated before the arguments. |
| 2275 // Preserve the current context, since it will be overridden by the closure | 2281 // Preserve the current context, since it will be overridden by the closure |
| 2276 // context during the call. | 2282 // context during the call. |
| 2277 __ pushl(CTX); | 2283 __ pushl(CTX); |
| 2278 // Compute the closure object and pass it as first argument to the stub. | 2284 // Compute the closure object and pass it as first argument to the stub. |
| 2279 node->closure()->Visit(this); | 2285 node->closure()->Visit(this); |
| 2280 // Now compute the arguments to the call. | 2286 // Now compute the arguments to the call. |
| 2281 node->arguments()->Visit(this); | 2287 node->arguments()->Visit(this); |
| 2282 // Set up the number of arguments (excluding the closure) to the ClosureCall | 2288 // Set up the number of arguments (excluding the closure) to the ClosureCall |
| 2283 // stub which will setup the closure context and jump to the entrypoint of the | 2289 // stub which will setup the closure context and jump to the entrypoint of the |
| 2284 // closure function (the function will be compiled if it has not already been | 2290 // closure function (the function will be compiled if it has not already been |
| 2285 // compiled). | 2291 // compiled). |
| 2286 // NOTE: The stub accesses the closure before the parameter list. | 2292 // NOTE: The stub accesses the closure before the parameter list. |
| 2287 __ LoadObject(EDX, ArgumentsDescriptor(node->arguments()->length(), | 2293 __ LoadObject(EDX, ArgumentsDescriptor(node->arguments()->length(), |
| 2288 node->arguments()->names())); | 2294 node->arguments()->names())); |
| 2289 GenerateCall(node->token_index(), &StubCode::CallClosureFunctionLabel()); | 2295 GenerateCall(node->token_index(), |
| 2296 &StubCode::CallClosureFunctionLabel(), |
| 2297 PcDescriptors::kOther); |
| 2290 __ addl(ESP, Immediate((node->arguments()->length() + 1) * kWordSize)); | 2298 __ addl(ESP, Immediate((node->arguments()->length() + 1) * kWordSize)); |
| 2291 // Restore the context. | 2299 // Restore the context. |
| 2292 __ popl(CTX); | 2300 __ popl(CTX); |
| 2293 // Result is in EAX. | 2301 // Result is in EAX. |
| 2294 if (IsResultNeeded(node)) { | 2302 if (IsResultNeeded(node)) { |
| 2295 __ pushl(EAX); | 2303 __ pushl(EAX); |
| 2296 } | 2304 } |
| 2297 } | 2305 } |
| 2298 | 2306 |
| 2299 | 2307 |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2424 const bool requires_type_arguments = true; // Always first arg to factory. | 2432 const bool requires_type_arguments = true; // Always first arg to factory. |
| 2425 GenerateTypeArguments(node, requires_type_arguments); | 2433 GenerateTypeArguments(node, requires_type_arguments); |
| 2426 // The top of stack is an instantiated AbstractTypeArguments object | 2434 // The top of stack is an instantiated AbstractTypeArguments object |
| 2427 // (or null). | 2435 // (or null). |
| 2428 int num_args = node->arguments()->length() + 1; // +1 to include type args. | 2436 int num_args = node->arguments()->length() + 1; // +1 to include type args. |
| 2429 node->arguments()->Visit(this); | 2437 node->arguments()->Visit(this); |
| 2430 // Call the factory. | 2438 // Call the factory. |
| 2431 __ LoadObject(ECX, node->constructor()); | 2439 __ LoadObject(ECX, node->constructor()); |
| 2432 __ LoadObject(EDX, ArgumentsDescriptor(num_args, | 2440 __ LoadObject(EDX, ArgumentsDescriptor(num_args, |
| 2433 node->arguments()->names())); | 2441 node->arguments()->names())); |
| 2434 GenerateCall(node->token_index(), &StubCode::CallStaticFunctionLabel()); | 2442 GenerateCall(node->token_index(), |
| 2443 &StubCode::CallStaticFunctionLabel(), |
| 2444 PcDescriptors::kFuncCall); |
| 2435 // Factory constructor returns object in EAX. | 2445 // Factory constructor returns object in EAX. |
| 2436 __ addl(ESP, Immediate(num_args * kWordSize)); | 2446 __ addl(ESP, Immediate(num_args * kWordSize)); |
| 2437 if (IsResultNeeded(node)) { | 2447 if (IsResultNeeded(node)) { |
| 2438 __ pushl(EAX); | 2448 __ pushl(EAX); |
| 2439 } | 2449 } |
| 2440 return; | 2450 return; |
| 2441 } | 2451 } |
| 2442 | 2452 |
| 2443 const Class& cls = Class::ZoneHandle(node->constructor().owner()); | 2453 const Class& cls = Class::ZoneHandle(node->constructor().owner()); |
| 2444 const bool requires_type_arguments = cls.HasTypeArguments(); | 2454 const bool requires_type_arguments = cls.HasTypeArguments(); |
| 2445 GenerateTypeArguments(node, requires_type_arguments); | 2455 GenerateTypeArguments(node, requires_type_arguments); |
| 2446 | 2456 |
| 2447 // If cls is parameterized, the type arguments and the instantiator's | 2457 // If cls is parameterized, the type arguments and the instantiator's |
| 2448 // type arguments are on the stack. | 2458 // type arguments are on the stack. |
| 2449 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls)); | 2459 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls)); |
| 2450 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); | 2460 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); |
| 2451 GenerateCall(node->token_index(), &label); | 2461 GenerateCall(node->token_index(), &label, PcDescriptors::kOther); |
| 2452 if (requires_type_arguments) { | 2462 if (requires_type_arguments) { |
| 2453 __ popl(ECX); // Pop type arguments. | 2463 __ popl(ECX); // Pop type arguments. |
| 2454 __ popl(ECX); // Pop instantiator type arguments. | 2464 __ popl(ECX); // Pop instantiator type arguments. |
| 2455 } | 2465 } |
| 2456 | 2466 |
| 2457 if (IsResultNeeded(node)) { | 2467 if (IsResultNeeded(node)) { |
| 2458 __ pushl(EAX); // Set up return value from allocate. | 2468 __ pushl(EAX); // Set up return value from allocate. |
| 2459 } | 2469 } |
| 2460 | 2470 |
| 2461 // First argument(this) for constructor call which follows. | 2471 // First argument(this) for constructor call which follows. |
| 2462 __ pushl(EAX); | 2472 __ pushl(EAX); |
| 2463 // Second argument is the implicit construction phase parameter. | 2473 // Second argument is the implicit construction phase parameter. |
| 2464 // Run both the constructor initializer list and the constructor body. | 2474 // Run both the constructor initializer list and the constructor body. |
| 2465 __ PushObject(Smi::ZoneHandle(Smi::New(Function::kCtorPhaseAll))); | 2475 __ PushObject(Smi::ZoneHandle(Smi::New(Function::kCtorPhaseAll))); |
| 2466 | 2476 |
| 2467 | 2477 |
| 2468 // Now setup rest of the arguments for the constructor call. | 2478 // Now setup rest of the arguments for the constructor call. |
| 2469 node->arguments()->Visit(this); | 2479 node->arguments()->Visit(this); |
| 2470 | 2480 |
| 2471 // Call the constructor. | 2481 // Call the constructor. |
| 2472 // +2 to include implicit receiver and phase arguments. | 2482 // +2 to include implicit receiver and phase arguments. |
| 2473 int num_args = node->arguments()->length() + 2; | 2483 int num_args = node->arguments()->length() + 2; |
| 2474 __ LoadObject(ECX, node->constructor()); | 2484 __ LoadObject(ECX, node->constructor()); |
| 2475 __ LoadObject(EDX, ArgumentsDescriptor(num_args, node->arguments()->names())); | 2485 __ LoadObject(EDX, ArgumentsDescriptor(num_args, node->arguments()->names())); |
| 2476 GenerateCall(node->token_index(), &StubCode::CallStaticFunctionLabel()); | 2486 GenerateCall(node->token_index(), |
| 2487 &StubCode::CallStaticFunctionLabel(), |
| 2488 PcDescriptors::kFuncCall); |
| 2477 // Constructors do not return any value. | 2489 // Constructors do not return any value. |
| 2478 | 2490 |
| 2479 // Pop out all the other arguments on the stack. | 2491 // Pop out all the other arguments on the stack. |
| 2480 __ addl(ESP, Immediate(num_args * kWordSize)); | 2492 __ addl(ESP, Immediate(num_args * kWordSize)); |
| 2481 } | 2493 } |
| 2482 | 2494 |
| 2483 | 2495 |
| 2484 // Expects receiver on stack, returns result in EAX.. | 2496 // Expects receiver on stack, returns result in EAX.. |
| 2485 void CodeGenerator::GenerateInstanceGetterCall(intptr_t node_id, | 2497 void CodeGenerator::GenerateInstanceGetterCall(intptr_t node_id, |
| 2486 intptr_t token_index, | 2498 intptr_t token_index, |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2560 const Function& function = | 2572 const Function& function = |
| 2561 Function::ZoneHandle(field_class.LookupStaticFunction(getter_name)); | 2573 Function::ZoneHandle(field_class.LookupStaticFunction(getter_name)); |
| 2562 if (function.IsNull()) { | 2574 if (function.IsNull()) { |
| 2563 ErrorMsg(token_index, "Static getter does not exist: %s", | 2575 ErrorMsg(token_index, "Static getter does not exist: %s", |
| 2564 getter_name.ToCString()); | 2576 getter_name.ToCString()); |
| 2565 } | 2577 } |
| 2566 __ LoadObject(ECX, function); | 2578 __ LoadObject(ECX, function); |
| 2567 const int kNumberOfArguments = 0; | 2579 const int kNumberOfArguments = 0; |
| 2568 const Array& kNoArgumentNames = Array::Handle(); | 2580 const Array& kNoArgumentNames = Array::Handle(); |
| 2569 __ LoadObject(EDX, ArgumentsDescriptor(kNumberOfArguments, kNoArgumentNames)); | 2581 __ LoadObject(EDX, ArgumentsDescriptor(kNumberOfArguments, kNoArgumentNames)); |
| 2570 GenerateCall(token_index, &StubCode::CallStaticFunctionLabel()); | 2582 GenerateCall(token_index, |
| 2583 &StubCode::CallStaticFunctionLabel(), |
| 2584 PcDescriptors::kFuncCall); |
| 2571 // No arguments were pushed, hence nothing to pop. | 2585 // No arguments were pushed, hence nothing to pop. |
| 2572 } | 2586 } |
| 2573 | 2587 |
| 2574 | 2588 |
| 2575 // Call to static getter. | 2589 // Call to static getter. |
| 2576 void CodeGenerator::VisitStaticGetterNode(StaticGetterNode* node) { | 2590 void CodeGenerator::VisitStaticGetterNode(StaticGetterNode* node) { |
| 2577 GenerateStaticGetterCall(node->token_index(), | 2591 GenerateStaticGetterCall(node->token_index(), |
| 2578 node->cls(), | 2592 node->cls(), |
| 2579 node->field_name()); | 2593 node->field_name()); |
| 2580 // Result is in EAX. | 2594 // Result is in EAX. |
| 2581 if (IsResultNeeded(node)) { | 2595 if (IsResultNeeded(node)) { |
| 2582 __ pushl(EAX); | 2596 __ pushl(EAX); |
| 2583 } | 2597 } |
| 2584 } | 2598 } |
| 2585 | 2599 |
| 2586 | 2600 |
| 2587 // Expects value on stack. | 2601 // Expects value on stack. |
| 2588 void CodeGenerator::GenerateStaticSetterCall(intptr_t token_index, | 2602 void CodeGenerator::GenerateStaticSetterCall(intptr_t token_index, |
| 2589 const Class& field_class, | 2603 const Class& field_class, |
| 2590 const String& field_name) { | 2604 const String& field_name) { |
| 2591 const String& setter_name = String::Handle(Field::SetterName(field_name)); | 2605 const String& setter_name = String::Handle(Field::SetterName(field_name)); |
| 2592 const Function& function = | 2606 const Function& function = |
| 2593 Function::ZoneHandle(field_class.LookupStaticFunction(setter_name)); | 2607 Function::ZoneHandle(field_class.LookupStaticFunction(setter_name)); |
| 2594 __ LoadObject(ECX, function); | 2608 __ LoadObject(ECX, function); |
| 2595 const int kNumberOfArguments = 1; // value. | 2609 const int kNumberOfArguments = 1; // value. |
| 2596 const Array& kNoArgumentNames = Array::Handle(); | 2610 const Array& kNoArgumentNames = Array::Handle(); |
| 2597 __ LoadObject(EDX, ArgumentsDescriptor(kNumberOfArguments, kNoArgumentNames)); | 2611 __ LoadObject(EDX, ArgumentsDescriptor(kNumberOfArguments, kNoArgumentNames)); |
| 2598 GenerateCall(token_index, &StubCode::CallStaticFunctionLabel()); | 2612 GenerateCall(token_index, |
| 2613 &StubCode::CallStaticFunctionLabel(), |
| 2614 PcDescriptors::kFuncCall); |
| 2599 __ addl(ESP, Immediate(kNumberOfArguments * kWordSize)); | 2615 __ addl(ESP, Immediate(kNumberOfArguments * kWordSize)); |
| 2600 } | 2616 } |
| 2601 | 2617 |
| 2602 | 2618 |
| 2603 // The call to static setter implements assignment to a static field. | 2619 // The call to static setter implements assignment to a static field. |
| 2604 // The result of the assignment is the value being stored. | 2620 // The result of the assignment is the value being stored. |
| 2605 void CodeGenerator::VisitStaticSetterNode(StaticSetterNode* node) { | 2621 void CodeGenerator::VisitStaticSetterNode(StaticSetterNode* node) { |
| 2606 node->value()->Visit(this); | 2622 node->value()->Visit(this); |
| 2607 if (IsResultNeeded(node)) { | 2623 if (IsResultNeeded(node)) { |
| 2608 // Preserve the original value when returning from setter. | 2624 // Preserve the original value when returning from setter. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2621 // Push the result place holder initialized to NULL. | 2637 // Push the result place holder initialized to NULL. |
| 2622 __ PushObject(Object::ZoneHandle()); | 2638 __ PushObject(Object::ZoneHandle()); |
| 2623 // Pass a pointer to the first argument in EAX. | 2639 // Pass a pointer to the first argument in EAX. |
| 2624 if (!node->has_optional_parameters()) { | 2640 if (!node->has_optional_parameters()) { |
| 2625 __ leal(EAX, Address(EBP, (1 + node->argument_count()) * kWordSize)); | 2641 __ leal(EAX, Address(EBP, (1 + node->argument_count()) * kWordSize)); |
| 2626 } else { | 2642 } else { |
| 2627 __ leal(EAX, Address(EBP, -1 * kWordSize)); | 2643 __ leal(EAX, Address(EBP, -1 * kWordSize)); |
| 2628 } | 2644 } |
| 2629 __ movl(ECX, Immediate(reinterpret_cast<uword>(node->native_c_function()))); | 2645 __ movl(ECX, Immediate(reinterpret_cast<uword>(node->native_c_function()))); |
| 2630 __ movl(EDX, Immediate(node->argument_count())); | 2646 __ movl(EDX, Immediate(node->argument_count())); |
| 2631 GenerateCall(node->token_index(), &StubCode::CallNativeCFunctionLabel()); | 2647 GenerateCall(node->token_index(), |
| 2648 &StubCode::CallNativeCFunctionLabel(), |
| 2649 PcDescriptors::kOther); |
| 2632 // Result is on the stack. | 2650 // Result is on the stack. |
| 2633 if (!IsResultNeeded(node)) { | 2651 if (!IsResultNeeded(node)) { |
| 2634 __ popl(EAX); | 2652 __ popl(EAX); |
| 2635 } | 2653 } |
| 2636 } | 2654 } |
| 2637 | 2655 |
| 2638 | 2656 |
| 2639 void CodeGenerator::VisitCatchClauseNode(CatchClauseNode* node) { | 2657 void CodeGenerator::VisitCatchClauseNode(CatchClauseNode* node) { |
| 2640 // NOTE: The implicit variables ':saved_context', ':exception_var' | 2658 // NOTE: The implicit variables ':saved_context', ':exception_var' |
| 2641 // and ':stacktrace_var' can never be captured variables. | 2659 // and ':stacktrace_var' can never be captured variables. |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2747 GenerateLoadVariable(CTX, node->context_var()); | 2765 GenerateLoadVariable(CTX, node->context_var()); |
| 2748 node->finally_block()->Visit(this); | 2766 node->finally_block()->Visit(this); |
| 2749 | 2767 |
| 2750 if (try_index >= 0) { | 2768 if (try_index >= 0) { |
| 2751 state()->set_try_index(try_index); | 2769 state()->set_try_index(try_index); |
| 2752 } | 2770 } |
| 2753 } | 2771 } |
| 2754 | 2772 |
| 2755 | 2773 |
| 2756 void CodeGenerator::GenerateCall(intptr_t token_index, | 2774 void CodeGenerator::GenerateCall(intptr_t token_index, |
| 2757 const ExternalLabel* ext_label) { | 2775 const ExternalLabel* ext_label, |
| 2776 PcDescriptors::Kind desc_kind) { |
| 2758 __ call(ext_label); | 2777 __ call(ext_label); |
| 2759 AddCurrentDescriptor(PcDescriptors::kOther, AstNode::kNoId, token_index); | 2778 AddCurrentDescriptor(desc_kind, AstNode::kNoId, token_index); |
| 2760 } | 2779 } |
| 2761 | 2780 |
| 2762 | 2781 |
| 2763 void CodeGenerator::GenerateCallRuntime(intptr_t node_id, | 2782 void CodeGenerator::GenerateCallRuntime(intptr_t node_id, |
| 2764 intptr_t token_index, | 2783 intptr_t token_index, |
| 2765 const RuntimeEntry& entry) { | 2784 const RuntimeEntry& entry) { |
| 2766 __ CallRuntimeFromDart(entry); | 2785 __ CallRuntimeFromDart(entry); |
| 2767 AddCurrentDescriptor(PcDescriptors::kOther, node_id, token_index); | 2786 AddCurrentDescriptor(PcDescriptors::kOther, node_id, token_index); |
| 2768 } | 2787 } |
| 2769 | 2788 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2795 const Error& error = Error::Handle( | 2814 const Error& error = Error::Handle( |
| 2796 Parser::FormatError(script, token_index, "Error", format, args)); | 2815 Parser::FormatError(script, token_index, "Error", format, args)); |
| 2797 va_end(args); | 2816 va_end(args); |
| 2798 Isolate::Current()->long_jump_base()->Jump(1, error); | 2817 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 2799 UNREACHABLE(); | 2818 UNREACHABLE(); |
| 2800 } | 2819 } |
| 2801 | 2820 |
| 2802 } // namespace dart | 2821 } // namespace dart |
| 2803 | 2822 |
| 2804 #endif // defined TARGET_ARCH_IA32 | 2823 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |