OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
451 // ----------------------------------- | 451 // ----------------------------------- |
452 __ pop(scratch); | 452 __ pop(scratch); |
453 __ add(esp, Immediate(kPointerSize * kFastApiCallArguments)); | 453 __ add(esp, Immediate(kPointerSize * kFastApiCallArguments)); |
454 __ push(scratch); | 454 __ push(scratch); |
455 } | 455 } |
456 | 456 |
457 | 457 |
458 // Generates call to API function. | 458 // Generates call to API function. |
459 static void GenerateFastApiCall(MacroAssembler* masm, | 459 static void GenerateFastApiCall(MacroAssembler* masm, |
460 const CallOptimization& optimization, | 460 const CallOptimization& optimization, |
461 int argc) { | 461 int argc, |
462 bool restore_context) { | |
462 // ----------- S t a t e ------------- | 463 // ----------- S t a t e ------------- |
463 // -- esp[0] : return address | 464 // -- esp[0] : return address |
464 // -- esp[4] : object passing the type check | 465 // -- esp[4] : context |
466 // -- esp[8] : object passing the type check | |
465 // (last fast api call extra argument, | 467 // (last fast api call extra argument, |
466 // set by CheckPrototypes) | 468 // set by CheckPrototypes) |
467 // -- esp[8] : api function | 469 // -- esp[12] : api function |
468 // (first fast api call extra argument) | 470 // (first fast api call extra argument) |
469 // -- esp[12] : api call data | 471 // -- esp[16] : api call data |
470 // -- esp[16] : isolate | 472 // -- esp[20] : isolate |
471 // -- esp[20] : ReturnValue default value | 473 // -- esp[24] : ReturnValue default value |
472 // -- esp[24] : ReturnValue | 474 // -- esp[28] : ReturnValue |
473 // -- esp[28] : last argument | 475 // -- esp[32] : last argument |
474 // -- ... | 476 // -- ... |
475 // -- esp[(argc + 6) * 4] : first argument | 477 // -- esp[(argc + 7) * 4] : first argument |
476 // -- esp[(argc + 7) * 4] : receiver | 478 // -- esp[(argc + 8) * 4] : receiver |
477 // ----------------------------------- | 479 // ----------------------------------- |
480 | |
481 // Save calling context. | |
482 __ mov(Operand(esp, kPointerSize), esi); | |
483 | |
478 // Get the function and setup the context. | 484 // Get the function and setup the context. |
479 Handle<JSFunction> function = optimization.constant_function(); | 485 Handle<JSFunction> function = optimization.constant_function(); |
480 __ LoadHeapObject(edi, function); | 486 __ LoadHeapObject(edi, function); |
481 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 487 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
482 | 488 |
483 // Pass the additional arguments. | 489 // Pass the additional arguments. |
484 __ mov(Operand(esp, 2 * kPointerSize), edi); | 490 __ mov(Operand(esp, 3 * kPointerSize), edi); |
485 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); | 491 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); |
486 Handle<Object> call_data(api_call_info->data(), masm->isolate()); | 492 Handle<Object> call_data(api_call_info->data(), masm->isolate()); |
487 if (masm->isolate()->heap()->InNewSpace(*call_data)) { | 493 if (masm->isolate()->heap()->InNewSpace(*call_data)) { |
488 __ mov(ecx, api_call_info); | 494 __ mov(ecx, api_call_info); |
489 __ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kDataOffset)); | 495 __ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kDataOffset)); |
490 __ mov(Operand(esp, 3 * kPointerSize), ebx); | 496 __ mov(Operand(esp, 4 * kPointerSize), ebx); |
491 } else { | 497 } else { |
492 __ mov(Operand(esp, 3 * kPointerSize), Immediate(call_data)); | 498 __ mov(Operand(esp, 4 * kPointerSize), Immediate(call_data)); |
493 } | 499 } |
494 __ mov(Operand(esp, 4 * kPointerSize), | 500 __ mov(Operand(esp, 5 * kPointerSize), |
495 Immediate(reinterpret_cast<int>(masm->isolate()))); | 501 Immediate(reinterpret_cast<int>(masm->isolate()))); |
496 __ mov(Operand(esp, 5 * kPointerSize), | 502 __ mov(Operand(esp, 6 * kPointerSize), |
497 masm->isolate()->factory()->undefined_value()); | 503 masm->isolate()->factory()->undefined_value()); |
498 __ mov(Operand(esp, 6 * kPointerSize), | 504 __ mov(Operand(esp, 7 * kPointerSize), |
499 masm->isolate()->factory()->undefined_value()); | 505 masm->isolate()->factory()->undefined_value()); |
500 | 506 |
501 // Prepare arguments. | 507 // Prepare arguments. |
502 STATIC_ASSERT(kFastApiCallArguments == 6); | 508 STATIC_ASSERT(kFastApiCallArguments == 7); |
503 __ lea(eax, Operand(esp, kFastApiCallArguments * kPointerSize)); | 509 __ lea(eax, Operand(esp, kFastApiCallArguments * kPointerSize)); |
504 | 510 |
505 | 511 |
506 // API function gets reference to the v8::Arguments. If CPU profiler | 512 // API function gets reference to the v8::Arguments. If CPU profiler |
507 // is enabled wrapper function will be called and we need to pass | 513 // is enabled wrapper function will be called and we need to pass |
508 // address of the callback as additional parameter, always allocate | 514 // address of the callback as additional parameter, always allocate |
509 // space for it. | 515 // space for it. |
510 const int kApiArgc = 1 + 1; | 516 const int kApiArgc = 1 + 1; |
511 | 517 |
512 // Allocate the v8::Arguments structure in the arguments' space since | 518 // Allocate the v8::Arguments structure in the arguments' space since |
(...skipping 13 matching lines...) Expand all Loading... | |
526 __ Set(ApiParameterOperand(4), Immediate(argc)); | 532 __ Set(ApiParameterOperand(4), Immediate(argc)); |
527 // v8::Arguments::is_construct_call_. | 533 // v8::Arguments::is_construct_call_. |
528 __ Set(ApiParameterOperand(5), Immediate(0)); | 534 __ Set(ApiParameterOperand(5), Immediate(0)); |
529 | 535 |
530 // v8::InvocationCallback's argument. | 536 // v8::InvocationCallback's argument. |
531 __ lea(eax, ApiParameterOperand(2)); | 537 __ lea(eax, ApiParameterOperand(2)); |
532 __ mov(ApiParameterOperand(0), eax); | 538 __ mov(ApiParameterOperand(0), eax); |
533 | 539 |
534 Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback); | 540 Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback); |
535 | 541 |
542 Operand context_restore_operand(ebp, 2 * kPointerSize); | |
543 Operand return_value_operand( | |
544 ebp, (kFastApiCallArguments + 1) * kPointerSize); | |
Michael Starzinger
2013/09/16 15:08:51
nit: Indentation is off.
| |
536 __ CallApiFunctionAndReturn(function_address, | 545 __ CallApiFunctionAndReturn(function_address, |
537 thunk_address, | 546 thunk_address, |
538 ApiParameterOperand(1), | 547 ApiParameterOperand(1), |
539 argc + kFastApiCallArguments + 1, | 548 argc + kFastApiCallArguments + 1, |
540 kFastApiCallArguments + 1); | 549 return_value_operand, |
550 restore_context ? | |
551 &context_restore_operand : NULL); | |
541 } | 552 } |
542 | 553 |
543 | 554 |
544 // Generate call to api function. | 555 // Generate call to api function. |
545 static void GenerateFastApiCall(MacroAssembler* masm, | 556 static void GenerateFastApiCall(MacroAssembler* masm, |
546 const CallOptimization& optimization, | 557 const CallOptimization& optimization, |
547 Register receiver, | 558 Register receiver, |
548 Register scratch, | 559 Register scratch, |
549 int argc, | 560 int argc, |
550 Register* values) { | 561 Register* values) { |
551 ASSERT(optimization.is_simple_api_call()); | 562 ASSERT(optimization.is_simple_api_call()); |
552 ASSERT(!receiver.is(scratch)); | 563 ASSERT(!receiver.is(scratch)); |
553 | 564 |
554 const int stack_space = kFastApiCallArguments + argc + 1; | 565 const int stack_space = kFastApiCallArguments + argc + 1; |
566 const int kHolderIndex = kFastApiCallArguments + | |
567 FunctionCallbackArguments::kHolderIndex; | |
555 // Copy return value. | 568 // Copy return value. |
556 __ mov(scratch, Operand(esp, 0)); | 569 __ mov(scratch, Operand(esp, 0)); |
557 // Assign stack space for the call arguments. | 570 // Assign stack space for the call arguments. |
558 __ sub(esp, Immediate(stack_space * kPointerSize)); | 571 __ sub(esp, Immediate(stack_space * kPointerSize)); |
559 // Move the return address on top of the stack. | 572 // Move the return address on top of the stack. |
560 __ mov(Operand(esp, 0), scratch); | 573 __ mov(Operand(esp, 0), scratch); |
561 // Write holder to stack frame. | 574 // Write holder to stack frame. |
562 __ mov(Operand(esp, 1 * kPointerSize), receiver); | 575 __ mov(Operand(esp, kHolderIndex * kPointerSize), receiver); |
563 // Write receiver to stack frame. | 576 // Write receiver to stack frame. |
564 int index = stack_space; | 577 int index = stack_space; |
565 __ mov(Operand(esp, index-- * kPointerSize), receiver); | 578 __ mov(Operand(esp, index-- * kPointerSize), receiver); |
566 // Write the arguments to stack frame. | 579 // Write the arguments to stack frame. |
567 for (int i = 0; i < argc; i++) { | 580 for (int i = 0; i < argc; i++) { |
568 ASSERT(!receiver.is(values[i])); | 581 ASSERT(!receiver.is(values[i])); |
569 ASSERT(!scratch.is(values[i])); | 582 ASSERT(!scratch.is(values[i])); |
570 __ mov(Operand(esp, index-- * kPointerSize), values[i]); | 583 __ mov(Operand(esp, index-- * kPointerSize), values[i]); |
571 } | 584 } |
572 | 585 |
573 GenerateFastApiCall(masm, optimization, argc); | 586 GenerateFastApiCall(masm, optimization, argc, true); |
574 } | 587 } |
575 | 588 |
576 | 589 |
577 class CallInterceptorCompiler BASE_EMBEDDED { | 590 class CallInterceptorCompiler BASE_EMBEDDED { |
578 public: | 591 public: |
579 CallInterceptorCompiler(StubCompiler* stub_compiler, | 592 CallInterceptorCompiler(StubCompiler* stub_compiler, |
580 const ParameterCount& arguments, | 593 const ParameterCount& arguments, |
581 Register name, | 594 Register name, |
582 Code::ExtraICState extra_state) | 595 Code::ExtraICState extra_state) |
583 : stub_compiler_(stub_compiler), | 596 : stub_compiler_(stub_compiler), |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
677 } else { | 690 } else { |
678 // CheckPrototypes has a side effect of fetching a 'holder' | 691 // CheckPrototypes has a side effect of fetching a 'holder' |
679 // for API (object which is instanceof for the signature). It's | 692 // for API (object which is instanceof for the signature). It's |
680 // safe to omit it here, as if present, it should be fetched | 693 // safe to omit it here, as if present, it should be fetched |
681 // by the previous CheckPrototypes. | 694 // by the previous CheckPrototypes. |
682 ASSERT(depth2 == kInvalidProtoDepth); | 695 ASSERT(depth2 == kInvalidProtoDepth); |
683 } | 696 } |
684 | 697 |
685 // Invoke function. | 698 // Invoke function. |
686 if (can_do_fast_api_call) { | 699 if (can_do_fast_api_call) { |
687 GenerateFastApiCall(masm, optimization, arguments_.immediate()); | 700 GenerateFastApiCall(masm, optimization, arguments_.immediate(), false); |
688 } else { | 701 } else { |
689 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 702 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
690 ? CALL_AS_FUNCTION | 703 ? CALL_AS_FUNCTION |
691 : CALL_AS_METHOD; | 704 : CALL_AS_METHOD; |
692 Handle<JSFunction> function = optimization.constant_function(); | 705 Handle<JSFunction> function = optimization.constant_function(); |
693 ParameterCount expected(function); | 706 ParameterCount expected(function); |
694 __ InvokeFunction(function, expected, arguments_, | 707 __ InvokeFunction(function, expected, arguments_, |
695 JUMP_FUNCTION, NullCallWrapper(), call_kind); | 708 JUMP_FUNCTION, NullCallWrapper(), call_kind); |
696 } | 709 } |
697 | 710 |
(...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1149 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, | 1162 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, |
1150 Register object_reg, | 1163 Register object_reg, |
1151 Handle<JSObject> holder, | 1164 Handle<JSObject> holder, |
1152 Register holder_reg, | 1165 Register holder_reg, |
1153 Register scratch1, | 1166 Register scratch1, |
1154 Register scratch2, | 1167 Register scratch2, |
1155 Handle<Name> name, | 1168 Handle<Name> name, |
1156 int save_at_depth, | 1169 int save_at_depth, |
1157 Label* miss, | 1170 Label* miss, |
1158 PrototypeCheckType check) { | 1171 PrototypeCheckType check) { |
1172 const int kHolderIndex = kFastApiCallArguments + | |
1173 FunctionCallbackArguments::kHolderIndex; | |
1159 // Make sure that the type feedback oracle harvests the receiver map. | 1174 // Make sure that the type feedback oracle harvests the receiver map. |
1160 // TODO(svenpanne) Remove this hack when all ICs are reworked. | 1175 // TODO(svenpanne) Remove this hack when all ICs are reworked. |
1161 __ mov(scratch1, Handle<Map>(object->map())); | 1176 __ mov(scratch1, Handle<Map>(object->map())); |
1162 | 1177 |
1163 Handle<JSObject> first = object; | 1178 Handle<JSObject> first = object; |
1164 // Make sure there's no overlap between holder and object registers. | 1179 // Make sure there's no overlap between holder and object registers. |
1165 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 1180 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
1166 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 1181 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
1167 && !scratch2.is(scratch1)); | 1182 && !scratch2.is(scratch1)); |
1168 | 1183 |
1169 // Keep track of the current object in register reg. | 1184 // Keep track of the current object in register reg. |
1170 Register reg = object_reg; | 1185 Register reg = object_reg; |
1171 Handle<JSObject> current = object; | 1186 Handle<JSObject> current = object; |
1172 int depth = 0; | 1187 int depth = 0; |
1173 | 1188 |
1174 if (save_at_depth == depth) { | 1189 if (save_at_depth == depth) { |
1175 __ mov(Operand(esp, kPointerSize), reg); | 1190 __ mov(Operand(esp, kHolderIndex * kPointerSize), reg); |
1176 } | 1191 } |
1177 | 1192 |
1178 // Traverse the prototype chain and check the maps in the prototype chain for | 1193 // Traverse the prototype chain and check the maps in the prototype chain for |
1179 // fast and global objects or do negative lookup for normal objects. | 1194 // fast and global objects or do negative lookup for normal objects. |
1180 while (!current.is_identical_to(holder)) { | 1195 while (!current.is_identical_to(holder)) { |
1181 ++depth; | 1196 ++depth; |
1182 | 1197 |
1183 // Only global objects and objects that do not require access | 1198 // Only global objects and objects that do not require access |
1184 // checks are allowed in stubs. | 1199 // checks are allowed in stubs. |
1185 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); | 1200 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1226 // The prototype is in new space; we cannot store a reference to it | 1241 // The prototype is in new space; we cannot store a reference to it |
1227 // in the code. Load it from the map. | 1242 // in the code. Load it from the map. |
1228 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 1243 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
1229 } else { | 1244 } else { |
1230 // The prototype is in old space; load it directly. | 1245 // The prototype is in old space; load it directly. |
1231 __ mov(reg, prototype); | 1246 __ mov(reg, prototype); |
1232 } | 1247 } |
1233 } | 1248 } |
1234 | 1249 |
1235 if (save_at_depth == depth) { | 1250 if (save_at_depth == depth) { |
1236 __ mov(Operand(esp, kPointerSize), reg); | 1251 __ mov(Operand(esp, kHolderIndex * kPointerSize), reg); |
1237 } | 1252 } |
1238 | 1253 |
1239 // Go to the next object in the prototype chain. | 1254 // Go to the next object in the prototype chain. |
1240 current = prototype; | 1255 current = prototype; |
1241 } | 1256 } |
1242 ASSERT(current.is_identical_to(holder)); | 1257 ASSERT(current.is_identical_to(holder)); |
1243 | 1258 |
1244 // Log the check depth. | 1259 // Log the check depth. |
1245 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 1260 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
1246 | 1261 |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1449 // already generated). Do not allow the assembler to perform a | 1464 // already generated). Do not allow the assembler to perform a |
1450 // garbage collection but instead return the allocation failure | 1465 // garbage collection but instead return the allocation failure |
1451 // object. | 1466 // object. |
1452 | 1467 |
1453 Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback); | 1468 Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback); |
1454 | 1469 |
1455 __ CallApiFunctionAndReturn(getter_address, | 1470 __ CallApiFunctionAndReturn(getter_address, |
1456 thunk_address, | 1471 thunk_address, |
1457 ApiParameterOperand(2), | 1472 ApiParameterOperand(2), |
1458 kStackSpace, | 1473 kStackSpace, |
1459 7); | 1474 Operand(ebp, 7 * kPointerSize), |
1475 NULL); | |
1460 } | 1476 } |
1461 | 1477 |
1462 | 1478 |
1463 void BaseLoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { | 1479 void BaseLoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { |
1464 // Return the constant value. | 1480 // Return the constant value. |
1465 __ LoadObject(eax, value); | 1481 __ LoadObject(eax, value); |
1466 __ ret(0); | 1482 __ ret(0); |
1467 } | 1483 } |
1468 | 1484 |
1469 | 1485 |
(...skipping 1142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2612 // Check that the maps haven't changed and find a Holder as a side effect. | 2628 // Check that the maps haven't changed and find a Holder as a side effect. |
2613 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, | 2629 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, |
2614 name, depth, &miss); | 2630 name, depth, &miss); |
2615 | 2631 |
2616 // Move the return address on top of the stack. | 2632 // Move the return address on top of the stack. |
2617 __ mov(eax, Operand(esp, kFastApiCallArguments * kPointerSize)); | 2633 __ mov(eax, Operand(esp, kFastApiCallArguments * kPointerSize)); |
2618 __ mov(Operand(esp, 0 * kPointerSize), eax); | 2634 __ mov(Operand(esp, 0 * kPointerSize), eax); |
2619 | 2635 |
2620 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains | 2636 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains |
2621 // duplicate of return address and will be overwritten. | 2637 // duplicate of return address and will be overwritten. |
2622 GenerateFastApiCall(masm(), optimization, argc); | 2638 GenerateFastApiCall(masm(), optimization, argc, false); |
2623 | 2639 |
2624 __ bind(&miss); | 2640 __ bind(&miss); |
2625 __ add(esp, Immediate(kFastApiCallArguments * kPointerSize)); | 2641 __ add(esp, Immediate(kFastApiCallArguments * kPointerSize)); |
2626 | 2642 |
2627 __ bind(&miss_before_stack_reserved); | 2643 __ bind(&miss_before_stack_reserved); |
2628 GenerateMissBranch(); | 2644 GenerateMissBranch(); |
2629 | 2645 |
2630 // Return the generated code. | 2646 // Return the generated code. |
2631 return GetCode(function); | 2647 return GetCode(function); |
2632 } | 2648 } |
(...skipping 631 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3264 // ----------------------------------- | 3280 // ----------------------------------- |
3265 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); | 3281 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); |
3266 } | 3282 } |
3267 | 3283 |
3268 | 3284 |
3269 #undef __ | 3285 #undef __ |
3270 | 3286 |
3271 } } // namespace v8::internal | 3287 } } // namespace v8::internal |
3272 | 3288 |
3273 #endif // V8_TARGET_ARCH_IA32 | 3289 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |