| 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 |