Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_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/flow_graph_compiler.h" | 8 #include "vm/flow_graph_compiler.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 75 intptr_t token_index, | 75 intptr_t token_index, |
| 76 intptr_t try_index, | 76 intptr_t try_index, |
| 77 const RuntimeEntry& entry) { | 77 const RuntimeEntry& entry) { |
| 78 __ CallRuntime(entry); | 78 __ CallRuntime(entry); |
| 79 AddCurrentDescriptor(PcDescriptors::kOther, cid, token_index, try_index); | 79 AddCurrentDescriptor(PcDescriptors::kOther, cid, token_index, try_index); |
| 80 } | 80 } |
| 81 | 81 |
| 82 | 82 |
| 83 void FlowGraphCompiler::CopyParameters() { | 83 void FlowGraphCompiler::CopyParameters() { |
| 84 const Function& function = parsed_function().function(); | 84 const Function& function = parsed_function().function(); |
| 85 const bool is_implicit_native_closure = | |
| 86 function.is_native() && function.IsImplicitClosureFunction(); | |
|
regis
2012/06/15 17:13:34
ditto
siva
2012/06/16 00:25:43
Done.
| |
| 85 LocalScope* scope = parsed_function().node_sequence()->scope(); | 87 LocalScope* scope = parsed_function().node_sequence()->scope(); |
| 86 const int num_fixed_params = function.num_fixed_parameters(); | 88 const int num_fixed_params = function.num_fixed_parameters(); |
| 87 const int num_opt_params = function.num_optional_parameters(); | 89 const int num_opt_params = function.num_optional_parameters(); |
| 88 ASSERT(parsed_function().first_parameter_index() == | 90 ASSERT(parsed_function().first_parameter_index() == |
| 89 ParsedFunction::kFirstLocalSlotIndex); | 91 ParsedFunction::kFirstLocalSlotIndex); |
| 90 // Copy positional arguments. | 92 // Copy positional arguments. |
| 91 // Check that no fewer than num_fixed_params positional arguments are passed | 93 // Check that no fewer than num_fixed_params positional arguments are passed |
| 92 // in and that no more than num_params arguments are passed in. | 94 // in and that no more than num_params arguments are passed in. |
| 93 // Passed argument i at fp[1 + argc - i] | 95 // Passed argument i at fp[1 + argc - i] |
| 94 // copied to fp[ParsedFunction::kFirstLocalSlotIndex - i]. | 96 // copied to fp[ParsedFunction::kFirstLocalSlotIndex - i]. |
| 95 const int num_params = num_fixed_params + num_opt_params; | 97 const int num_params = num_fixed_params + num_opt_params; |
| 96 | 98 |
| 97 // Total number of args is the first Smi in args descriptor array (EDX). | 99 // Total number of args is the first Smi in args descriptor array (EDX). |
| 98 __ movl(EBX, FieldAddress(EDX, Array::data_offset())); | 100 __ movl(EBX, FieldAddress(EDX, Array::data_offset())); |
| 99 // Check that num_args <= num_params. | 101 // Check that num_args <= num_params. |
| 100 Label wrong_num_arguments; | 102 Label wrong_num_arguments; |
| 101 __ cmpl(EBX, Immediate(Smi::RawValue(num_params))); | 103 __ cmpl(EBX, Immediate(Smi::RawValue(num_params))); |
| 102 __ j(GREATER, &wrong_num_arguments); | 104 __ j(GREATER, &wrong_num_arguments); |
| 103 // Number of positional args is the second Smi in descriptor array (EDX). | 105 // Number of positional args is the second Smi in descriptor array (EDX). |
| 104 __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize))); | 106 __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize))); |
| 105 // Check that num_pos_args >= num_fixed_params. | 107 // Check that num_pos_args >= num_fixed_params. |
| 106 __ cmpl(ECX, Immediate(Smi::RawValue(num_fixed_params))); | 108 __ cmpl(ECX, Immediate(Smi::RawValue(num_fixed_params))); |
| 107 __ j(LESS, &wrong_num_arguments); | 109 __ j(LESS, &wrong_num_arguments); |
| 108 // Since EBX and ECX are Smi, use TIMES_2 instead of TIMES_4. | 110 // Since EBX and ECX are Smi, use TIMES_2 instead of TIMES_4. |
| 109 // Let EBX point to the last passed positional argument, i.e. to | 111 // Let EBX point to the last passed positional argument, i.e. to |
| 110 // fp[1 + num_args - (num_pos_args - 1)]. | 112 // fp[1 + num_args - (num_pos_args - 1)]. |
| 111 __ subl(EBX, ECX); | 113 __ subl(EBX, ECX); |
| 112 __ leal(EBX, Address(EBP, EBX, TIMES_2, 2 * kWordSize)); | 114 __ leal(EBX, Address(EBP, EBX, TIMES_2, 2 * kWordSize)); |
| 115 | |
| 113 // Let EDI point to the last copied positional argument, i.e. to | 116 // Let EDI point to the last copied positional argument, i.e. to |
| 114 // fp[ParsedFunction::kFirstLocalSlotIndex - (num_pos_args - 1)]. | 117 // fp[ParsedFunction::kFirstLocalSlotIndex - (num_pos_args - 1)]. |
| 115 const int index = ParsedFunction::kFirstLocalSlotIndex + 1; | 118 int implicit_this_param_pos = is_implicit_native_closure ? -1 : 0; |
| 119 const int index = | |
| 120 ParsedFunction::kFirstLocalSlotIndex + 1 + implicit_this_param_pos; | |
| 121 // First copy captured receiver if function is an implicit native closure. | |
| 122 if (is_implicit_native_closure) { | |
| 123 __ movl(EAX, FieldAddress(CTX, Context::variable_offset(0))); | |
| 124 __ movl(Address(EBP, (index * kWordSize)), EAX); | |
| 125 } | |
| 116 __ leal(EDI, Address(EBP, (index * kWordSize))); | 126 __ leal(EDI, Address(EBP, (index * kWordSize))); |
| 117 __ subl(EDI, ECX); // ECX is a Smi, subtract twice for TIMES_4 scaling. | 127 __ subl(EDI, ECX); // ECX is a Smi, subtract twice for TIMES_4 scaling. |
| 118 __ subl(EDI, ECX); | 128 __ subl(EDI, ECX); |
| 119 __ SmiUntag(ECX); | 129 __ SmiUntag(ECX); |
| 120 Label loop, loop_condition; | 130 Label loop, loop_condition; |
| 121 __ jmp(&loop_condition, Assembler::kNearJump); | 131 __ jmp(&loop_condition, Assembler::kNearJump); |
| 122 // We do not use the final allocation index of the variable here, i.e. | 132 // We do not use the final allocation index of the variable here, i.e. |
| 123 // scope->VariableAt(i)->index(), because captured variables still need | 133 // scope->VariableAt(i)->index(), because captured variables still need |
| 124 // to be copied to the context that is not yet allocated. | 134 // to be copied to the context that is not yet allocated. |
| 125 const Address argument_addr(EBX, ECX, TIMES_4, 0); | 135 const Address argument_addr(EBX, ECX, TIMES_4, 0); |
| 126 const Address copy_addr(EDI, ECX, TIMES_4, 0); | 136 const Address copy_addr(EDI, ECX, TIMES_4, 0); |
| 127 __ Bind(&loop); | 137 __ Bind(&loop); |
| 128 __ movl(EAX, argument_addr); | 138 __ movl(EAX, argument_addr); |
| 129 __ movl(copy_addr, EAX); | 139 __ movl(copy_addr, EAX); |
| 130 __ Bind(&loop_condition); | 140 __ Bind(&loop_condition); |
| 131 __ decl(ECX); | 141 __ decl(ECX); |
| 132 __ j(POSITIVE, &loop, Assembler::kNearJump); | 142 __ j(POSITIVE, &loop, Assembler::kNearJump); |
| 133 | 143 |
| 134 // Copy or initialize optional named arguments. | 144 // Copy or initialize optional named arguments. |
| 135 ASSERT(num_opt_params > 0); // Or we would not have to copy arguments. | 145 Label all_arguments_processed; |
| 136 // Start by alphabetically sorting the names of the optional parameters. | |
| 137 LocalVariable** opt_param = new LocalVariable*[num_opt_params]; | |
| 138 int* opt_param_position = new int[num_opt_params]; | |
| 139 for (int pos = num_fixed_params; pos < num_params; pos++) { | |
| 140 LocalVariable* parameter = scope->VariableAt(pos); | |
| 141 const String& opt_param_name = parameter->name(); | |
| 142 int i = pos - num_fixed_params; | |
| 143 while (--i >= 0) { | |
| 144 LocalVariable* param_i = opt_param[i]; | |
| 145 const intptr_t result = opt_param_name.CompareTo(param_i->name()); | |
| 146 ASSERT(result != 0); | |
| 147 if (result > 0) break; | |
| 148 opt_param[i + 1] = opt_param[i]; | |
| 149 opt_param_position[i + 1] = opt_param_position[i]; | |
| 150 } | |
| 151 opt_param[i + 1] = parameter; | |
| 152 opt_param_position[i + 1] = pos; | |
| 153 } | |
| 154 // Generate code handling each optional parameter in alphabetical order. | |
| 155 // Total number of args is the first Smi in args descriptor array (EDX). | |
| 156 __ movl(EBX, FieldAddress(EDX, Array::data_offset())); | |
| 157 // Number of positional args is the second Smi in descriptor array (EDX). | |
| 158 __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize))); | |
| 159 __ SmiUntag(ECX); | |
| 160 // Let EBX point to the first passed argument, i.e. to fp[1 + argc - 0]. | |
| 161 __ leal(EBX, Address(EBP, EBX, TIMES_2, kWordSize)); // EBX is Smi. | |
| 162 // Let EDI point to the name/pos pair of the first named argument. | |
| 163 __ leal(EDI, FieldAddress(EDX, Array::data_offset() + (2 * kWordSize))); | |
| 164 for (int i = 0; i < num_opt_params; i++) { | |
| 165 // Handle this optional parameter only if k or fewer positional arguments | |
| 166 // have been passed, where k is the position of this optional parameter in | |
| 167 // the formal parameter list. | |
| 168 Label load_default_value, assign_optional_parameter, next_parameter; | |
| 169 const int param_pos = opt_param_position[i]; | |
| 170 __ cmpl(ECX, Immediate(param_pos)); | |
| 171 __ j(GREATER, &next_parameter, Assembler::kNearJump); | |
| 172 // Check if this named parameter was passed in. | |
| 173 __ movl(EAX, Address(EDI, 0)); // Load EAX with the name of the argument. | |
| 174 __ CompareObject(EAX, opt_param[i]->name()); | |
| 175 __ j(NOT_EQUAL, &load_default_value, Assembler::kNearJump); | |
| 176 // Load EAX with passed-in argument at provided arg_pos, i.e. at | |
| 177 // fp[1 + argc - arg_pos]. | |
| 178 __ movl(EAX, Address(EDI, kWordSize)); // EAX is arg_pos as Smi. | |
| 179 __ addl(EDI, Immediate(2 * kWordSize)); // Point to next name/pos pair. | |
| 180 __ negl(EAX); | |
| 181 Address argument_addr(EBX, EAX, TIMES_2, 0); // EAX is a negative Smi. | |
| 182 __ movl(EAX, argument_addr); | |
| 183 __ jmp(&assign_optional_parameter, Assembler::kNearJump); | |
| 184 __ Bind(&load_default_value); | |
| 185 // Load EAX with default argument at pos. | |
| 186 const Object& value = Object::ZoneHandle( | |
| 187 parsed_function().default_parameter_values().At( | |
| 188 param_pos - num_fixed_params)); | |
| 189 __ LoadObject(EAX, value); | |
| 190 __ Bind(&assign_optional_parameter); | |
| 191 // Assign EAX to fp[ParsedFunction::kFirstLocalSlotIndex - param_pos]. | |
| 192 // We do not use the final allocation index of the variable here, i.e. | |
| 193 // scope->VariableAt(i)->index(), because captured variables still need | |
| 194 // to be copied to the context that is not yet allocated. | |
| 195 const Address param_addr( | |
| 196 EBP, (ParsedFunction::kFirstLocalSlotIndex - param_pos) * kWordSize); | |
| 197 __ movl(param_addr, EAX); | |
| 198 __ Bind(&next_parameter); | |
| 199 } | |
| 200 delete[] opt_param; | |
| 201 delete[] opt_param_position; | |
| 202 // Check that EDI now points to the null terminator in the array descriptor. | |
| 203 const Immediate raw_null = | 146 const Immediate raw_null = |
| 204 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 147 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 205 Label all_arguments_processed; | 148 if (num_opt_params > 0) { |
| 206 __ cmpl(Address(EDI, 0), raw_null); | 149 // Start by alphabetically sorting the names of the optional parameters. |
| 207 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); | 150 LocalVariable** opt_param = new LocalVariable*[num_opt_params]; |
| 151 int* opt_param_position = new int[num_opt_params]; | |
| 152 for (int pos = num_fixed_params; pos < num_params; pos++) { | |
| 153 LocalVariable* parameter = scope->VariableAt(pos); | |
| 154 const String& opt_param_name = parameter->name(); | |
| 155 int i = pos - num_fixed_params; | |
| 156 while (--i >= 0) { | |
| 157 LocalVariable* param_i = opt_param[i]; | |
| 158 const intptr_t result = opt_param_name.CompareTo(param_i->name()); | |
| 159 ASSERT(result != 0); | |
| 160 if (result > 0) break; | |
| 161 opt_param[i + 1] = opt_param[i]; | |
| 162 opt_param_position[i + 1] = opt_param_position[i]; | |
| 163 } | |
| 164 opt_param[i + 1] = parameter; | |
| 165 opt_param_position[i + 1] = pos; | |
| 166 } | |
| 167 // Generate code handling each optional parameter in alphabetical order. | |
| 168 // Total number of args is the first Smi in args descriptor array (EDX). | |
| 169 __ movl(EBX, FieldAddress(EDX, Array::data_offset())); | |
| 170 // Number of positional args is the second Smi in descriptor array (EDX). | |
| 171 __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize))); | |
| 172 __ SmiUntag(ECX); | |
| 173 // Let EBX point to the first passed argument, i.e. to fp[1 + argc - 0]. | |
| 174 __ leal(EBX, Address(EBP, EBX, TIMES_2, kWordSize)); // EBX is Smi. | |
| 175 // Let EDI point to the name/pos pair of the first named argument. | |
| 176 __ leal(EDI, FieldAddress(EDX, Array::data_offset() + (2 * kWordSize))); | |
| 177 for (int i = 0; i < num_opt_params; i++) { | |
| 178 // Handle this optional parameter only if k or fewer positional arguments | |
| 179 // have been passed, where k is the position of this optional parameter in | |
| 180 // the formal parameter list. | |
| 181 Label load_default_value, assign_optional_parameter, next_parameter; | |
| 182 const int param_pos = opt_param_position[i]; | |
| 183 __ cmpl(ECX, Immediate(param_pos)); | |
| 184 __ j(GREATER, &next_parameter, Assembler::kNearJump); | |
| 185 // Check if this named parameter was passed in. | |
| 186 __ movl(EAX, Address(EDI, 0)); // Load EAX with the name of the argument. | |
| 187 __ CompareObject(EAX, opt_param[i]->name()); | |
| 188 __ j(NOT_EQUAL, &load_default_value, Assembler::kNearJump); | |
| 189 // Load EAX with passed-in argument at provided arg_pos, i.e. at | |
| 190 // fp[1 + argc - arg_pos]. | |
| 191 __ movl(EAX, Address(EDI, kWordSize)); // EAX is arg_pos as Smi. | |
| 192 __ addl(EDI, Immediate(2 * kWordSize)); // Point to next name/pos pair. | |
| 193 __ negl(EAX); | |
| 194 Address argument_addr(EBX, EAX, TIMES_2, 0); // EAX is a negative Smi. | |
| 195 __ movl(EAX, argument_addr); | |
| 196 __ jmp(&assign_optional_parameter, Assembler::kNearJump); | |
| 197 __ Bind(&load_default_value); | |
| 198 // Load EAX with default argument at pos. | |
| 199 const Object& value = Object::ZoneHandle( | |
| 200 parsed_function().default_parameter_values().At( | |
| 201 param_pos - num_fixed_params)); | |
| 202 __ LoadObject(EAX, value); | |
| 203 __ Bind(&assign_optional_parameter); | |
| 204 // Assign EAX to fp[ParsedFunction::kFirstLocalSlotIndex - param_pos]. | |
| 205 // We do not use the final allocation index of the variable here, i.e. | |
| 206 // scope->VariableAt(i)->index(), because captured variables still need | |
| 207 // to be copied to the context that is not yet allocated. | |
| 208 intptr_t computed_param_pos = (ParsedFunction::kFirstLocalSlotIndex - | |
| 209 param_pos + implicit_this_param_pos); | |
| 210 const Address param_addr(EBP, (computed_param_pos * kWordSize)); | |
| 211 __ movl(param_addr, EAX); | |
| 212 __ Bind(&next_parameter); | |
| 213 } | |
| 214 delete[] opt_param; | |
| 215 delete[] opt_param_position; | |
| 216 // Check that EDI now points to the null terminator in the array descriptor. | |
| 217 __ cmpl(Address(EDI, 0), raw_null); | |
| 218 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); | |
| 219 } else { | |
| 220 ASSERT(is_implicit_native_closure); | |
| 221 __ jmp(&all_arguments_processed, Assembler::kNearJump); | |
| 222 } | |
| 208 | 223 |
| 209 __ Bind(&wrong_num_arguments); | 224 __ Bind(&wrong_num_arguments); |
| 210 if (StackSize() != 0) { | 225 if (StackSize() != 0) { |
| 211 // We need to unwind the space we reserved for locals and copied parameters. | 226 // We need to unwind the space we reserved for locals and copied parameters. |
| 212 // The NoSuchMethodFunction stub does not expect to see that area on the | 227 // The NoSuchMethodFunction stub does not expect to see that area on the |
| 213 // stack. | 228 // stack. |
| 214 __ addl(ESP, Immediate(StackSize() * kWordSize)); | 229 __ addl(ESP, Immediate(StackSize() * kWordSize)); |
| 215 } | 230 } |
| 216 if (function.IsClosureFunction()) { | 231 if (function.IsClosureFunction()) { |
| 217 GenerateCallRuntime(AstNode::kNoId, | 232 GenerateCallRuntime(AstNode::kNoId, |
| (...skipping 788 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1006 __ cvtsi2sd(result, temp); | 1021 __ cvtsi2sd(result, temp); |
| 1007 __ Bind(&done); | 1022 __ Bind(&done); |
| 1008 } | 1023 } |
| 1009 | 1024 |
| 1010 | 1025 |
| 1011 #undef __ | 1026 #undef __ |
| 1012 | 1027 |
| 1013 } // namespace dart | 1028 } // namespace dart |
| 1014 | 1029 |
| 1015 #endif // defined TARGET_ARCH_IA32 | 1030 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |