| 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/code_generator.h" | 8 #include "vm/code_generator.h" |
| 9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
| 10 #include "vm/ic_data.h" |
| 10 #include "vm/object_store.h" | 11 #include "vm/object_store.h" |
| 11 #include "vm/pages.h" | 12 #include "vm/pages.h" |
| 12 #include "vm/resolver.h" | 13 #include "vm/resolver.h" |
| 13 #include "vm/scavenger.h" | 14 #include "vm/scavenger.h" |
| 14 #include "vm/stub_code.h" | 15 #include "vm/stub_code.h" |
| 15 | 16 |
| 16 | 17 |
| 17 #define __ assembler-> | 18 #define __ assembler-> |
| 18 | 19 |
| 19 namespace dart { | 20 namespace dart { |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 217 | 218 |
| 218 __ movl(ECX, FieldAddress(EAX, Code::instructions_offset())); | 219 __ movl(ECX, FieldAddress(EAX, Code::instructions_offset())); |
| 219 __ addl(ECX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 220 __ addl(ECX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 220 __ jmp(ECX); | 221 __ jmp(ECX); |
| 221 } | 222 } |
| 222 | 223 |
| 223 | 224 |
| 224 // Stub is entered after a call but before the callee's frame has been | 225 // Stub is entered after a call but before the callee's frame has been |
| 225 // constructed. | 226 // constructed. |
| 226 // Handle stack overflow by calling the runtime routine and preserving | 227 // Handle stack overflow by calling the runtime routine and preserving |
| 227 // the argument descriptor (EDX) and the name/function object of the call (ECX). | 228 // the argument descriptor (EDX) and the ic-data array/function object of |
| 229 // the call (ECX). |
| 228 // The stub must be able to return to callee in case the stack overflow | 230 // The stub must be able to return to callee in case the stack overflow |
| 229 // exception is not thrown. | 231 // exception is not thrown. |
| 230 void StubCode::GenerateStackOverflowStub(Assembler* assembler) { | 232 void StubCode::GenerateStackOverflowStub(Assembler* assembler) { |
| 231 __ EnterFrame(0); | 233 __ EnterFrame(0); |
| 232 // Stack at this point: | 234 // Stack at this point: |
| 233 // TOS + 0: Saved EBP of previous frame. <== EBP | 235 // TOS + 0: Saved EBP of previous frame. <== EBP |
| 234 // TOS + 1: Dart code return address | 236 // TOS + 1: Dart code return address |
| 235 // TOS + 2: Last argument of caller. | 237 // TOS + 2: Last argument of caller. |
| 236 // .... | 238 // .... |
| 237 __ pushl(EDX); // Preserve arguments descriptor array. | 239 __ pushl(EDX); // Preserve arguments descriptor array. |
| 238 __ pushl(ECX); // Preserve object (function name or function object). | 240 __ pushl(ECX); // Preserve object (ic-data array or function object). |
| 239 __ CallRuntimeFromStub(kStackOverflowRuntimeEntry); | 241 __ CallRuntimeFromStub(kStackOverflowRuntimeEntry); |
| 240 __ popl(ECX); // Restore object (function name or function object). | 242 __ popl(ECX); // Restore object (ic-data array or function object). |
| 241 __ popl(EDX); // Restore arguments descriptor array. | 243 __ popl(EDX); // Restore arguments descriptor array. |
| 242 __ LeaveFrame(); | 244 __ LeaveFrame(); |
| 243 __ int3(); | 245 __ int3(); |
| 244 } | 246 } |
| 245 | 247 |
| 246 | 248 |
| 247 // Called when number of invocations exceeds | 249 // Called when number of invocations exceeds |
| 248 // --optimization_invocation_threshold. | 250 // --optimization_invocation_threshold. |
| 249 // EAX: target function. | 251 // EAX: target function. |
| 250 // EDX: arguments descriptor array (num_args is first Smi element). | 252 // EDX: arguments descriptor array (num_args is first Smi element). |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 283 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); | 285 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); |
| 284 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 286 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 285 __ LeaveFrame(); | 287 __ LeaveFrame(); |
| 286 __ jmp(EAX); | 288 __ jmp(EAX); |
| 287 __ int3(); | 289 __ int3(); |
| 288 } | 290 } |
| 289 | 291 |
| 290 | 292 |
| 291 // Lookup for [function-name, arg count] in 'functions_map_'. | 293 // Lookup for [function-name, arg count] in 'functions_map_'. |
| 292 // Input parameters (to be treated as read only, unless calling to target!): | 294 // Input parameters (to be treated as read only, unless calling to target!): |
| 293 // ECX: function name string. | 295 // ECX: ic-data array. |
| 294 // EDX: arguments descriptor array (num_args is first Smi element). | 296 // EDX: arguments descriptor array (num_args is first Smi element). |
| 295 // Stack: return address, arguments. | 297 // Stack: return address, arguments. |
| 296 // If the lookup succeeds we jump to the target method from here, otherwise | 298 // If the lookup succeeds we jump to the target method from here, otherwise |
| 297 // we continue in code generated by the caller of 'MegamorphicLookup'. | 299 // we continue in code generated by the caller of 'MegamorphicLookup'. |
| 298 static void MegamorphicLookup(Assembler* assembler) { | 300 static void MegamorphicLookup(Assembler* assembler) { |
| 299 const Immediate raw_null = | 301 const Immediate raw_null = |
| 300 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 302 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 301 Label class_in_eax, smi_receiver, null_receiver, not_found; | 303 Label class_in_eax, smi_receiver, null_receiver, not_found; |
| 302 // Total number of args is the first Smi in args descriptor array (EDX). | 304 // Total number of args is the first Smi in args descriptor array (EDX). |
| 303 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 305 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 332 // Iterate and search for identical name. | 334 // Iterate and search for identical name. |
| 333 __ leal(EBX, FieldAddress(EAX, Array::data_offset())); | 335 __ leal(EBX, FieldAddress(EAX, Array::data_offset())); |
| 334 | 336 |
| 335 // EBX is pointing into content of functions_map_ array. | 337 // EBX is pointing into content of functions_map_ array. |
| 336 __ Bind(&loop); | 338 __ Bind(&loop); |
| 337 __ movl(EDI, Address(EBX, FunctionsCache::kFunctionName * kWordSize)); | 339 __ movl(EDI, Address(EBX, FunctionsCache::kFunctionName * kWordSize)); |
| 338 | 340 |
| 339 __ cmpl(EDI, raw_null); | 341 __ cmpl(EDI, raw_null); |
| 340 __ j(EQUAL, ¬_found, Assembler::kNearJump); | 342 __ j(EQUAL, ¬_found, Assembler::kNearJump); |
| 341 | 343 |
| 342 __ cmpl(EDI, ECX); | 344 ASSERT(ICData::kNameIndex == 0); |
| 345 __ cmpl(EDI, FieldAddress(ECX, Array::data_offset())); |
| 343 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump); | 346 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump); |
| 344 | 347 |
| 345 // Name found, check total argument count and named argument count. | 348 // Name found, check total argument count and named argument count. |
| 346 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 349 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 347 // EAX is total argument count as Smi. | 350 // EAX is total argument count as Smi. |
| 348 __ movl(EDI, Address(EBX, FunctionsCache::kArgCount * kWordSize)); | 351 __ movl(EDI, Address(EBX, FunctionsCache::kArgCount * kWordSize)); |
| 349 __ cmpl(EAX, EDI); // Compare total argument counts. | 352 __ cmpl(EAX, EDI); // Compare total argument counts. |
| 350 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump); | 353 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump); |
| 351 __ subl(EAX, FieldAddress(EDX, Array::data_offset() + kWordSize)); | 354 __ subl(EAX, FieldAddress(EDX, Array::data_offset() + kWordSize)); |
| 352 // EAX is named argument count as Smi. | 355 // EAX is named argument count as Smi. |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 395 __ movl(Address(ECX, 0), EAX); | 398 __ movl(Address(ECX, 0), EAX); |
| 396 __ AddImmediate(ECX, Immediate(kWordSize)); | 399 __ AddImmediate(ECX, Immediate(kWordSize)); |
| 397 __ AddImmediate(EBX, Immediate(-kWordSize)); | 400 __ AddImmediate(EBX, Immediate(-kWordSize)); |
| 398 __ Bind(&loop_condition); | 401 __ Bind(&loop_condition); |
| 399 __ decl(EDX); | 402 __ decl(EDX); |
| 400 __ j(POSITIVE, &loop, Assembler::kNearJump); | 403 __ j(POSITIVE, &loop, Assembler::kNearJump); |
| 401 } | 404 } |
| 402 | 405 |
| 403 | 406 |
| 404 // Input parameters: | 407 // Input parameters: |
| 405 // ECX: function name string. | 408 // ECX: ic-data array. |
| 406 // EDX: arguments descriptor array (num_args is first Smi element). | 409 // EDX: arguments descriptor array (num_args is first Smi element). |
| 407 // Note: The receiver object is the first argument to the function being | 410 // Note: The receiver object is the first argument to the function being |
| 408 // called, the stub accesses the receiver from this location directly | 411 // called, the stub accesses the receiver from this location directly |
| 409 // when trying to resolve the call. | 412 // when trying to resolve the call. |
| 410 // Uses EDI. | 413 // Uses EDI. |
| 411 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { | 414 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { |
| 412 const Immediate raw_null = | 415 const Immediate raw_null = |
| 413 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 416 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 414 | 417 |
| 415 MegamorphicLookup(assembler); | 418 MegamorphicLookup(assembler); |
| 416 // Lookup in function_table_ failed, resolve, compile and enter function | 419 // Lookup in function_table_ failed, resolve, compile and enter function |
| 417 // into function_table_. | 420 // into function_table_. |
| 418 | 421 |
| 419 // Create a stub frame as we are pushing some objects on the stack before | 422 // Create a stub frame as we are pushing some objects on the stack before |
| 420 // calling into the runtime. | 423 // calling into the runtime. |
| 421 __ EnterFrame(0); | 424 __ EnterFrame(0); |
| 422 | 425 |
| 423 // Preserve values across call to resolving. | 426 // Preserve values across call to resolving. |
| 424 // Stack at this point: | 427 // Stack at this point: |
| 425 // TOS + 0: Saved EBP of previous frame. <== EBP | 428 // TOS + 0: Saved EBP of previous frame. <== EBP |
| 426 // TOS + 1: Dart code return address | 429 // TOS + 1: Dart code return address |
| 427 // TOS + 2: Last argument of caller. | 430 // TOS + 2: Last argument of caller. |
| 428 // .... | 431 // .... |
| 429 // Total number of args is the first Smi in args descriptor array (EDX). | 432 // Total number of args is the first Smi in args descriptor array (EDX). |
| 430 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 433 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 431 __ movl(EAX, Address(ESP, EAX, TIMES_2, kWordSize)); // Get receiver. | 434 __ movl(EAX, Address(ESP, EAX, TIMES_2, kWordSize)); // Get receiver. |
| 432 __ pushl(EDX); // Preserve arguments descriptor array. | 435 __ pushl(EDX); // Preserve arguments descriptor array. |
| 433 __ pushl(EAX); // Preserve receiver. | 436 __ pushl(EAX); // Preserve receiver. |
| 434 __ pushl(ECX); // Preserve function name. | 437 __ pushl(ECX); // Preserve ic-data array. |
| 435 // First resolve the function to get the function object. | 438 // First resolve the function to get the function object. |
| 436 | 439 |
| 437 // Setup space for return value on stack by pushing smi 0. | 440 // Setup space for return value on stack by pushing smi 0. |
| 438 __ pushl(Immediate(0)); | 441 __ pushl(Immediate(0)); |
| 439 __ pushl(EAX); // Push receiver. | 442 __ pushl(EAX); // Push receiver. |
| 440 __ CallRuntimeFromStub(kResolveCompileInstanceFunctionRuntimeEntry); | 443 __ CallRuntimeFromStub(kResolveCompileInstanceFunctionRuntimeEntry); |
| 441 __ popl(EAX); // Remove receiver pushed earlier. | 444 __ popl(EAX); // Remove receiver pushed earlier. |
| 442 __ popl(ECX); // Pop returned code object into ECX. | 445 __ popl(ECX); // Pop returned code object into ECX. |
| 443 // Pop preserved values | 446 // Pop preserved values |
| 444 __ popl(EDX); // Restore function name. | 447 __ popl(EDX); // Restore ic-data array. |
| 445 __ popl(EAX); // Restore receiver. | 448 __ popl(EAX); // Restore receiver. |
| 446 __ popl(EDI); // Restore arguments descriptor array. | 449 __ popl(EDI); // Restore arguments descriptor array. |
| 447 | 450 |
| 448 __ cmpl(ECX, raw_null); | 451 __ cmpl(ECX, raw_null); |
| 449 Label check_implicit_closure; | 452 Label check_implicit_closure; |
| 450 __ j(EQUAL, &check_implicit_closure, Assembler::kNearJump); | 453 __ j(EQUAL, &check_implicit_closure, Assembler::kNearJump); |
| 451 | 454 |
| 452 // Remove the stub frame as we are about to jump to the dart function. | 455 // Remove the stub frame as we are about to jump to the dart function. |
| 453 __ LeaveFrame(); | 456 __ LeaveFrame(); |
| 454 | 457 |
| 455 __ movl(EDX, EDI); | 458 __ movl(EDX, EDI); |
| 456 __ movl(ECX, FieldAddress(ECX, Code::instructions_offset())); | 459 __ movl(ECX, FieldAddress(ECX, Code::instructions_offset())); |
| 457 __ addl(ECX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 460 __ addl(ECX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 458 __ jmp(ECX); | 461 __ jmp(ECX); |
| 459 | 462 |
| 460 __ Bind(&check_implicit_closure); | 463 __ Bind(&check_implicit_closure); |
| 461 // EAX: receiver. | 464 // EAX: receiver. |
| 462 // EDX: function name. | 465 // EDX: ic-data array. |
| 463 // ECX: raw_null. | 466 // ECX: raw_null. |
| 464 // EDI: arguments descriptor array. | 467 // EDI: arguments descriptor array. |
| 465 // The target function was not found. | 468 // The target function was not found. |
| 466 // First check to see if this is a getter function and we are | 469 // First check to see if this is a getter function and we are |
| 467 // trying to create a closure of an instance function. | 470 // trying to create a closure of an instance function. |
| 468 // Push values that need to be preserved across runtime call. | 471 // Push values that need to be preserved across runtime call. |
| 469 __ pushl(EAX); // Preserve receiver. | 472 __ pushl(EAX); // Preserve receiver. |
| 470 __ pushl(EDX); // Preserve function name. | 473 __ pushl(EDX); // Preserve ic-data array. |
| 471 __ pushl(EDI); // Preserve arguments descriptor array. | 474 __ pushl(EDI); // Preserve arguments descriptor array. |
| 472 | 475 |
| 473 __ pushl(Immediate(0)); | 476 __ pushl(Immediate(0)); |
| 474 __ pushl(EAX); // Push receiver. | 477 __ pushl(EAX); // Push receiver. |
| 475 __ pushl(EDX); // Function name. | 478 __ pushl(EDX); // Ic-data array. |
| 476 __ CallRuntimeFromStub(kResolveImplicitClosureFunctionRuntimeEntry); | 479 __ CallRuntimeFromStub(kResolveImplicitClosureFunctionRuntimeEntry); |
| 477 __ popl(EAX); | 480 __ popl(EAX); |
| 478 __ popl(EAX); | 481 __ popl(EAX); |
| 479 __ popl(ECX); // Get return value into ECX, might be Closure object. | 482 __ popl(ECX); // Get return value into ECX, might be Closure object. |
| 480 | 483 |
| 481 // Pop preserved values. | 484 // Pop preserved values. |
| 482 __ popl(EDI); // Restore arguments descriptor array. | 485 __ popl(EDI); // Restore arguments descriptor array. |
| 483 __ popl(EDX); // Restore function name. | 486 __ popl(EDX); // Restore ic-data array. |
| 484 __ popl(EAX); // Restore receiver. | 487 __ popl(EAX); // Restore receiver. |
| 485 | 488 |
| 486 __ cmpl(ECX, raw_null); | 489 __ cmpl(ECX, raw_null); |
| 487 Label check_implicit_closure_through_getter; | 490 Label check_implicit_closure_through_getter; |
| 488 __ j(EQUAL, &check_implicit_closure_through_getter, Assembler::kNearJump); | 491 __ j(EQUAL, &check_implicit_closure_through_getter, Assembler::kNearJump); |
| 489 | 492 |
| 490 __ movl(EAX, ECX); // Return value is the closure object. | 493 __ movl(EAX, ECX); // Return value is the closure object. |
| 491 // Remove the stub frame as we are about return. | 494 // Remove the stub frame as we are about return. |
| 492 __ LeaveFrame(); | 495 __ LeaveFrame(); |
| 493 __ ret(); | 496 __ ret(); |
| 494 | 497 |
| 495 __ Bind(&check_implicit_closure_through_getter); | 498 __ Bind(&check_implicit_closure_through_getter); |
| 496 // EAX: receiver. | 499 // EAX: receiver. |
| 497 // EDX: function name. | 500 // EDX: ic-data array. |
| 498 // ECX: raw_null. | 501 // ECX: raw_null. |
| 499 // EDI: arguments descriptor array. | 502 // EDI: arguments descriptor array. |
| 500 // This is not the case of an instance so invoke the getter of the | 503 // This is not the case of an instance so invoke the getter of the |
| 501 // same name and see if we get a closure back which we are then | 504 // same name and see if we get a closure back which we are then |
| 502 // supposed to invoke. | 505 // supposed to invoke. |
| 503 // Push values that need to be preserved across runtime call. | 506 // Push values that need to be preserved across runtime call. |
| 504 __ pushl(EAX); // Preserve receiver. | 507 __ pushl(EAX); // Preserve receiver. |
| 505 __ pushl(EDX); // Preserve function name. | 508 __ pushl(EDX); // Preserve ic-data array. |
| 506 __ pushl(EDI); // Preserve arguments descriptor array. | 509 __ pushl(EDI); // Preserve arguments descriptor array. |
| 507 | 510 |
| 508 __ pushl(Immediate(0)); | 511 __ pushl(Immediate(0)); |
| 509 __ pushl(EAX); // Push receiver. | 512 __ pushl(EAX); // Push receiver. |
| 510 __ pushl(EDX); // Function name. | 513 __ pushl(EDX); // Ic-data array. |
| 511 __ CallRuntimeFromStub(kResolveImplicitClosureThroughGetterRuntimeEntry); | 514 __ CallRuntimeFromStub(kResolveImplicitClosureThroughGetterRuntimeEntry); |
| 512 __ popl(EDX); // Restore function name. | 515 __ popl(EDX); // Pop argument. |
| 513 __ popl(EAX); // Restore receiver. | 516 __ popl(EAX); // Pop argument. |
| 514 __ popl(ECX); // get return value into ECX, might be Closure object. | 517 __ popl(ECX); // get return value into ECX, might be Closure object. |
| 515 | 518 |
| 516 // Pop preserved values. | 519 // Pop preserved values. |
| 517 __ popl(EDI); // Restore arguments descriptor array. | 520 __ popl(EDI); // Restore arguments descriptor array. |
| 518 __ popl(EDX); // Restore function name. | 521 __ popl(EDX); // Restore ic-data array. |
| 519 __ popl(EAX); // Restore receiver. | 522 __ popl(EAX); // Restore receiver. |
| 520 | 523 |
| 521 __ cmpl(ECX, raw_null); | 524 __ cmpl(ECX, raw_null); |
| 522 Label function_not_found; | 525 Label function_not_found; |
| 523 __ j(EQUAL, &function_not_found, Assembler::kNearJump); | 526 __ j(EQUAL, &function_not_found, Assembler::kNearJump); |
| 524 | 527 |
| 525 // ECX: Closure object. | 528 // ECX: Closure object. |
| 526 // EDI: Arguments descriptor array. | 529 // EDI: Arguments descriptor array. |
| 527 __ pushl(Immediate(0)); // Result from invoking Closure. | 530 __ pushl(Immediate(0)); // Result from invoking Closure. |
| 528 __ pushl(ECX); // Closure object. | 531 __ pushl(ECX); // Closure object. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 549 __ popl(EAX); // Get result into EAX. | 552 __ popl(EAX); // Get result into EAX. |
| 550 | 553 |
| 551 // Remove the stub frame as we are about to return. | 554 // Remove the stub frame as we are about to return. |
| 552 __ LeaveFrame(); | 555 __ LeaveFrame(); |
| 553 __ ret(); | 556 __ ret(); |
| 554 | 557 |
| 555 __ Bind(&function_not_found); | 558 __ Bind(&function_not_found); |
| 556 // The target function was not found, so invoke method | 559 // The target function was not found, so invoke method |
| 557 // "void noSuchMethod(function_name, args_array)". | 560 // "void noSuchMethod(function_name, args_array)". |
| 558 // EAX: receiver. | 561 // EAX: receiver. |
| 559 // EDX: function name. | 562 // EDX: ic-data array. |
| 560 // ECX: raw_null. | 563 // ECX: raw_null. |
| 561 // EDI: argument descriptor array. | 564 // EDI: argument descriptor array. |
| 562 | 565 |
| 563 // Setup space for return value on stack by pushing smi 0. | 566 // Setup space for return value on stack by pushing smi 0. |
| 564 __ pushl(Immediate(0)); // Result from noSuchMethod. | 567 __ pushl(Immediate(0)); // Result from noSuchMethod. |
| 565 __ pushl(EAX); // Receiver. | 568 __ pushl(EAX); // Receiver. |
| 566 __ pushl(EDX); // Function name. | 569 __ pushl(EDX); // IC-data array. |
| 567 __ pushl(EDI); // Argument descriptor array. | 570 __ pushl(EDI); // Argument descriptor array. |
| 568 __ movl(EDI, FieldAddress(EDI, Array::data_offset())); | 571 __ movl(EDI, FieldAddress(EDI, Array::data_offset())); |
| 569 __ SmiUntag(EDI); | 572 __ SmiUntag(EDI); |
| 570 __ subl(EDI, Immediate(1)); // Arguments array length, minus the receiver. | 573 __ subl(EDI, Immediate(1)); // Arguments array length, minus the receiver. |
| 571 // See stack layout below explaining "wordSize * 6" offset. | 574 // See stack layout below explaining "wordSize * 6" offset. |
| 572 PushArgumentsArray(assembler, (kWordSize * 6)); | 575 PushArgumentsArray(assembler, (kWordSize * 6)); |
| 573 | 576 |
| 574 // Stack: | 577 // Stack: |
| 575 // TOS + 0: Argument array. | 578 // TOS + 0: Argument array. |
| 576 // TOS + 1: Argument descriptor array. | 579 // TOS + 1: Argument descriptor array. |
| 577 // TOS + 2: Function name. | 580 // TOS + 2: IC-data array. |
| 578 // TOS + 3: Receiver. | 581 // TOS + 3: Receiver. |
| 579 // TOS + 4: Place for result from noSuchMethod. | 582 // TOS + 4: Place for result from noSuchMethod. |
| 580 // TOS + 5: Saved EBP of previous frame. <== EBP | 583 // TOS + 5: Saved EBP of previous frame. <== EBP |
| 581 // TOS + 6: Dart code return address | 584 // TOS + 6: Dart code return address |
| 582 // TOS + 7: Last argument of caller. | 585 // TOS + 7: Last argument of caller. |
| 583 // .... | 586 // .... |
| 584 | 587 |
| 585 __ CallRuntimeFromStub(kInvokeNoSuchMethodFunctionRuntimeEntry); | 588 __ CallRuntimeFromStub(kInvokeNoSuchMethodFunctionRuntimeEntry); |
| 586 // Remove arguments. | 589 // Remove arguments. |
| 587 __ popl(EAX); | 590 __ popl(EAX); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 600 __ EnterFrame(0); | 603 __ EnterFrame(0); |
| 601 // Stack at this point: | 604 // Stack at this point: |
| 602 // TOS + 0: Saved EBP of previous frame. <== EBP | 605 // TOS + 0: Saved EBP of previous frame. <== EBP |
| 603 // TOS + 1: Dart code return address | 606 // TOS + 1: Dart code return address |
| 604 // TOS + 2: Last argument of caller. | 607 // TOS + 2: Last argument of caller. |
| 605 // .... | 608 // .... |
| 606 // Total number of args is the first Smi in args descriptor array (EDX). | 609 // Total number of args is the first Smi in args descriptor array (EDX). |
| 607 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); // EAX is a Smi. | 610 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); // EAX is a Smi. |
| 608 __ movl(EAX, Address(ESP, EAX, TIMES_2, kWordSize)); // Load receiver. | 611 __ movl(EAX, Address(ESP, EAX, TIMES_2, kWordSize)); // Load receiver. |
| 609 __ pushl(EDX); // Preserve arguments descriptor array. | 612 __ pushl(EDX); // Preserve arguments descriptor array. |
| 610 __ pushl(ECX); // Preserve function name. | 613 __ pushl(ECX); // Preserve ic-data array. |
| 611 __ pushl(EAX); // Push receiver. | 614 __ pushl(EAX); // Push receiver. |
| 612 __ CallRuntimeFromStub(kResolvePatchInstanceCallRuntimeEntry); | 615 __ CallRuntimeFromStub(kResolvePatchInstanceCallRuntimeEntry); |
| 613 __ popl(EAX); // Remove receiver pushed earlier. | 616 __ popl(EAX); // Remove receiver pushed earlier. |
| 614 // Pop preserved values | 617 // Pop preserved values |
| 615 __ popl(ECX); // Restore function name. | 618 __ popl(ECX); // Restore ic-data array. |
| 616 __ popl(EDX); // Restore arguments descriptor array. | 619 __ popl(EDX); // Restore arguments descriptor array. |
| 617 __ LeaveFrame(); | 620 __ LeaveFrame(); |
| 618 __ popl(EAX); | 621 __ popl(EAX); |
| 619 // Reexecute call. | 622 // Reexecute call. |
| 620 __ subl(EAX, Immediate(Assembler::kCallExternalLabelSize)); | 623 __ subl(EAX, Immediate(Assembler::kCallExternalLabelSize)); |
| 621 __ jmp(EAX); | 624 __ jmp(EAX); |
| 622 } | 625 } |
| 623 | 626 |
| 624 | 627 |
| 625 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { | 628 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { |
| (...skipping 763 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1389 } | 1392 } |
| 1390 | 1393 |
| 1391 | 1394 |
| 1392 // Called for invoking noSuchMethod function from the entry code of a dart | 1395 // Called for invoking noSuchMethod function from the entry code of a dart |
| 1393 // function after an error in passed named arguments is detected. | 1396 // function after an error in passed named arguments is detected. |
| 1394 // Input parameters: | 1397 // Input parameters: |
| 1395 // EBP : points to previous frame pointer. | 1398 // EBP : points to previous frame pointer. |
| 1396 // EBP + 4 : points to return address. | 1399 // EBP + 4 : points to return address. |
| 1397 // EBP + 8 : address of last argument (arg n-1). | 1400 // EBP + 8 : address of last argument (arg n-1). |
| 1398 // EBP + 8 + 4*(n-1) : address of first argument (arg 0). | 1401 // EBP + 8 + 4*(n-1) : address of first argument (arg 0). |
| 1399 // ECX : function name. | 1402 // ECX : ic-data array. |
| 1400 // EDX : arguments descriptor array. | 1403 // EDX : arguments descriptor array. |
| 1401 // Uses EAX, EBX, EDI as temporary registers. | 1404 // Uses EAX, EBX, EDI as temporary registers. |
| 1402 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { | 1405 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { |
| 1403 // The target function was not found, so invoke method | 1406 // The target function was not found, so invoke method |
| 1404 // "void noSuchMethod(function_name, Array arguments)". | 1407 // "void noSuchMethod(function_name, Array arguments)". |
| 1405 // TODO(regis): For now, we simply pass the actual arguments, both positional | 1408 // TODO(regis): For now, we simply pass the actual arguments, both positional |
| 1406 // and named, as the argument array. This is not correct if out-of-order | 1409 // and named, as the argument array. This is not correct if out-of-order |
| 1407 // named arguments were passed. | 1410 // named arguments were passed. |
| 1408 // The signature of the "noSuchMethod" method has to change from | 1411 // The signature of the "noSuchMethod" method has to change from |
| 1409 // noSuchMethod(String name, Array arguments) to something like | 1412 // noSuchMethod(String name, Array arguments) to something like |
| 1410 // noSuchMethod(InvocationMirror call). | 1413 // noSuchMethod(InvocationMirror call). |
| 1411 // Also, the class NoSuchMethodException has to be modified accordingly. | 1414 // Also, the class NoSuchMethodException has to be modified accordingly. |
| 1412 // Total number of args is the first Smi in args descriptor array (EDX). | 1415 // Total number of args is the first Smi in args descriptor array (EDX). |
| 1413 __ movl(EDI, FieldAddress(EDX, Array::data_offset())); | 1416 __ movl(EDI, FieldAddress(EDX, Array::data_offset())); |
| 1414 __ SmiUntag(EDI); | 1417 __ SmiUntag(EDI); |
| 1415 __ movl(EAX, Address(EBP, EDI, TIMES_4, kWordSize)); // Get receiver. | 1418 __ movl(EAX, Address(EBP, EDI, TIMES_4, kWordSize)); // Get receiver. |
| 1416 | 1419 |
| 1417 __ EnterFrame(0); | 1420 __ EnterFrame(0); |
| 1418 // Setup space for return value on stack by pushing smi 0. | 1421 // Setup space for return value on stack by pushing smi 0. |
| 1419 __ pushl(Immediate(0)); // Result from noSuchMethod. | 1422 __ pushl(Immediate(0)); // Result from noSuchMethod. |
| 1420 __ pushl(EAX); // Receiver. | 1423 __ pushl(EAX); // Receiver. |
| 1421 __ pushl(ECX); // Function name. | 1424 __ pushl(ECX); // IC data array. |
| 1422 __ pushl(EDX); // Arguments descriptor array. | 1425 __ pushl(EDX); // Arguments descriptor array. |
| 1423 __ subl(EDI, Immediate(1)); // Arguments array length, minus the receiver. | 1426 __ subl(EDI, Immediate(1)); // Arguments array length, minus the receiver. |
| 1424 // See stack layout below explaining "wordSize * 8" offset. | 1427 // See stack layout below explaining "wordSize * 8" offset. |
| 1425 PushArgumentsArray(assembler, (kWordSize * 8)); | 1428 PushArgumentsArray(assembler, (kWordSize * 8)); |
| 1426 | 1429 |
| 1427 // Stack: | 1430 // Stack: |
| 1428 // TOS + 0: Argument array. | 1431 // TOS + 0: Argument array. |
| 1429 // TOS + 1: Arguments descriptor array. | 1432 // TOS + 1: Arguments descriptor array. |
| 1430 // TOS + 2: Function name. | 1433 // TOS + 2: Ic-data array. |
| 1431 // TOS + 3: Receiver. | 1434 // TOS + 3: Receiver. |
| 1432 // TOS + 4: Place for result from noSuchMethod. | 1435 // TOS + 4: Place for result from noSuchMethod. |
| 1433 // TOS + 5: Saved EBP of previous frame. <== EBP | 1436 // TOS + 5: Saved EBP of previous frame. <== EBP |
| 1434 // TOS + 6: Dart callee (or stub) code return address | 1437 // TOS + 6: Dart callee (or stub) code return address |
| 1435 // TOS + 7: Saved EBP of dart caller frame. | 1438 // TOS + 7: Saved EBP of dart caller frame. |
| 1436 // TOS + 8: Dart caller code return address | 1439 // TOS + 8: Dart caller code return address |
| 1437 // TOS + 9: Last argument of caller. | 1440 // TOS + 9: Last argument of caller. |
| 1438 // .... | 1441 // .... |
| 1439 __ CallRuntimeFromStub(kInvokeNoSuchMethodFunctionRuntimeEntry); | 1442 __ CallRuntimeFromStub(kInvokeNoSuchMethodFunctionRuntimeEntry); |
| 1440 // Remove arguments. | 1443 // Remove arguments. |
| 1441 __ popl(EAX); | 1444 __ popl(EAX); |
| 1442 __ popl(EAX); | 1445 __ popl(EAX); |
| 1443 __ popl(EAX); | 1446 __ popl(EAX); |
| 1444 __ popl(EAX); | 1447 __ popl(EAX); |
| 1445 __ popl(EAX); // Get result into EAX. | 1448 __ popl(EAX); // Get result into EAX. |
| 1446 | 1449 |
| 1447 // Remove the stub frame as we are about to return. | 1450 // Remove the stub frame as we are about to return. |
| 1448 __ LeaveFrame(); | 1451 __ LeaveFrame(); |
| 1449 __ ret(); | 1452 __ ret(); |
| 1450 } | 1453 } |
| 1451 | 1454 |
| 1452 } // namespace dart | 1455 } // namespace dart |
| 1453 | 1456 |
| 1454 #endif // defined TARGET_ARCH_IA32 | 1457 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |