| 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_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 707 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 718 kTraceFunctionExitRuntimeEntry); | 718 kTraceFunctionExitRuntimeEntry); |
| 719 __ popl(EAX); // Remove argument. | 719 __ popl(EAX); // Remove argument. |
| 720 __ popl(EAX); // Restore result. | 720 __ popl(EAX); // Restore result. |
| 721 } | 721 } |
| 722 __ LeaveFrame(); | 722 __ LeaveFrame(); |
| 723 __ ret(); | 723 __ ret(); |
| 724 // Add a NOP to make return code pattern 5 bytes long for patching | 724 // Add a NOP to make return code pattern 5 bytes long for patching |
| 725 // in breakpoints during debugging. | 725 // in breakpoints during debugging. |
| 726 __ nop(1); | 726 __ nop(1); |
| 727 AddCurrentDescriptor(PcDescriptors::kReturn, | 727 AddCurrentDescriptor(PcDescriptors::kReturn, |
| 728 AstNode::kNoId, | 728 node->id(), |
| 729 node->token_index()); | 729 node->token_index()); |
| 730 | 730 |
| 731 #ifdef DEBUG | 731 #ifdef DEBUG |
| 732 __ Bind(&wrong_stack); | 732 __ Bind(&wrong_stack); |
| 733 __ Stop("Exit stack size does not match the entry stack size."); | 733 __ Stop("Exit stack size does not match the entry stack size."); |
| 734 #endif // DEBUG. | 734 #endif // DEBUG. |
| 735 } | 735 } |
| 736 | 736 |
| 737 | 737 |
| 738 void CodeGenerator::VisitReturnNode(ReturnNode* node) { | 738 void CodeGenerator::VisitReturnNode(ReturnNode* node) { |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 826 const Class& cls = Class::Handle(function.signature_class()); | 826 const Class& cls = Class::Handle(function.signature_class()); |
| 827 ASSERT(!cls.IsNull()); | 827 ASSERT(!cls.IsNull()); |
| 828 const bool requires_type_arguments = cls.HasTypeArguments(); | 828 const bool requires_type_arguments = cls.HasTypeArguments(); |
| 829 if (requires_type_arguments) { | 829 if (requires_type_arguments) { |
| 830 ASSERT(!function.IsImplicitStaticClosureFunction()); | 830 ASSERT(!function.IsImplicitStaticClosureFunction()); |
| 831 GenerateInstantiatorTypeArguments(node->token_index()); | 831 GenerateInstantiatorTypeArguments(node->token_index()); |
| 832 } | 832 } |
| 833 const Code& stub = Code::Handle( | 833 const Code& stub = Code::Handle( |
| 834 StubCode::GetAllocationStubForClosure(function)); | 834 StubCode::GetAllocationStubForClosure(function)); |
| 835 const ExternalLabel label(function.ToCString(), stub.EntryPoint()); | 835 const ExternalLabel label(function.ToCString(), stub.EntryPoint()); |
| 836 GenerateCall(node->token_index(), &label); | 836 GenerateCall(node->token_index(), &label, PcDescriptors::kOther); |
| 837 if (requires_type_arguments) { | 837 if (requires_type_arguments) { |
| 838 __ popl(ECX); // Pop type arguments. | 838 __ popl(ECX); // Pop type arguments. |
| 839 } | 839 } |
| 840 if (function.IsImplicitInstanceClosureFunction()) { | 840 if (function.IsImplicitInstanceClosureFunction()) { |
| 841 __ popl(ECX); // Pop receiver. | 841 __ popl(ECX); // Pop receiver. |
| 842 } | 842 } |
| 843 if (IsResultNeeded(node)) { | 843 if (IsResultNeeded(node)) { |
| 844 __ pushl(EAX); | 844 __ pushl(EAX); |
| 845 } | 845 } |
| 846 } | 846 } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 867 CodeGeneratorState codegen_state(this); | 867 CodeGeneratorState codegen_state(this); |
| 868 LocalScope* scope = node_sequence->scope(); | 868 LocalScope* scope = node_sequence->scope(); |
| 869 const intptr_t num_context_variables = | 869 const intptr_t num_context_variables = |
| 870 (scope != NULL) ? scope->num_context_variables() : 0; | 870 (scope != NULL) ? scope->num_context_variables() : 0; |
| 871 if (num_context_variables > 0) { | 871 if (num_context_variables > 0) { |
| 872 // The loop local scope declares variables that are captured. | 872 // The loop local scope declares variables that are captured. |
| 873 // Allocate and chain a new context. | 873 // Allocate and chain a new context. |
| 874 __ movl(EDX, Immediate(num_context_variables)); | 874 __ movl(EDX, Immediate(num_context_variables)); |
| 875 const ExternalLabel label("alloc_context", | 875 const ExternalLabel label("alloc_context", |
| 876 StubCode::AllocateContextEntryPoint()); | 876 StubCode::AllocateContextEntryPoint()); |
| 877 GenerateCall(node_sequence->token_index(), &label); | 877 GenerateCall(node_sequence->token_index(), &label, PcDescriptors::kOther); |
| 878 | 878 |
| 879 // Chain the new context in EAX to its parent in CTX. | 879 // Chain the new context in EAX to its parent in CTX. |
| 880 __ StoreIntoObject(EAX, FieldAddress(EAX, Context::parent_offset()), CTX); | 880 __ StoreIntoObject(EAX, FieldAddress(EAX, Context::parent_offset()), CTX); |
| 881 // Set new context as current context. | 881 // Set new context as current context. |
| 882 __ movl(CTX, EAX); | 882 __ movl(CTX, EAX); |
| 883 state()->set_context_level(scope->context_level()); | 883 state()->set_context_level(scope->context_level()); |
| 884 | 884 |
| 885 // If this node_sequence is the body of the function being compiled, copy | 885 // If this node_sequence is the body of the function being compiled, copy |
| 886 // the captured parameters from the frame into the context. | 886 // the captured parameters from the frame into the context. |
| 887 if (node_sequence == parsed_function_.node_sequence()) { | 887 if (node_sequence == parsed_function_.node_sequence()) { |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 946 element->Visit(this); | 946 element->Visit(this); |
| 947 } | 947 } |
| 948 | 948 |
| 949 // Allocate the array. | 949 // Allocate the array. |
| 950 // EDX : Array length as Smi. | 950 // EDX : Array length as Smi. |
| 951 // ECX : element type for the array. | 951 // ECX : element type for the array. |
| 952 __ movl(EDX, Immediate(Smi::RawValue(node->length()))); | 952 __ movl(EDX, Immediate(Smi::RawValue(node->length()))); |
| 953 const AbstractTypeArguments& element_type = node->type_arguments(); | 953 const AbstractTypeArguments& element_type = node->type_arguments(); |
| 954 ASSERT(element_type.IsNull() || element_type.IsInstantiated()); | 954 ASSERT(element_type.IsNull() || element_type.IsInstantiated()); |
| 955 __ LoadObject(ECX, element_type); | 955 __ LoadObject(ECX, element_type); |
| 956 GenerateCall(node->token_index(), &StubCode::AllocateArrayLabel()); | 956 GenerateCall(node->token_index(), |
| 957 &StubCode::AllocateArrayLabel(), |
| 958 PcDescriptors::kOther); |
| 957 | 959 |
| 958 // Pop the element values from the stack into the array. | 960 // Pop the element values from the stack into the array. |
| 959 __ leal(ECX, FieldAddress(EAX, Array::data_offset())); | 961 __ leal(ECX, FieldAddress(EAX, Array::data_offset())); |
| 960 for (int i = node->length() - 1; i >= 0; i--) { | 962 for (int i = node->length() - 1; i >= 0; i--) { |
| 961 __ popl(Address(ECX, i * kWordSize)); | 963 __ popl(Address(ECX, i * kWordSize)); |
| 962 } | 964 } |
| 963 | 965 |
| 964 if (IsResultNeeded(node)) { | 966 if (IsResultNeeded(node)) { |
| 965 __ pushl(EAX); | 967 __ pushl(EAX); |
| 966 } | 968 } |
| (...skipping 1174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2141 } | 2143 } |
| 2142 | 2144 |
| 2143 // Could not concatenate at compile time, generate a call to | 2145 // Could not concatenate at compile time, generate a call to |
| 2144 // interpolation function. | 2146 // interpolation function. |
| 2145 ArgumentListNode* interpol_arg = new ArgumentListNode(node->token_index()); | 2147 ArgumentListNode* interpol_arg = new ArgumentListNode(node->token_index()); |
| 2146 interpol_arg->Add(node->values()); | 2148 interpol_arg->Add(node->values()); |
| 2147 node->values()->Visit(this); | 2149 node->values()->Visit(this); |
| 2148 __ LoadObject(ECX, interpol_func); | 2150 __ LoadObject(ECX, interpol_func); |
| 2149 __ LoadObject(EDX, ArgumentsDescriptor(interpol_arg->length(), | 2151 __ LoadObject(EDX, ArgumentsDescriptor(interpol_arg->length(), |
| 2150 interpol_arg->names())); | 2152 interpol_arg->names())); |
| 2151 GenerateCall(node->token_index(), &StubCode::CallStaticFunctionLabel()); | 2153 GenerateCall(node->token_index(), |
| 2154 &StubCode::CallStaticFunctionLabel(), |
| 2155 PcDescriptors::kFuncCall); |
| 2152 __ addl(ESP, Immediate(interpol_arg->length() * kWordSize)); | 2156 __ addl(ESP, Immediate(interpol_arg->length() * kWordSize)); |
| 2153 // Result is in EAX. | 2157 // Result is in EAX. |
| 2154 if (IsResultNeeded(node)) { | 2158 if (IsResultNeeded(node)) { |
| 2155 __ pushl(EAX); | 2159 __ pushl(EAX); |
| 2156 } | 2160 } |
| 2157 } | 2161 } |
| 2158 | 2162 |
| 2159 | 2163 |
| 2160 void CodeGenerator::VisitInstanceCallNode(InstanceCallNode* node) { | 2164 void CodeGenerator::VisitInstanceCallNode(InstanceCallNode* node) { |
| 2161 const int number_of_arguments = node->arguments()->length() + 1; | 2165 const int number_of_arguments = node->arguments()->length() + 1; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2178 __ pushl(EAX); | 2182 __ pushl(EAX); |
| 2179 } | 2183 } |
| 2180 } | 2184 } |
| 2181 | 2185 |
| 2182 | 2186 |
| 2183 void CodeGenerator::VisitStaticCallNode(StaticCallNode* node) { | 2187 void CodeGenerator::VisitStaticCallNode(StaticCallNode* node) { |
| 2184 node->arguments()->Visit(this); | 2188 node->arguments()->Visit(this); |
| 2185 __ LoadObject(ECX, node->function()); | 2189 __ LoadObject(ECX, node->function()); |
| 2186 __ LoadObject(EDX, ArgumentsDescriptor(node->arguments()->length(), | 2190 __ LoadObject(EDX, ArgumentsDescriptor(node->arguments()->length(), |
| 2187 node->arguments()->names())); | 2191 node->arguments()->names())); |
| 2188 GenerateCall(node->token_index(), &StubCode::CallStaticFunctionLabel()); | 2192 GenerateCall(node->token_index(), |
| 2193 &StubCode::CallStaticFunctionLabel(), |
| 2194 PcDescriptors::kFuncCall); |
| 2189 __ addl(ESP, Immediate(node->arguments()->length() * kWordSize)); | 2195 __ addl(ESP, Immediate(node->arguments()->length() * kWordSize)); |
| 2190 // Result is in EAX. | 2196 // Result is in EAX. |
| 2191 if (IsResultNeeded(node)) { | 2197 if (IsResultNeeded(node)) { |
| 2192 __ pushl(EAX); | 2198 __ pushl(EAX); |
| 2193 } | 2199 } |
| 2194 } | 2200 } |
| 2195 | 2201 |
| 2196 | 2202 |
| 2197 void CodeGenerator::VisitClosureCallNode(ClosureCallNode* node) { | 2203 void CodeGenerator::VisitClosureCallNode(ClosureCallNode* node) { |
| 2198 // The spec states that the closure is evaluated before the arguments. | 2204 // The spec states that the closure is evaluated before the arguments. |
| 2199 // Preserve the current context, since it will be overridden by the closure | 2205 // Preserve the current context, since it will be overridden by the closure |
| 2200 // context during the call. | 2206 // context during the call. |
| 2201 __ pushl(CTX); | 2207 __ pushl(CTX); |
| 2202 // Compute the closure object and pass it as first argument to the stub. | 2208 // Compute the closure object and pass it as first argument to the stub. |
| 2203 node->closure()->Visit(this); | 2209 node->closure()->Visit(this); |
| 2204 // Now compute the arguments to the call. | 2210 // Now compute the arguments to the call. |
| 2205 node->arguments()->Visit(this); | 2211 node->arguments()->Visit(this); |
| 2206 // Set up the number of arguments (excluding the closure) to the ClosureCall | 2212 // Set up the number of arguments (excluding the closure) to the ClosureCall |
| 2207 // stub which will setup the closure context and jump to the entrypoint of the | 2213 // stub which will setup the closure context and jump to the entrypoint of the |
| 2208 // closure function (the function will be compiled if it has not already been | 2214 // closure function (the function will be compiled if it has not already been |
| 2209 // compiled). | 2215 // compiled). |
| 2210 // NOTE: The stub accesses the closure before the parameter list. | 2216 // NOTE: The stub accesses the closure before the parameter list. |
| 2211 __ LoadObject(EDX, ArgumentsDescriptor(node->arguments()->length(), | 2217 __ LoadObject(EDX, ArgumentsDescriptor(node->arguments()->length(), |
| 2212 node->arguments()->names())); | 2218 node->arguments()->names())); |
| 2213 GenerateCall(node->token_index(), &StubCode::CallClosureFunctionLabel()); | 2219 GenerateCall(node->token_index(), |
| 2220 &StubCode::CallClosureFunctionLabel(), |
| 2221 PcDescriptors::kOther); |
| 2214 __ addl(ESP, Immediate((node->arguments()->length() + 1) * kWordSize)); | 2222 __ addl(ESP, Immediate((node->arguments()->length() + 1) * kWordSize)); |
| 2215 // Restore the context. | 2223 // Restore the context. |
| 2216 __ popl(CTX); | 2224 __ popl(CTX); |
| 2217 // Result is in EAX. | 2225 // Result is in EAX. |
| 2218 if (IsResultNeeded(node)) { | 2226 if (IsResultNeeded(node)) { |
| 2219 __ pushl(EAX); | 2227 __ pushl(EAX); |
| 2220 } | 2228 } |
| 2221 } | 2229 } |
| 2222 | 2230 |
| 2223 | 2231 |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2348 const bool requires_type_arguments = true; // Always first arg to factory. | 2356 const bool requires_type_arguments = true; // Always first arg to factory. |
| 2349 GenerateTypeArguments(node, requires_type_arguments); | 2357 GenerateTypeArguments(node, requires_type_arguments); |
| 2350 // The top of stack is an instantiated AbstractTypeArguments object | 2358 // The top of stack is an instantiated AbstractTypeArguments object |
| 2351 // (or null). | 2359 // (or null). |
| 2352 int num_args = node->arguments()->length() + 1; // +1 to include type args. | 2360 int num_args = node->arguments()->length() + 1; // +1 to include type args. |
| 2353 node->arguments()->Visit(this); | 2361 node->arguments()->Visit(this); |
| 2354 // Call the factory. | 2362 // Call the factory. |
| 2355 __ LoadObject(ECX, node->constructor()); | 2363 __ LoadObject(ECX, node->constructor()); |
| 2356 __ LoadObject(EDX, ArgumentsDescriptor(num_args, | 2364 __ LoadObject(EDX, ArgumentsDescriptor(num_args, |
| 2357 node->arguments()->names())); | 2365 node->arguments()->names())); |
| 2358 GenerateCall(node->token_index(), &StubCode::CallStaticFunctionLabel()); | 2366 GenerateCall(node->token_index(), |
| 2367 &StubCode::CallStaticFunctionLabel(), |
| 2368 PcDescriptors::kFuncCall); |
| 2359 // Factory constructor returns object in EAX. | 2369 // Factory constructor returns object in EAX. |
| 2360 __ addl(ESP, Immediate(num_args * kWordSize)); | 2370 __ addl(ESP, Immediate(num_args * kWordSize)); |
| 2361 if (IsResultNeeded(node)) { | 2371 if (IsResultNeeded(node)) { |
| 2362 __ pushl(EAX); | 2372 __ pushl(EAX); |
| 2363 } | 2373 } |
| 2364 return; | 2374 return; |
| 2365 } | 2375 } |
| 2366 | 2376 |
| 2367 const Class& cls = Class::ZoneHandle(node->constructor().owner()); | 2377 const Class& cls = Class::ZoneHandle(node->constructor().owner()); |
| 2368 const bool requires_type_arguments = cls.HasTypeArguments(); | 2378 const bool requires_type_arguments = cls.HasTypeArguments(); |
| 2369 GenerateTypeArguments(node, requires_type_arguments); | 2379 GenerateTypeArguments(node, requires_type_arguments); |
| 2370 | 2380 |
| 2371 // If cls is parameterized, the type arguments and the instantiator's | 2381 // If cls is parameterized, the type arguments and the instantiator's |
| 2372 // type arguments are on the stack. | 2382 // type arguments are on the stack. |
| 2373 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls)); | 2383 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls)); |
| 2374 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); | 2384 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); |
| 2375 GenerateCall(node->token_index(), &label); | 2385 GenerateCall(node->token_index(), &label, PcDescriptors::kOther); |
| 2376 if (requires_type_arguments) { | 2386 if (requires_type_arguments) { |
| 2377 __ popl(ECX); // Pop type arguments. | 2387 __ popl(ECX); // Pop type arguments. |
| 2378 __ popl(ECX); // Pop instantiator type arguments. | 2388 __ popl(ECX); // Pop instantiator type arguments. |
| 2379 } | 2389 } |
| 2380 | 2390 |
| 2381 if (IsResultNeeded(node)) { | 2391 if (IsResultNeeded(node)) { |
| 2382 __ pushl(EAX); // Set up return value from allocate. | 2392 __ pushl(EAX); // Set up return value from allocate. |
| 2383 } | 2393 } |
| 2384 | 2394 |
| 2385 // First argument(this) for constructor call which follows. | 2395 // First argument(this) for constructor call which follows. |
| 2386 __ pushl(EAX); | 2396 __ pushl(EAX); |
| 2387 // Second argument is the implicit construction phase parameter. | 2397 // Second argument is the implicit construction phase parameter. |
| 2388 // Run both the constructor initializer list and the constructor body. | 2398 // Run both the constructor initializer list and the constructor body. |
| 2389 __ PushObject(Smi::ZoneHandle(Smi::New(Function::kCtorPhaseAll))); | 2399 __ PushObject(Smi::ZoneHandle(Smi::New(Function::kCtorPhaseAll))); |
| 2390 | 2400 |
| 2391 | 2401 |
| 2392 // Now setup rest of the arguments for the constructor call. | 2402 // Now setup rest of the arguments for the constructor call. |
| 2393 node->arguments()->Visit(this); | 2403 node->arguments()->Visit(this); |
| 2394 | 2404 |
| 2395 // Call the constructor. | 2405 // Call the constructor. |
| 2396 // +2 to include implicit receiver and phase arguments. | 2406 // +2 to include implicit receiver and phase arguments. |
| 2397 int num_args = node->arguments()->length() + 2; | 2407 int num_args = node->arguments()->length() + 2; |
| 2398 __ LoadObject(ECX, node->constructor()); | 2408 __ LoadObject(ECX, node->constructor()); |
| 2399 __ LoadObject(EDX, ArgumentsDescriptor(num_args, node->arguments()->names())); | 2409 __ LoadObject(EDX, ArgumentsDescriptor(num_args, node->arguments()->names())); |
| 2400 GenerateCall(node->token_index(), &StubCode::CallStaticFunctionLabel()); | 2410 GenerateCall(node->token_index(), |
| 2411 &StubCode::CallStaticFunctionLabel(), |
| 2412 PcDescriptors::kFuncCall); |
| 2401 // Constructors do not return any value. | 2413 // Constructors do not return any value. |
| 2402 | 2414 |
| 2403 // Pop out all the other arguments on the stack. | 2415 // Pop out all the other arguments on the stack. |
| 2404 __ addl(ESP, Immediate(num_args * kWordSize)); | 2416 __ addl(ESP, Immediate(num_args * kWordSize)); |
| 2405 } | 2417 } |
| 2406 | 2418 |
| 2407 | 2419 |
| 2408 // Expects receiver on stack, returns result in EAX.. | 2420 // Expects receiver on stack, returns result in EAX.. |
| 2409 void CodeGenerator::GenerateInstanceGetterCall(intptr_t node_id, | 2421 void CodeGenerator::GenerateInstanceGetterCall(intptr_t node_id, |
| 2410 intptr_t token_index, | 2422 intptr_t token_index, |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2484 const Function& function = | 2496 const Function& function = |
| 2485 Function::ZoneHandle(field_class.LookupStaticFunction(getter_name)); | 2497 Function::ZoneHandle(field_class.LookupStaticFunction(getter_name)); |
| 2486 if (function.IsNull()) { | 2498 if (function.IsNull()) { |
| 2487 ErrorMsg(token_index, "Static getter does not exist: %s", | 2499 ErrorMsg(token_index, "Static getter does not exist: %s", |
| 2488 getter_name.ToCString()); | 2500 getter_name.ToCString()); |
| 2489 } | 2501 } |
| 2490 __ LoadObject(ECX, function); | 2502 __ LoadObject(ECX, function); |
| 2491 const int kNumberOfArguments = 0; | 2503 const int kNumberOfArguments = 0; |
| 2492 const Array& kNoArgumentNames = Array::Handle(); | 2504 const Array& kNoArgumentNames = Array::Handle(); |
| 2493 __ LoadObject(EDX, ArgumentsDescriptor(kNumberOfArguments, kNoArgumentNames)); | 2505 __ LoadObject(EDX, ArgumentsDescriptor(kNumberOfArguments, kNoArgumentNames)); |
| 2494 GenerateCall(token_index, &StubCode::CallStaticFunctionLabel()); | 2506 GenerateCall(token_index, |
| 2507 &StubCode::CallStaticFunctionLabel(), |
| 2508 PcDescriptors::kFuncCall); |
| 2495 // No arguments were pushed, hence nothing to pop. | 2509 // No arguments were pushed, hence nothing to pop. |
| 2496 } | 2510 } |
| 2497 | 2511 |
| 2498 | 2512 |
| 2499 // Call to static getter. | 2513 // Call to static getter. |
| 2500 void CodeGenerator::VisitStaticGetterNode(StaticGetterNode* node) { | 2514 void CodeGenerator::VisitStaticGetterNode(StaticGetterNode* node) { |
| 2501 GenerateStaticGetterCall(node->token_index(), | 2515 GenerateStaticGetterCall(node->token_index(), |
| 2502 node->cls(), | 2516 node->cls(), |
| 2503 node->field_name()); | 2517 node->field_name()); |
| 2504 // Result is in EAX. | 2518 // Result is in EAX. |
| 2505 if (IsResultNeeded(node)) { | 2519 if (IsResultNeeded(node)) { |
| 2506 __ pushl(EAX); | 2520 __ pushl(EAX); |
| 2507 } | 2521 } |
| 2508 } | 2522 } |
| 2509 | 2523 |
| 2510 | 2524 |
| 2511 // Expects value on stack. | 2525 // Expects value on stack. |
| 2512 void CodeGenerator::GenerateStaticSetterCall(intptr_t token_index, | 2526 void CodeGenerator::GenerateStaticSetterCall(intptr_t token_index, |
| 2513 const Class& field_class, | 2527 const Class& field_class, |
| 2514 const String& field_name) { | 2528 const String& field_name) { |
| 2515 const String& setter_name = String::Handle(Field::SetterName(field_name)); | 2529 const String& setter_name = String::Handle(Field::SetterName(field_name)); |
| 2516 const Function& function = | 2530 const Function& function = |
| 2517 Function::ZoneHandle(field_class.LookupStaticFunction(setter_name)); | 2531 Function::ZoneHandle(field_class.LookupStaticFunction(setter_name)); |
| 2518 __ LoadObject(ECX, function); | 2532 __ LoadObject(ECX, function); |
| 2519 const int kNumberOfArguments = 1; // value. | 2533 const int kNumberOfArguments = 1; // value. |
| 2520 const Array& kNoArgumentNames = Array::Handle(); | 2534 const Array& kNoArgumentNames = Array::Handle(); |
| 2521 __ LoadObject(EDX, ArgumentsDescriptor(kNumberOfArguments, kNoArgumentNames)); | 2535 __ LoadObject(EDX, ArgumentsDescriptor(kNumberOfArguments, kNoArgumentNames)); |
| 2522 GenerateCall(token_index, &StubCode::CallStaticFunctionLabel()); | 2536 GenerateCall(token_index, |
| 2537 &StubCode::CallStaticFunctionLabel(), |
| 2538 PcDescriptors::kFuncCall); |
| 2523 __ addl(ESP, Immediate(kNumberOfArguments * kWordSize)); | 2539 __ addl(ESP, Immediate(kNumberOfArguments * kWordSize)); |
| 2524 } | 2540 } |
| 2525 | 2541 |
| 2526 | 2542 |
| 2527 // The call to static setter implements assignment to a static field. | 2543 // The call to static setter implements assignment to a static field. |
| 2528 // The result of the assignment is the value being stored. | 2544 // The result of the assignment is the value being stored. |
| 2529 void CodeGenerator::VisitStaticSetterNode(StaticSetterNode* node) { | 2545 void CodeGenerator::VisitStaticSetterNode(StaticSetterNode* node) { |
| 2530 node->value()->Visit(this); | 2546 node->value()->Visit(this); |
| 2531 if (IsResultNeeded(node)) { | 2547 if (IsResultNeeded(node)) { |
| 2532 // Preserve the original value when returning from setter. | 2548 // Preserve the original value when returning from setter. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2545 // Push the result place holder initialized to NULL. | 2561 // Push the result place holder initialized to NULL. |
| 2546 __ PushObject(Object::ZoneHandle()); | 2562 __ PushObject(Object::ZoneHandle()); |
| 2547 // Pass a pointer to the first argument in EAX. | 2563 // Pass a pointer to the first argument in EAX. |
| 2548 if (!node->has_optional_parameters()) { | 2564 if (!node->has_optional_parameters()) { |
| 2549 __ leal(EAX, Address(EBP, (1 + node->argument_count()) * kWordSize)); | 2565 __ leal(EAX, Address(EBP, (1 + node->argument_count()) * kWordSize)); |
| 2550 } else { | 2566 } else { |
| 2551 __ leal(EAX, Address(EBP, -1 * kWordSize)); | 2567 __ leal(EAX, Address(EBP, -1 * kWordSize)); |
| 2552 } | 2568 } |
| 2553 __ movl(ECX, Immediate(reinterpret_cast<uword>(node->native_c_function()))); | 2569 __ movl(ECX, Immediate(reinterpret_cast<uword>(node->native_c_function()))); |
| 2554 __ movl(EDX, Immediate(node->argument_count())); | 2570 __ movl(EDX, Immediate(node->argument_count())); |
| 2555 GenerateCall(node->token_index(), &StubCode::CallNativeCFunctionLabel()); | 2571 GenerateCall(node->token_index(), |
| 2572 &StubCode::CallNativeCFunctionLabel(), |
| 2573 PcDescriptors::kOther); |
| 2556 // Result is on the stack. | 2574 // Result is on the stack. |
| 2557 if (!IsResultNeeded(node)) { | 2575 if (!IsResultNeeded(node)) { |
| 2558 __ popl(EAX); | 2576 __ popl(EAX); |
| 2559 } | 2577 } |
| 2560 } | 2578 } |
| 2561 | 2579 |
| 2562 | 2580 |
| 2563 void CodeGenerator::VisitCatchClauseNode(CatchClauseNode* node) { | 2581 void CodeGenerator::VisitCatchClauseNode(CatchClauseNode* node) { |
| 2564 // NOTE: The implicit variables ':saved_context', ':exception_var' | 2582 // NOTE: The implicit variables ':saved_context', ':exception_var' |
| 2565 // and ':stacktrace_var' can never be captured variables. | 2583 // and ':stacktrace_var' can never be captured variables. |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2671 GenerateLoadVariable(CTX, node->context_var()); | 2689 GenerateLoadVariable(CTX, node->context_var()); |
| 2672 node->finally_block()->Visit(this); | 2690 node->finally_block()->Visit(this); |
| 2673 | 2691 |
| 2674 if (try_index >= 0) { | 2692 if (try_index >= 0) { |
| 2675 state()->set_try_index(try_index); | 2693 state()->set_try_index(try_index); |
| 2676 } | 2694 } |
| 2677 } | 2695 } |
| 2678 | 2696 |
| 2679 | 2697 |
| 2680 void CodeGenerator::GenerateCall(intptr_t token_index, | 2698 void CodeGenerator::GenerateCall(intptr_t token_index, |
| 2681 const ExternalLabel* ext_label) { | 2699 const ExternalLabel* ext_label, |
| 2700 PcDescriptors::Kind desc_kind) { |
| 2682 __ call(ext_label); | 2701 __ call(ext_label); |
| 2683 AddCurrentDescriptor(PcDescriptors::kOther, AstNode::kNoId, token_index); | 2702 AddCurrentDescriptor(desc_kind, AstNode::kNoId, token_index); |
| 2684 } | 2703 } |
| 2685 | 2704 |
| 2686 | 2705 |
| 2687 void CodeGenerator::GenerateCallRuntime(intptr_t node_id, | 2706 void CodeGenerator::GenerateCallRuntime(intptr_t node_id, |
| 2688 intptr_t token_index, | 2707 intptr_t token_index, |
| 2689 const RuntimeEntry& entry) { | 2708 const RuntimeEntry& entry) { |
| 2690 __ CallRuntimeFromDart(entry); | 2709 __ CallRuntimeFromDart(entry); |
| 2691 AddCurrentDescriptor(PcDescriptors::kOther, node_id, token_index); | 2710 AddCurrentDescriptor(PcDescriptors::kOther, node_id, token_index); |
| 2692 } | 2711 } |
| 2693 | 2712 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2719 const Error& error = Error::Handle( | 2738 const Error& error = Error::Handle( |
| 2720 Parser::FormatError(script, token_index, "Error", format, args)); | 2739 Parser::FormatError(script, token_index, "Error", format, args)); |
| 2721 va_end(args); | 2740 va_end(args); |
| 2722 Isolate::Current()->long_jump_base()->Jump(1, error); | 2741 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 2723 UNREACHABLE(); | 2742 UNREACHABLE(); |
| 2724 } | 2743 } |
| 2725 | 2744 |
| 2726 } // namespace dart | 2745 } // namespace dart |
| 2727 | 2746 |
| 2728 #endif // defined TARGET_ARCH_IA32 | 2747 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |