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 388 matching lines...) Loading... |
399 Handle<JSObject> holder_obj) { | 399 Handle<JSObject> holder_obj) { |
400 __ push(name); | 400 __ push(name); |
401 Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); | 401 Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); |
402 ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor)); | 402 ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor)); |
403 Register scratch = name; | 403 Register scratch = name; |
404 __ mov(scratch, Immediate(interceptor)); | 404 __ mov(scratch, Immediate(interceptor)); |
405 __ push(scratch); | 405 __ push(scratch); |
406 __ push(receiver); | 406 __ push(receiver); |
407 __ push(holder); | 407 __ push(holder); |
408 __ push(FieldOperand(scratch, InterceptorInfo::kDataOffset)); | 408 __ push(FieldOperand(scratch, InterceptorInfo::kDataOffset)); |
| 409 __ push(Immediate(reinterpret_cast<int>(masm->isolate()))); |
409 } | 410 } |
410 | 411 |
411 | 412 |
412 static void CompileCallLoadPropertyWithInterceptor( | 413 static void CompileCallLoadPropertyWithInterceptor( |
413 MacroAssembler* masm, | 414 MacroAssembler* masm, |
414 Register receiver, | 415 Register receiver, |
415 Register holder, | 416 Register holder, |
416 Register name, | 417 Register name, |
417 Handle<JSObject> holder_obj) { | 418 Handle<JSObject> holder_obj) { |
418 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); | 419 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); |
419 __ CallExternalReference( | 420 __ CallExternalReference( |
420 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly), | 421 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly), |
421 masm->isolate()), | 422 masm->isolate()), |
422 5); | 423 6); |
423 } | 424 } |
424 | 425 |
425 | 426 |
426 // Number of pointers to be reserved on stack for fast API call. | 427 // Number of pointers to be reserved on stack for fast API call. |
427 static const int kFastApiCallArguments = 3; | 428 static const int kFastApiCallArguments = 4; |
428 | 429 |
429 | 430 |
430 // Reserves space for the extra arguments to API function in the | 431 // Reserves space for the extra arguments to API function in the |
431 // caller's frame. | 432 // caller's frame. |
432 // | 433 // |
433 // These arguments are set by CheckPrototypes and GenerateFastApiCall. | 434 // These arguments are set by CheckPrototypes and GenerateFastApiCall. |
434 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) { | 435 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) { |
435 // ----------- S t a t e ------------- | 436 // ----------- S t a t e ------------- |
436 // -- esp[0] : return address | 437 // -- esp[0] : return address |
437 // -- esp[4] : last argument in the internal frame of the caller | 438 // -- esp[4] : last argument in the internal frame of the caller |
(...skipping 27 matching lines...) Loading... |
465 const CallOptimization& optimization, | 466 const CallOptimization& optimization, |
466 int argc) { | 467 int argc) { |
467 // ----------- S t a t e ------------- | 468 // ----------- S t a t e ------------- |
468 // -- esp[0] : return address | 469 // -- esp[0] : return address |
469 // -- esp[4] : object passing the type check | 470 // -- esp[4] : object passing the type check |
470 // (last fast api call extra argument, | 471 // (last fast api call extra argument, |
471 // set by CheckPrototypes) | 472 // set by CheckPrototypes) |
472 // -- esp[8] : api function | 473 // -- esp[8] : api function |
473 // (first fast api call extra argument) | 474 // (first fast api call extra argument) |
474 // -- esp[12] : api call data | 475 // -- esp[12] : api call data |
475 // -- esp[16] : last argument | 476 // -- esp[16] : isolate |
| 477 // -- esp[20] : last argument |
476 // -- ... | 478 // -- ... |
477 // -- esp[(argc + 3) * 4] : first argument | 479 // -- esp[(argc + 4) * 4] : first argument |
478 // -- esp[(argc + 4) * 4] : receiver | 480 // -- esp[(argc + 5) * 4] : receiver |
479 // ----------------------------------- | 481 // ----------------------------------- |
480 // Get the function and setup the context. | 482 // Get the function and setup the context. |
481 Handle<JSFunction> function = optimization.constant_function(); | 483 Handle<JSFunction> function = optimization.constant_function(); |
482 __ LoadHeapObject(edi, function); | 484 __ LoadHeapObject(edi, function); |
483 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 485 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
484 | 486 |
485 // Pass the additional arguments. | 487 // Pass the additional arguments. |
486 __ mov(Operand(esp, 2 * kPointerSize), edi); | 488 __ mov(Operand(esp, 2 * kPointerSize), edi); |
487 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); | 489 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); |
488 Handle<Object> call_data(api_call_info->data()); | 490 Handle<Object> call_data(api_call_info->data()); |
489 if (masm->isolate()->heap()->InNewSpace(*call_data)) { | 491 if (masm->isolate()->heap()->InNewSpace(*call_data)) { |
490 __ mov(ecx, api_call_info); | 492 __ mov(ecx, api_call_info); |
491 __ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kDataOffset)); | 493 __ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kDataOffset)); |
492 __ mov(Operand(esp, 3 * kPointerSize), ebx); | 494 __ mov(Operand(esp, 3 * kPointerSize), ebx); |
493 } else { | 495 } else { |
494 __ mov(Operand(esp, 3 * kPointerSize), Immediate(call_data)); | 496 __ mov(Operand(esp, 3 * kPointerSize), Immediate(call_data)); |
495 } | 497 } |
| 498 __ mov(Operand(esp, 4 * kPointerSize), |
| 499 Immediate(reinterpret_cast<int>(masm->isolate()))); |
496 | 500 |
497 // Prepare arguments. | 501 // Prepare arguments. |
498 __ lea(eax, Operand(esp, 3 * kPointerSize)); | 502 __ lea(eax, Operand(esp, 4 * kPointerSize)); |
499 | 503 |
500 const int kApiArgc = 1; // API function gets reference to the v8::Arguments. | 504 const int kApiArgc = 1; // API function gets reference to the v8::Arguments. |
501 | 505 |
502 // Allocate the v8::Arguments structure in the arguments' space since | 506 // Allocate the v8::Arguments structure in the arguments' space since |
503 // it's not controlled by GC. | 507 // it's not controlled by GC. |
504 const int kApiStackSpace = 4; | 508 const int kApiStackSpace = 4; |
505 | 509 |
506 __ PrepareCallApiFunction(kApiArgc + kApiStackSpace); | 510 __ PrepareCallApiFunction(kApiArgc + kApiStackSpace); |
507 | 511 |
508 __ mov(ApiParameterOperand(1), eax); // v8::Arguments::implicit_args_. | 512 __ mov(ApiParameterOperand(1), eax); // v8::Arguments::implicit_args_. |
(...skipping 163 matching lines...) Loading... |
672 | 676 |
673 FrameScope scope(masm, StackFrame::INTERNAL); | 677 FrameScope scope(masm, StackFrame::INTERNAL); |
674 // Save the name_ register across the call. | 678 // Save the name_ register across the call. |
675 __ push(name_); | 679 __ push(name_); |
676 | 680 |
677 PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder); | 681 PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder); |
678 | 682 |
679 __ CallExternalReference( | 683 __ CallExternalReference( |
680 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall), | 684 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall), |
681 masm->isolate()), | 685 masm->isolate()), |
682 5); | 686 6); |
683 | 687 |
684 // Restore the name_ register. | 688 // Restore the name_ register. |
685 __ pop(name_); | 689 __ pop(name_); |
686 | 690 |
687 // Leave the internal frame. | 691 // Leave the internal frame. |
688 } | 692 } |
689 | 693 |
690 void LoadWithInterceptor(MacroAssembler* masm, | 694 void LoadWithInterceptor(MacroAssembler* masm, |
691 Register receiver, | 695 Register receiver, |
692 Register holder, | 696 Register holder, |
(...skipping 332 matching lines...) Loading... |
1025 __ mov(scratch2, esp); | 1029 __ mov(scratch2, esp); |
1026 ASSERT(!scratch2.is(reg)); | 1030 ASSERT(!scratch2.is(reg)); |
1027 __ push(reg); // holder | 1031 __ push(reg); // holder |
1028 // Push data from AccessorInfo. | 1032 // Push data from AccessorInfo. |
1029 if (isolate()->heap()->InNewSpace(callback->data())) { | 1033 if (isolate()->heap()->InNewSpace(callback->data())) { |
1030 __ mov(scratch1, Immediate(callback)); | 1034 __ mov(scratch1, Immediate(callback)); |
1031 __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset)); | 1035 __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset)); |
1032 } else { | 1036 } else { |
1033 __ push(Immediate(Handle<Object>(callback->data()))); | 1037 __ push(Immediate(Handle<Object>(callback->data()))); |
1034 } | 1038 } |
| 1039 __ push(Immediate(reinterpret_cast<int>(isolate()))); |
1035 | 1040 |
1036 // Save a pointer to where we pushed the arguments pointer. | 1041 // Save a pointer to where we pushed the arguments pointer. |
1037 // This will be passed as the const AccessorInfo& to the C++ callback. | 1042 // This will be passed as the const AccessorInfo& to the C++ callback. |
1038 __ push(scratch2); | 1043 __ push(scratch2); |
1039 | 1044 |
1040 __ push(name_reg); // name | 1045 __ push(name_reg); // name |
1041 __ mov(ebx, esp); // esp points to reference to name (handler). | 1046 __ mov(ebx, esp); // esp points to reference to name (handler). |
1042 | 1047 |
1043 __ push(scratch3); // Restore return address. | 1048 __ push(scratch3); // Restore return address. |
1044 | 1049 |
1045 // 3 elements array for v8::Arguments::values_, handler for name and pointer | 1050 // 4 elements array for v8::Arguments::values_, handler for name and pointer |
1046 // to the values (it considered as smi in GC). | 1051 // to the values (it considered as smi in GC). |
1047 const int kStackSpace = 5; | 1052 const int kStackSpace = 6; |
1048 const int kApiArgc = 2; | 1053 const int kApiArgc = 2; |
1049 | 1054 |
1050 __ PrepareCallApiFunction(kApiArgc); | 1055 __ PrepareCallApiFunction(kApiArgc); |
1051 __ mov(ApiParameterOperand(0), ebx); // name. | 1056 __ mov(ApiParameterOperand(0), ebx); // name. |
1052 __ add(ebx, Immediate(kPointerSize)); | 1057 __ add(ebx, Immediate(kPointerSize)); |
1053 __ mov(ApiParameterOperand(1), ebx); // arguments pointer. | 1058 __ mov(ApiParameterOperand(1), ebx); // arguments pointer. |
1054 | 1059 |
1055 // Emitting a stub call may try to allocate (if the code is not | 1060 // Emitting a stub call may try to allocate (if the code is not |
1056 // already generated). Do not allow the assembler to perform a | 1061 // already generated). Do not allow the assembler to perform a |
1057 // garbage collection but instead return the allocation failure | 1062 // garbage collection but instead return the allocation failure |
(...skipping 132 matching lines...) Loading... |
1190 ASSERT(callback->getter() != NULL); | 1195 ASSERT(callback->getter() != NULL); |
1191 | 1196 |
1192 // Tail call to runtime. | 1197 // Tail call to runtime. |
1193 // Important invariant in CALLBACKS case: the code above must be | 1198 // Important invariant in CALLBACKS case: the code above must be |
1194 // structured to never clobber |receiver| register. | 1199 // structured to never clobber |receiver| register. |
1195 __ pop(scratch2); // return address | 1200 __ pop(scratch2); // return address |
1196 __ push(receiver); | 1201 __ push(receiver); |
1197 __ push(holder_reg); | 1202 __ push(holder_reg); |
1198 __ mov(holder_reg, Immediate(callback)); | 1203 __ mov(holder_reg, Immediate(callback)); |
1199 __ push(FieldOperand(holder_reg, AccessorInfo::kDataOffset)); | 1204 __ push(FieldOperand(holder_reg, AccessorInfo::kDataOffset)); |
| 1205 __ push(Immediate(reinterpret_cast<int>(isolate()))); |
1200 __ push(holder_reg); | 1206 __ push(holder_reg); |
1201 __ push(name_reg); | 1207 __ push(name_reg); |
1202 __ push(scratch2); // restore return address | 1208 __ push(scratch2); // restore return address |
1203 | 1209 |
1204 ExternalReference ref = | 1210 ExternalReference ref = |
1205 ExternalReference(IC_Utility(IC::kLoadCallbackProperty), | 1211 ExternalReference(IC_Utility(IC::kLoadCallbackProperty), |
1206 masm()->isolate()); | 1212 masm()->isolate()); |
1207 __ TailCallExternalReference(ref, 5, 1); | 1213 __ TailCallExternalReference(ref, 6, 1); |
1208 } | 1214 } |
1209 } else { // !compile_followup_inline | 1215 } else { // !compile_followup_inline |
1210 // Call the runtime system to load the interceptor. | 1216 // Call the runtime system to load the interceptor. |
1211 // Check that the maps haven't changed. | 1217 // Check that the maps haven't changed. |
1212 Register holder_reg = | 1218 Register holder_reg = |
1213 CheckPrototypes(object, receiver, interceptor_holder, | 1219 CheckPrototypes(object, receiver, interceptor_holder, |
1214 scratch1, scratch2, scratch3, name, miss); | 1220 scratch1, scratch2, scratch3, name, miss); |
1215 __ pop(scratch2); // save old return address | 1221 __ pop(scratch2); // save old return address |
1216 PushInterceptorArguments(masm(), receiver, holder_reg, | 1222 PushInterceptorArguments(masm(), receiver, holder_reg, |
1217 name_reg, interceptor_holder); | 1223 name_reg, interceptor_holder); |
1218 __ push(scratch2); // restore old return address | 1224 __ push(scratch2); // restore old return address |
1219 | 1225 |
1220 ExternalReference ref = | 1226 ExternalReference ref = |
1221 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), | 1227 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), |
1222 isolate()); | 1228 isolate()); |
1223 __ TailCallExternalReference(ref, 5, 1); | 1229 __ TailCallExternalReference(ref, 6, 1); |
1224 } | 1230 } |
1225 } | 1231 } |
1226 | 1232 |
1227 | 1233 |
1228 void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) { | 1234 void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) { |
1229 if (kind_ == Code::KEYED_CALL_IC) { | 1235 if (kind_ == Code::KEYED_CALL_IC) { |
1230 __ cmp(ecx, Immediate(name)); | 1236 __ cmp(ecx, Immediate(name)); |
1231 __ j(not_equal, miss); | 1237 __ j(not_equal, miss); |
1232 } | 1238 } |
1233 } | 1239 } |
(...skipping 917 matching lines...) Loading... |
2151 | 2157 |
2152 // Allocate space for v8::Arguments implicit values. Must be initialized | 2158 // Allocate space for v8::Arguments implicit values. Must be initialized |
2153 // before calling any runtime function. | 2159 // before calling any runtime function. |
2154 __ sub(esp, Immediate(kFastApiCallArguments * kPointerSize)); | 2160 __ sub(esp, Immediate(kFastApiCallArguments * kPointerSize)); |
2155 | 2161 |
2156 // Check that the maps haven't changed and find a Holder as a side effect. | 2162 // Check that the maps haven't changed and find a Holder as a side effect. |
2157 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, | 2163 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, |
2158 name, depth, &miss); | 2164 name, depth, &miss); |
2159 | 2165 |
2160 // Move the return address on top of the stack. | 2166 // Move the return address on top of the stack. |
2161 __ mov(eax, Operand(esp, 3 * kPointerSize)); | 2167 __ mov(eax, Operand(esp, 4 * kPointerSize)); |
2162 __ mov(Operand(esp, 0 * kPointerSize), eax); | 2168 __ mov(Operand(esp, 0 * kPointerSize), eax); |
2163 | 2169 |
2164 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains | 2170 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains |
2165 // duplicate of return address and will be overwritten. | 2171 // duplicate of return address and will be overwritten. |
2166 GenerateFastApiCall(masm(), optimization, argc); | 2172 GenerateFastApiCall(masm(), optimization, argc); |
2167 | 2173 |
2168 __ bind(&miss); | 2174 __ bind(&miss); |
2169 __ add(esp, Immediate(kFastApiCallArguments * kPointerSize)); | 2175 __ add(esp, Immediate(kFastApiCallArguments * kPointerSize)); |
2170 | 2176 |
2171 __ bind(&miss_before_stack_reserved); | 2177 __ bind(&miss_before_stack_reserved); |
(...skipping 1898 matching lines...) Loading... |
4070 __ jmp(ic_slow, RelocInfo::CODE_TARGET); | 4076 __ jmp(ic_slow, RelocInfo::CODE_TARGET); |
4071 } | 4077 } |
4072 } | 4078 } |
4073 | 4079 |
4074 | 4080 |
4075 #undef __ | 4081 #undef __ |
4076 | 4082 |
4077 } } // namespace v8::internal | 4083 } } // namespace v8::internal |
4078 | 4084 |
4079 #endif // V8_TARGET_ARCH_IA32 | 4085 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |