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" | 5 #include "vm/globals.h" |
6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
7 | 7 |
8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
9 #include "vm/assembler_macros.h" | 9 #include "vm/assembler_macros.h" |
10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
245 __ popl(EDX); // Restore arguments descriptor array. | 245 __ popl(EDX); // Restore arguments descriptor array. |
246 __ movl(EAX, FieldAddress(EAX, Function::code_offset())); | 246 __ movl(EAX, FieldAddress(EAX, Function::code_offset())); |
247 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); | 247 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); |
248 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 248 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
249 __ LeaveFrame(); | 249 __ LeaveFrame(); |
250 __ jmp(EAX); | 250 __ jmp(EAX); |
251 __ int3(); | 251 __ int3(); |
252 } | 252 } |
253 | 253 |
254 | 254 |
255 // Lookup for [function-name, arg count] in 'functions_map_'. | |
256 // Input parameters (to be treated as read only, unless calling to target!): | |
257 // ECX: ic-data. | |
258 // EDX: arguments descriptor array (num_args is first Smi element). | |
259 // Stack: return address, arguments. | |
260 // If the lookup succeeds we jump to the target method from here, otherwise | |
261 // we continue in code generated by the caller of 'MegamorphicLookup'. | |
262 static void MegamorphicLookup(Assembler* assembler) { | |
263 const Immediate raw_null = | |
264 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
265 Label class_in_eax, smi_receiver, null_receiver, not_found; | |
266 // Total number of args is the first Smi in args descriptor array (EDX). | |
267 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | |
268 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // Get receiver. EAX is a Smi. | |
269 // TODO(srdjan): Remove the special casing below for null receiver, once | |
270 // NullClass is implemented. | |
271 __ cmpl(EAX, raw_null); | |
272 // Use Object class if receiver is null. | |
273 __ j(EQUAL, &null_receiver, Assembler::kNearJump); | |
274 __ testl(EAX, Immediate(kSmiTagMask)); | |
275 __ j(ZERO, &smi_receiver, Assembler::kNearJump); | |
276 __ LoadClass(EAX, EAX, EDI); | |
277 __ jmp(&class_in_eax, Assembler::kNearJump); | |
278 __ Bind(&smi_receiver); | |
279 // For Smis we need to get the class from the isolate. | |
280 // Load current Isolate pointer from Context structure into EAX. | |
281 __ movl(EAX, FieldAddress(CTX, Context::isolate_offset())); | |
282 __ movl(EAX, Address(EAX, Isolate::object_store_offset())); | |
283 __ movl(EAX, Address(EAX, ObjectStore::smi_class_offset())); | |
284 __ jmp(&class_in_eax, Assembler::kNearJump); | |
285 __ Bind(&null_receiver); | |
286 __ movl(EAX, FieldAddress(CTX, Context::isolate_offset())); | |
287 __ movl(EAX, Address(EAX, Isolate::object_store_offset())); | |
288 __ movl(EAX, Address(EAX, ObjectStore::object_class_offset())); | |
289 | |
290 __ Bind(&class_in_eax); | |
291 // Class is in EAX. | |
292 | |
293 Label loop, next_iteration; | |
294 // Get functions_cache, since it is allocated lazily it maybe null. | |
295 __ movl(EAX, FieldAddress(EAX, Class::functions_cache_offset())); | |
296 __ cmpl(EAX, raw_null); | |
297 __ j(EQUAL, ¬_found, Assembler::kNearJump); | |
298 | |
299 // Iterate and search for identical name. | |
300 __ leal(EBX, FieldAddress(EAX, Array::data_offset())); | |
301 | |
302 // EBX is pointing into content of functions_map_ array. | |
303 __ Bind(&loop); | |
304 __ movl(EDI, Address(EBX, FunctionsCache::kFunctionName * kWordSize)); | |
305 | |
306 __ cmpl(EDI, raw_null); | |
307 __ j(EQUAL, ¬_found, Assembler::kNearJump); | |
308 | |
309 __ cmpl(EDI, FieldAddress(ECX, ICData::target_name_offset())); | |
310 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump); | |
311 | |
312 // Name found, check total argument count and named argument count. | |
313 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | |
314 // EAX is total argument count as Smi. | |
315 __ movl(EDI, Address(EBX, FunctionsCache::kArgCount * kWordSize)); | |
316 __ cmpl(EAX, EDI); // Compare total argument counts. | |
317 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump); | |
318 __ subl(EAX, FieldAddress(EDX, Array::data_offset() + kWordSize)); | |
319 // EAX is named argument count as Smi. | |
320 __ movl(EDI, Address(EBX, FunctionsCache::kNamedArgCount * kWordSize)); | |
321 __ cmpl(EAX, EDI); // Compare named argument counts. | |
322 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump); | |
323 | |
324 // Argument count matches, jump to target. | |
325 // EDX: arguments descriptor array. | |
326 __ movl(ECX, Address(EBX, FunctionsCache::kFunction * kWordSize)); | |
327 __ movl(ECX, FieldAddress(ECX, Function::code_offset())); | |
328 __ movl(ECX, FieldAddress(ECX, Code::instructions_offset())); | |
329 __ addl(ECX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | |
330 __ jmp(ECX); | |
331 | |
332 __ Bind(&next_iteration); | |
333 __ AddImmediate(EBX, Immediate(FunctionsCache::kNumEntries * kWordSize)); | |
334 __ jmp(&loop, Assembler::kNearJump); | |
335 | |
336 __ Bind(¬_found); | |
337 } | |
338 | |
339 | |
340 // Input parameters: | 255 // Input parameters: |
341 // EDI: argument count, may be zero. | 256 // EDI: argument count, may be zero. |
342 // Uses EAX, EBX, ECX, EDX. | 257 // Uses EAX, EBX, ECX, EDX. |
343 static void PushArgumentsArray(Assembler* assembler, intptr_t arg_offset) { | 258 static void PushArgumentsArray(Assembler* assembler, intptr_t arg_offset) { |
344 const Immediate raw_null = | 259 const Immediate raw_null = |
345 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 260 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
346 | 261 |
347 // Allocate array to store arguments of caller. | 262 // Allocate array to store arguments of caller. |
348 __ movl(EDX, EDI); // Arguments array length. | 263 __ movl(EDX, EDI); // Arguments array length. |
349 __ SmiTag(EDX); // Convert to Smi. | 264 __ SmiTag(EDX); // Convert to Smi. |
(...skipping 18 matching lines...) Expand all Loading... |
368 } | 283 } |
369 | 284 |
370 | 285 |
371 // Input parameters: | 286 // Input parameters: |
372 // ECX: ic-data. | 287 // ECX: ic-data. |
373 // EDX: arguments descriptor array (num_args is first Smi element). | 288 // EDX: arguments descriptor array (num_args is first Smi element). |
374 // Note: The receiver object is the first argument to the function being | 289 // Note: The receiver object is the first argument to the function being |
375 // called, the stub accesses the receiver from this location directly | 290 // called, the stub accesses the receiver from this location directly |
376 // when trying to resolve the call. | 291 // when trying to resolve the call. |
377 // Uses EDI. | 292 // Uses EDI. |
378 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { | 293 void StubCode::GenerateInstanceFunctionLookupStub(Assembler* assembler) { |
379 const Immediate raw_null = | 294 const Immediate raw_null = |
380 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 295 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
381 | 296 |
382 MegamorphicLookup(assembler); | |
383 // Lookup in function_table_ failed, resolve, compile and enter function | |
384 // into function_table_. | |
385 | |
386 // Create a stub frame as we are pushing some objects on the stack before | 297 // Create a stub frame as we are pushing some objects on the stack before |
387 // calling into the runtime. | 298 // calling into the runtime. |
388 AssemblerMacros::EnterStubFrame(assembler); | 299 AssemblerMacros::EnterStubFrame(assembler); |
389 | 300 |
390 // Preserve values across call to resolving. | 301 // Preserve values across call to resolving. |
391 // Stack at this point: | 302 // Stack at this point: |
392 // TOS + 0: PC marker => RawInstruction object. | 303 // TOS + 0: PC marker => RawInstruction object. |
393 // TOS + 1: Saved EBP of previous frame. <== EBP | 304 // TOS + 1: Saved EBP of previous frame. <== EBP |
394 // TOS + 2: Dart code return address | 305 // TOS + 2: Dart code return address |
395 // TOS + 3: Last argument of caller. | 306 // TOS + 3: Last argument of caller. |
(...skipping 1307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1703 __ popl(EAX); | 1614 __ popl(EAX); |
1704 } | 1615 } |
1705 __ popl(EAX); // Pop returned code object into EAX (null if not found). | 1616 __ popl(EAX); // Pop returned code object into EAX (null if not found). |
1706 __ popl(ECX); // Restore IC data array. | 1617 __ popl(ECX); // Restore IC data array. |
1707 __ popl(EDX); // Restore arguments array. | 1618 __ popl(EDX); // Restore arguments array. |
1708 __ LeaveFrame(); | 1619 __ LeaveFrame(); |
1709 Label call_target_function; | 1620 Label call_target_function; |
1710 __ cmpl(EAX, raw_null); | 1621 __ cmpl(EAX, raw_null); |
1711 __ j(NOT_EQUAL, &call_target_function, Assembler::kNearJump); | 1622 __ j(NOT_EQUAL, &call_target_function, Assembler::kNearJump); |
1712 // NoSuchMethod or closure. | 1623 // NoSuchMethod or closure. |
1713 __ jmp(&StubCode::MegamorphicLookupLabel()); | 1624 __ jmp(&StubCode::InstanceFunctionLookupLabel()); |
1714 | 1625 |
1715 __ Bind(&found); | 1626 __ Bind(&found); |
1716 // EBX: Pointer to an IC data check group (classes + target) | 1627 // EBX: Pointer to an IC data check group (classes + target) |
1717 __ movl(EAX, Address(EBX, kWordSize * num_args)); // Target function. | 1628 __ movl(EAX, Address(EBX, kWordSize * num_args)); // Target function. |
1718 | 1629 |
1719 __ Bind(&call_target_function); | 1630 __ Bind(&call_target_function); |
1720 // EAX: Target function. | 1631 // EAX: Target function. |
1721 __ movl(EAX, FieldAddress(EAX, Function::code_offset())); | 1632 __ movl(EAX, FieldAddress(EAX, Function::code_offset())); |
1722 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); | 1633 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); |
1723 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 1634 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1976 __ movl(EAX, Address(ESP, 4 * kWordSize)); // Load error object. | 1887 __ movl(EAX, Address(ESP, 4 * kWordSize)); // Load error object. |
1977 __ movl(EBP, Address(ESP, 3 * kWordSize)); // Load target frame_pointer. | 1888 __ movl(EBP, Address(ESP, 3 * kWordSize)); // Load target frame_pointer. |
1978 __ movl(EBX, Address(ESP, 1 * kWordSize)); // Load target PC into EBX. | 1889 __ movl(EBX, Address(ESP, 1 * kWordSize)); // Load target PC into EBX. |
1979 __ movl(ESP, Address(ESP, 2 * kWordSize)); // Load target stack_pointer. | 1890 __ movl(ESP, Address(ESP, 2 * kWordSize)); // Load target stack_pointer. |
1980 __ jmp(EBX); // Jump to the exception handler code. | 1891 __ jmp(EBX); // Jump to the exception handler code. |
1981 } | 1892 } |
1982 | 1893 |
1983 } // namespace dart | 1894 } // namespace dart |
1984 | 1895 |
1985 #endif // defined TARGET_ARCH_IA32 | 1896 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |