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