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 |