Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(978)

Side by Side Diff: runtime/vm/stub_code_ia32.cc

Issue 11316353: Refactor the InstanceFunctionLookupStub. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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" 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 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 __ popl(EDX); // Restore arguments descriptor array. 219 __ popl(EDX); // Restore arguments descriptor array.
220 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); 220 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset()));
221 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); 221 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
222 __ LeaveFrame(); 222 __ LeaveFrame();
223 __ jmp(EAX); 223 __ jmp(EAX);
224 __ int3(); 224 __ int3();
225 } 225 }
226 226
227 227
228 // Input parameters: 228 // Input parameters:
229 // EDI: argument count, may be zero. 229 // EDX: smi-tagged argument count, may be zero.
230 // Uses EAX, EBX, ECX, EDX. 230 // Uses EAX, EBX, ECX, EDX.
231 static void PushArgumentsArray(Assembler* assembler, intptr_t arg_offset) { 231 static void PushArgumentsArray(Assembler* assembler, intptr_t arg_offset) {
232 const Immediate raw_null = 232 const Immediate raw_null =
233 Immediate(reinterpret_cast<intptr_t>(Object::null())); 233 Immediate(reinterpret_cast<intptr_t>(Object::null()));
234 234
235 // Allocate array to store arguments of caller. 235 // Allocate array to store arguments of caller.
236 __ movl(EDX, EDI); // Arguments array length.
237 __ SmiTag(EDX); // Convert to Smi.
238 __ movl(ECX, raw_null); // Null element type for raw Array. 236 __ movl(ECX, raw_null); // Null element type for raw Array.
239 __ call(&StubCode::AllocateArrayLabel()); 237 __ call(&StubCode::AllocateArrayLabel());
240 __ SmiUntag(EDX); 238 __ SmiUntag(EDX);
241 // EAX: newly allocated array. 239 // EAX: newly allocated array.
242 // EDX: length of the array (was preserved by the stub). 240 // EDX: length of the array (was preserved by the stub).
243 __ pushl(EAX); // Array is in EAX and on top of stack. 241 __ pushl(EAX); // Array is in EAX and on top of stack.
244 __ leal(EBX, Address(ESP, EDX, TIMES_4, arg_offset)); // Addr of first arg. 242 __ leal(EBX, Address(ESP, EDX, TIMES_4, arg_offset)); // Addr of first arg.
245 __ leal(ECX, FieldAddress(EAX, Array::data_offset())); 243 __ leal(ECX, FieldAddress(EAX, Array::data_offset()));
246 Label loop, loop_condition; 244 Label loop, loop_condition;
247 __ jmp(&loop_condition, Assembler::kNearJump); 245 __ jmp(&loop_condition, Assembler::kNearJump);
248 __ Bind(&loop); 246 __ Bind(&loop);
249 __ movl(EAX, Address(EBX, 0)); 247 __ movl(EAX, Address(EBX, 0));
250 __ movl(Address(ECX, 0), EAX); 248 __ movl(Address(ECX, 0), EAX);
251 __ AddImmediate(ECX, Immediate(kWordSize)); 249 __ AddImmediate(ECX, Immediate(kWordSize));
252 __ AddImmediate(EBX, Immediate(-kWordSize)); 250 __ AddImmediate(EBX, Immediate(-kWordSize));
253 __ Bind(&loop_condition); 251 __ Bind(&loop_condition);
254 __ decl(EDX); 252 __ decl(EDX);
255 __ j(POSITIVE, &loop, Assembler::kNearJump); 253 __ j(POSITIVE, &loop, Assembler::kNearJump);
256 } 254 }
257 255
258 256
259 // Input parameters: 257 // Input parameters:
260 // ECX: ic-data. 258 // ECX: ic-data.
261 // EDX: arguments descriptor array. 259 // EDX: arguments descriptor array.
262 // Note: The receiver object is the first argument to the function being 260 // Note: The receiver object is the first argument to the function being
263 // called, the stub accesses the receiver from this location directly 261 // called, the stub accesses the receiver from this location directly
264 // when trying to resolve the call. 262 // when trying to resolve the call.
265 // Uses EDI. 263 // Uses EDI.
266 void StubCode::GenerateInstanceFunctionLookupStub(Assembler* assembler) { 264 void StubCode::GenerateInstanceFunctionLookupStub(Assembler* assembler) {
265 AssemblerMacros::EnterStubFrame(assembler);
266
267 const Immediate raw_null = 267 const Immediate raw_null =
268 Immediate(reinterpret_cast<intptr_t>(Object::null())); 268 Immediate(reinterpret_cast<intptr_t>(Object::null()));
269 __ pushl(raw_null); // Space for the return value.
269 270
270 // Create a stub frame as we are pushing some objects on the stack before 271 // Push the receiver as an argument. Load the smi-tagged argument
271 // calling into the runtime. 272 // count into EDI to index the receiver in the stack. There are
272 AssemblerMacros::EnterStubFrame(assembler); 273 // three words (null, stub's pc marker, saved fp) above the return
274 // address.
275 __ movl(EDI, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
276 __ pushl(Address(ESP, EDI, TIMES_2, (3 * kWordSize)));
273 277
274 // Preserve values across call to resolving. 278 __ pushl(ECX); // Pass IC data object.
275 // Stack at this point: 279 __ pushl(EDX); // Pass arguments descriptor array.
276 // TOS + 0: PC marker => RawInstruction object.
277 // TOS + 1: Saved EBP of previous frame. <== EBP
278 // TOS + 2: Dart code return address
279 // TOS + 3: Last argument of caller.
280 // ....
281 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
282 __ movl(EAX, Address(EBP, EAX, TIMES_2, kWordSize)); // Get receiver.
283 // EAX: receiver.
284 // ECX: ic-data.
285 // EDX: arguments descriptor array.
286 // The target function was not found.
287 // First check to see if this is a getter function and we are
288 // trying to create a closure of an instance function.
289 // Push values that need to be preserved across runtime call.
290 __ pushl(EAX); // Preserve receiver.
291 __ pushl(ECX); // Preserve ic-data.
292 __ pushl(EDX); // Preserve arguments descriptor array.
293 280
294 __ pushl(raw_null); // Setup space on stack for return value. 281 // Pass the call's arguments array.
295 __ pushl(EAX); // Push receiver. 282 __ movl(EDX, EDI); // Smi-tagged arguments array length.
296 __ pushl(ECX); // Ic-data. 283 PushArgumentsArray(assembler, (7 * kWordSize));
297 __ CallRuntime(kResolveImplicitClosureFunctionRuntimeEntry); 284 // Stack layout explaining "(7 * kWordSize)" offset.
298 __ popl(EAX);
299 __ popl(EAX);
300 __ popl(EBX); // Get return value into EBX, might be Closure object.
301
302 // Pop preserved values.
303 __ popl(EDX); // Restore arguments descriptor array.
304 __ popl(ECX); // Restore ic-data.
305 __ popl(EAX); // Restore receiver.
306
307 __ cmpl(EBX, raw_null);
308 Label check_implicit_closure_through_getter;
309 __ j(EQUAL, &check_implicit_closure_through_getter, Assembler::kNearJump);
310
311 __ movl(EAX, EBX); // Return value is the closure object.
312 // Remove the stub frame as we are about return.
313 __ LeaveFrame();
314 __ ret();
315
316 __ Bind(&check_implicit_closure_through_getter);
317 // EAX: receiver.
318 // ECX: ic-data.
319 // EDX: arguments descriptor array.
320 // This is not the case of an instance so invoke the getter of the
321 // same name and see if we get a closure back which we are then
322 // supposed to invoke.
323 // Push values that need to be preserved across runtime call.
324 __ pushl(EAX); // Preserve receiver.
325 __ pushl(ECX); // Preserve ic-data.
326 __ pushl(EDX); // Preserve arguments descriptor array.
327
328 __ pushl(raw_null); // Setup space on stack for return value.
329 __ pushl(EAX); // Push receiver.
330 __ pushl(ECX); // Ic-data.
331 __ CallRuntime(kResolveImplicitClosureThroughGetterRuntimeEntry);
332 __ popl(EAX); // Pop argument.
333 __ popl(EAX); // Pop argument.
334 __ popl(EBX); // get return value into EBX, might be Closure object.
335
336 // Pop preserved values.
337 __ popl(EDX); // Restore arguments descriptor array.
338 __ popl(ECX); // Restore ic-data.
339 __ popl(EAX); // Restore receiver.
340
341 __ cmpl(EBX, raw_null);
342 Label function_not_found;
343 __ j(EQUAL, &function_not_found, Assembler::kNearJump);
344
345 // EBX: Closure object.
346 // EDX: Arguments descriptor array.
347 __ pushl(raw_null); // Setup space on stack for result from invoking Closure.
348 __ pushl(EBX); // Closure object.
349 __ pushl(EDX); // Arguments descriptor.
350 __ movl(EDI, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
351 __ SmiUntag(EDI); // Arguments array length, including the original receiver.
352 PushArgumentsArray(assembler, (kWordSize * 6));
353 // Stack layout explaining "(kWordSize * 6)" offset.
354 // TOS + 0: Argument array.
355 // TOS + 1: Arguments descriptor array.
356 // TOS + 2: Closure object.
357 // TOS + 3: Place for result from closure function.
358 // TOS + 4: PC marker => RawInstruction object.
359 // TOS + 5: Saved EBP of previous frame. <== EBP
360 // TOS + 6: Dart code return address
361 // TOS + 7: Last argument of caller.
362 // ....
363
364 __ CallRuntime(kInvokeImplicitClosureFunctionRuntimeEntry);
365 // Remove arguments.
366 __ popl(EAX);
367 __ popl(EAX);
368 __ popl(EAX);
369 __ popl(EAX); // Get result into EAX.
370
371 // Remove the stub frame as we are about to return.
372 __ LeaveFrame();
373 __ ret();
374
375 __ Bind(&function_not_found);
376 // The target function was not found, so invoke method
377 // "dynamic noSuchMethod(InvocationMirror invocation)".
378 // EAX: receiver.
379 // ECX: ic-data.
380 // EDX: arguments descriptor array.
381
382 __ pushl(raw_null); // Setup space on stack for result from noSuchMethod.
383 __ pushl(EAX); // Receiver.
384 __ pushl(ECX); // IC-data.
385 __ pushl(EDX); // Arguments descriptor array.
386 __ movl(EDI, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
387 __ SmiUntag(EDI); // Arguments array length, including the original receiver.
388 // See stack layout below explaining "wordSize * 7" offset.
389 PushArgumentsArray(assembler, (kWordSize * 7));
390
391 // Stack:
392 // TOS + 0: Arguments array. 285 // TOS + 0: Arguments array.
393 // TOS + 1: Arguments descriptor array. 286 // TOS + 1: Arguments descriptor array.
394 // TOS + 2: IC-data. 287 // TOS + 2: IC data object.
395 // TOS + 3: Receiver 288 // TOS + 3: Receiver.
396 // TOS + 4: Place for result from noSuchMethod. 289 // TOS + 4: Space for the result of the runtime call.
397 // TOS + 5: PC marker => RawInstruction object. 290 // TOS + 5: Stub's PC marker (0)
398 // TOS + 6: Saved EBP of previous frame. <== EBP 291 // TOS + 6: Saved FP
399 // TOS + 7: Dart code return address 292 // TOS + 7: Dart code return address
400 // TOS + 8: Last argument of caller. 293 // TOS + 8: Last argument of caller.
401 // .... 294 // ....
402 295
403 __ CallRuntime(kInvokeNoSuchMethodFunctionRuntimeEntry); 296 __ CallRuntime(kInstanceFunctionLookupRuntimeEntry);
404 // Remove arguments. 297 // Remove arguments.
405 __ popl(EAX); 298 __ popl(EAX);
406 __ popl(EAX); 299 __ popl(EAX);
407 __ popl(EAX); 300 __ popl(EAX);
408 __ popl(EAX); 301 __ popl(EAX);
409 __ popl(EAX); // Get result into EAX. 302 __ popl(EAX); // Get result into EAX.
410
411 // Remove the stub frame as we are about to return.
412 __ LeaveFrame(); 303 __ LeaveFrame();
413 __ ret(); 304 __ ret();
414 } 305 }
415 306
416 307
417 DECLARE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, 308 DECLARE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame,
418 intptr_t deopt_reason, 309 intptr_t deopt_reason,
419 uword saved_registers_address); 310 uword saved_registers_address);
420 311
421 DECLARE_LEAF_RUNTIME_ENTRY(void, DeoptimizeFillFrame, uword last_fp); 312 DECLARE_LEAF_RUNTIME_ENTRY(void, DeoptimizeFillFrame, uword last_fp);
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
529 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { 420 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) {
530 GenerateDeoptimizationSequence(assembler, false); // Don't preserve EAX. 421 GenerateDeoptimizationSequence(assembler, false); // Don't preserve EAX.
531 } 422 }
532 423
533 424
534 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) { 425 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) {
535 AssemblerMacros::EnterStubFrame(assembler); 426 AssemblerMacros::EnterStubFrame(assembler);
536 // Load the receiver into EAX. The argument count in the arguments 427 // Load the receiver into EAX. The argument count in the arguments
537 // descriptor in EDX is a smi. 428 // descriptor in EDX is a smi.
538 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); 429 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
539 // Two words (return addres, saved fp) in the stack above the last argument. 430 // Two words (saved fp, stub's pc marker) in the stack above the return
431 // address.
540 __ movl(EAX, Address(ESP, EAX, TIMES_2, 2 * kWordSize)); 432 __ movl(EAX, Address(ESP, EAX, TIMES_2, 2 * kWordSize));
541 // Preserve IC data and arguments descriptor. 433 // Preserve IC data and arguments descriptor.
542 __ pushl(ECX); 434 __ pushl(ECX);
543 __ pushl(EDX); 435 __ pushl(EDX);
544 436
545 const Immediate raw_null = 437 const Immediate raw_null =
546 Immediate(reinterpret_cast<intptr_t>(Instructions::null())); 438 Immediate(reinterpret_cast<intptr_t>(Instructions::null()));
547 __ pushl(raw_null); // Space for the result of the runtime call. 439 __ pushl(raw_null); // Space for the result of the runtime call.
548 __ pushl(EAX); // Pass receiver. 440 __ pushl(EAX); // Pass receiver.
549 __ pushl(ECX); // Pass IC data. 441 __ pushl(ECX); // Pass IC data.
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
782 // EDI: non-closure object. 674 // EDI: non-closure object.
783 // EDX: arguments descriptor array. 675 // EDX: arguments descriptor array.
784 676
785 // Create a stub frame as we are pushing some objects on the stack before 677 // Create a stub frame as we are pushing some objects on the stack before
786 // calling into the runtime. 678 // calling into the runtime.
787 AssemblerMacros::EnterStubFrame(assembler); 679 AssemblerMacros::EnterStubFrame(assembler);
788 680
789 __ pushl(raw_null); // Setup space on stack for result from error reporting. 681 __ pushl(raw_null); // Setup space on stack for result from error reporting.
790 __ pushl(EDI); // Non-closure object. 682 __ pushl(EDI); // Non-closure object.
791 __ pushl(EDX); // Arguments descriptor. 683 __ pushl(EDX); // Arguments descriptor.
792 // Load num_args. 684 // Load smi-tagged arguments array length, including the non-closure.
793 __ movl(EDI, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); 685 __ movl(EDX, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
794 __ SmiUntag(EDI); // Arguments array length, including the non-closure.
795 // See stack layout below explaining "wordSize * 6" offset. 686 // See stack layout below explaining "wordSize * 6" offset.
796 PushArgumentsArray(assembler, (kWordSize * 6)); 687 PushArgumentsArray(assembler, (kWordSize * 6));
797 688
798 // Stack: 689 // Stack:
799 // TOS + 0: Argument array. 690 // TOS + 0: Argument array.
800 // TOS + 1: Arguments descriptor array. 691 // TOS + 1: Arguments descriptor array.
801 // TOS + 2: Non-closure object. 692 // TOS + 2: Non-closure object.
802 // TOS + 3: Place for result from the call. 693 // TOS + 3: Place for result from the call.
803 // TOS + 4: PC marker => RawInstruction object. 694 // TOS + 4: PC marker => RawInstruction object.
804 // TOS + 5: Saved EBP of previous frame. <== EBP 695 // TOS + 5: Saved EBP of previous frame. <== EBP
(...skipping 646 matching lines...) Expand 10 before | Expand all | Expand 10 after
1451 // EBP + 8 + 4*(n-1) : address of first argument (arg 0). 1342 // EBP + 8 + 4*(n-1) : address of first argument (arg 0).
1452 // ECX : ic-data. 1343 // ECX : ic-data.
1453 // EDX : arguments descriptor array. 1344 // EDX : arguments descriptor array.
1454 // Uses EAX, EBX, EDI as temporary registers. 1345 // Uses EAX, EBX, EDI as temporary registers.
1455 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { 1346 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) {
1456 // The target function was not found, so invoke method 1347 // The target function was not found, so invoke method
1457 // "dynamic noSuchMethod(InvocationMirror invocation)". 1348 // "dynamic noSuchMethod(InvocationMirror invocation)".
1458 const Immediate raw_null = 1349 const Immediate raw_null =
1459 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1350 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1460 __ movl(EDI, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); 1351 __ movl(EDI, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
1461 __ SmiUntag(EDI); 1352 __ movl(EAX, Address(EBP, EDI, TIMES_2, kWordSize)); // Get receiver.
1462 __ movl(EAX, Address(EBP, EDI, TIMES_4, kWordSize)); // Get receiver.
1463 1353
1464 // Create a stub frame as we are pushing some objects on the stack before 1354 // Create a stub frame as we are pushing some objects on the stack before
1465 // calling into the runtime. 1355 // calling into the runtime.
1466 AssemblerMacros::EnterStubFrame(assembler); 1356 AssemblerMacros::EnterStubFrame(assembler);
1467 1357
1468 __ pushl(raw_null); // Setup space on stack for result from noSuchMethod. 1358 __ pushl(raw_null); // Setup space on stack for result from noSuchMethod.
1469 __ pushl(EAX); // Receiver. 1359 __ pushl(EAX); // Receiver.
1470 __ pushl(ECX); // IC data array. 1360 __ pushl(ECX); // IC data array.
1471 __ pushl(EDX); // Arguments descriptor array. 1361 __ pushl(EDX); // Arguments descriptor array.
1472 // EDI: Arguments array length, including the receiver. 1362
1363 __ movl(EDX, EDI);
1473 // See stack layout below explaining "wordSize * 10" offset. 1364 // See stack layout below explaining "wordSize * 10" offset.
1474 PushArgumentsArray(assembler, (kWordSize * 10)); 1365 PushArgumentsArray(assembler, (kWordSize * 10));
1475 1366
1476 // Stack: 1367 // Stack:
1477 // TOS + 0: Argument array. 1368 // TOS + 0: Argument array.
1478 // TOS + 1: Arguments descriptor array. 1369 // TOS + 1: Arguments descriptor array.
1479 // TOS + 2: Ic-data. 1370 // TOS + 2: Ic-data.
1480 // TOS + 3: Receiver. 1371 // TOS + 3: Receiver.
1481 // TOS + 4: Place for result from noSuchMethod. 1372 // TOS + 4: Place for result from noSuchMethod.
1482 // TOS + 5: PC marker => RawInstruction object. 1373 // TOS + 5: PC marker => RawInstruction object.
(...skipping 737 matching lines...) Expand 10 before | Expand all | Expand 10 after
2220 __ Bind(&done); 2111 __ Bind(&done);
2221 __ popl(temp); 2112 __ popl(temp);
2222 __ popl(right); 2113 __ popl(right);
2223 __ popl(left); 2114 __ popl(left);
2224 __ ret(); 2115 __ ret();
2225 } 2116 }
2226 2117
2227 } // namespace dart 2118 } // namespace dart
2228 2119
2229 #endif // defined TARGET_ARCH_IA32 2120 #endif // defined TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698