OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 468 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
479 Handle<CallHandlerInfo> api_call_info_handle(optimization.api_call_info()); | 479 Handle<CallHandlerInfo> api_call_info_handle(optimization.api_call_info()); |
480 if (Heap::InNewSpace(call_data)) { | 480 if (Heap::InNewSpace(call_data)) { |
481 __ mov(ecx, api_call_info_handle); | 481 __ mov(ecx, api_call_info_handle); |
482 __ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kDataOffset)); | 482 __ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kDataOffset)); |
483 __ mov(Operand(esp, 3 * kPointerSize), ebx); | 483 __ mov(Operand(esp, 3 * kPointerSize), ebx); |
484 } else { | 484 } else { |
485 __ mov(Operand(esp, 3 * kPointerSize), | 485 __ mov(Operand(esp, 3 * kPointerSize), |
486 Immediate(Handle<Object>(call_data))); | 486 Immediate(Handle<Object>(call_data))); |
487 } | 487 } |
488 | 488 |
489 // Prepare arguments for ApiCallEntryStub. | 489 // Prepare arguments. |
490 __ lea(eax, Operand(esp, 3 * kPointerSize)); | 490 __ lea(eax, Operand(esp, 3 * kPointerSize)); |
491 __ lea(ebx, Operand(esp, (argc + 3) * kPointerSize)); | |
492 __ Set(edx, Immediate(argc)); | |
493 | 491 |
494 Object* callback = optimization.api_call_info()->callback(); | 492 Object* callback = optimization.api_call_info()->callback(); |
495 Address api_function_address = v8::ToCData<Address>(callback); | 493 Address api_function_address = v8::ToCData<Address>(callback); |
496 ApiFunction fun(api_function_address); | 494 ApiFunction fun(api_function_address); |
497 | 495 |
498 ApiCallEntryStub stub(api_call_info_handle, &fun); | 496 const int kApiArgc = 1; // API function gets reference to the v8::Arguments. |
499 | 497 |
500 __ EnterInternalFrame(); | 498 // Allocate the v8::Arguments structure in the arguments' space since |
| 499 // it's not controlled by GC. |
| 500 const int kApiStackSpace = 4; |
| 501 |
| 502 __ PrepareCallApiFunction(kApiArgc + kApiStackSpace, ebx); |
| 503 |
| 504 __ mov(ApiParameterOperand(1), eax); // v8::Arguments::implicit_args_. |
| 505 __ add(Operand(eax), Immediate(argc * kPointerSize)); |
| 506 __ mov(ApiParameterOperand(2), eax); // v8::Arguments::values_. |
| 507 __ Set(ApiParameterOperand(3), Immediate(argc)); // v8::Arguments::length_. |
| 508 // v8::Arguments::is_construct_call_. |
| 509 __ Set(ApiParameterOperand(4), Immediate(0)); |
| 510 |
| 511 // v8::InvocationCallback's argument. |
| 512 __ lea(eax, ApiParameterOperand(1)); |
| 513 __ mov(ApiParameterOperand(0), eax); |
501 | 514 |
502 // Emitting a stub call may try to allocate (if the code is not | 515 // Emitting a stub call may try to allocate (if the code is not |
503 // already generated). Do not allow the assembler to perform a | 516 // already generated). Do not allow the assembler to perform a |
504 // garbage collection but instead return the allocation failure | 517 // garbage collection but instead return the allocation failure |
505 // object. | 518 // object. |
506 MaybeObject* result = masm->TryCallStub(&stub); | 519 MaybeObject* result = |
| 520 masm->TryCallApiFunctionAndReturn(&fun, argc + kFastApiCallArguments + 1); |
507 if (result->IsFailure()) { | 521 if (result->IsFailure()) { |
508 *failure = Failure::cast(result); | 522 *failure = Failure::cast(result); |
509 return false; | 523 return false; |
510 } | 524 } |
511 | |
512 __ LeaveInternalFrame(); | |
513 __ ret((argc + 4) * kPointerSize); | |
514 return true; | 525 return true; |
515 } | 526 } |
516 | 527 |
517 | 528 |
518 class CallInterceptorCompiler BASE_EMBEDDED { | 529 class CallInterceptorCompiler BASE_EMBEDDED { |
519 public: | 530 public: |
520 CallInterceptorCompiler(StubCompiler* stub_compiler, | 531 CallInterceptorCompiler(StubCompiler* stub_compiler, |
521 const ParameterCount& arguments, | 532 const ParameterCount& arguments, |
522 Register name) | 533 Register name) |
523 : stub_compiler_(stub_compiler), | 534 : stub_compiler_(stub_compiler), |
(...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1056 __ test(receiver, Immediate(kSmiTagMask)); | 1067 __ test(receiver, Immediate(kSmiTagMask)); |
1057 __ j(zero, miss, not_taken); | 1068 __ j(zero, miss, not_taken); |
1058 | 1069 |
1059 // Check that the maps haven't changed. | 1070 // Check that the maps haven't changed. |
1060 Register reg = | 1071 Register reg = |
1061 CheckPrototypes(object, receiver, holder, scratch1, | 1072 CheckPrototypes(object, receiver, holder, scratch1, |
1062 scratch2, scratch3, name, miss); | 1073 scratch2, scratch3, name, miss); |
1063 | 1074 |
1064 Handle<AccessorInfo> callback_handle(callback); | 1075 Handle<AccessorInfo> callback_handle(callback); |
1065 | 1076 |
1066 __ EnterInternalFrame(); | 1077 // Insert additional parameters into the stack frame above return address. |
1067 // Push the stack address where the list of arguments ends. | 1078 ASSERT(!scratch3.is(reg)); |
1068 __ lea(scratch2, Operand(esp, -2 * kPointerSize)); | 1079 __ pop(scratch3); // Get return address to place it below. |
1069 __ push(scratch2); | 1080 |
1070 __ push(receiver); // receiver | 1081 __ push(receiver); // receiver |
| 1082 __ mov(scratch2, Operand(esp)); |
| 1083 ASSERT(!scratch2.is(reg)); |
1071 __ push(reg); // holder | 1084 __ push(reg); // holder |
1072 // Push data from AccessorInfo. | 1085 // Push data from AccessorInfo. |
1073 if (Heap::InNewSpace(callback_handle->data())) { | 1086 if (Heap::InNewSpace(callback_handle->data())) { |
1074 __ mov(scratch2, Immediate(callback_handle)); | 1087 __ mov(scratch1, Immediate(callback_handle)); |
1075 __ push(FieldOperand(scratch2, AccessorInfo::kDataOffset)); | 1088 __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset)); |
1076 } else { | 1089 } else { |
1077 __ push(Immediate(Handle<Object>(callback_handle->data()))); | 1090 __ push(Immediate(Handle<Object>(callback_handle->data()))); |
1078 } | 1091 } |
1079 __ push(name_reg); // name | 1092 |
1080 // Save a pointer to where we pushed the arguments pointer. | 1093 // Save a pointer to where we pushed the arguments pointer. |
1081 // This will be passed as the const AccessorInfo& to the C++ callback. | 1094 // This will be passed as the const AccessorInfo& to the C++ callback. |
1082 STATIC_ASSERT(ApiGetterEntryStub::kStackSpace == 5); | 1095 __ push(scratch2); |
1083 __ lea(eax, Operand(esp, 4 * kPointerSize)); | 1096 |
1084 __ mov(ebx, esp); | 1097 __ push(name_reg); // name |
| 1098 __ mov(ebx, esp); // esp points to reference to name (handler). |
| 1099 |
| 1100 __ push(scratch3); // Restore return address. |
1085 | 1101 |
1086 // Do call through the api. | 1102 // Do call through the api. |
1087 Address getter_address = v8::ToCData<Address>(callback->getter()); | 1103 Address getter_address = v8::ToCData<Address>(callback->getter()); |
1088 ApiFunction fun(getter_address); | 1104 ApiFunction fun(getter_address); |
1089 ApiGetterEntryStub stub(callback_handle, &fun); | 1105 |
| 1106 // 3 elements array for v8::Agruments::values_, handler for name and pointer |
| 1107 // to the values (it considered as smi in GC). |
| 1108 const int kStackSpace = 5; |
| 1109 const int kApiArgc = 2; |
| 1110 |
| 1111 __ PrepareCallApiFunction(kApiArgc, eax); |
| 1112 __ mov(ApiParameterOperand(0), ebx); // name. |
| 1113 __ add(Operand(ebx), Immediate(kPointerSize)); |
| 1114 __ mov(ApiParameterOperand(1), ebx); // arguments pointer. |
| 1115 |
1090 // Emitting a stub call may try to allocate (if the code is not | 1116 // Emitting a stub call may try to allocate (if the code is not |
1091 // already generated). Do not allow the assembler to perform a | 1117 // already generated). Do not allow the assembler to perform a |
1092 // garbage collection but instead return the allocation failure | 1118 // garbage collection but instead return the allocation failure |
1093 // object. | 1119 // object. |
1094 Object* result = NULL; // Initialization to please compiler. | 1120 MaybeObject* result = masm()->TryCallApiFunctionAndReturn(&fun, kStackSpace); |
1095 { MaybeObject* try_call_result = masm()->TryCallStub(&stub); | 1121 if (result->IsFailure()) { |
1096 if (!try_call_result->ToObject(&result)) { | 1122 *failure = Failure::cast(result); |
1097 *failure = Failure::cast(try_call_result); | 1123 return false; |
1098 return false; | |
1099 } | |
1100 } | 1124 } |
1101 __ LeaveInternalFrame(); | |
1102 | 1125 |
1103 __ ret(0); | |
1104 return true; | 1126 return true; |
1105 } | 1127 } |
1106 | 1128 |
1107 | 1129 |
1108 void StubCompiler::GenerateLoadConstant(JSObject* object, | 1130 void StubCompiler::GenerateLoadConstant(JSObject* object, |
1109 JSObject* holder, | 1131 JSObject* holder, |
1110 Register receiver, | 1132 Register receiver, |
1111 Register scratch1, | 1133 Register scratch1, |
1112 Register scratch2, | 1134 Register scratch2, |
1113 Register scratch3, | 1135 Register scratch3, |
(...skipping 1025 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2139 case RECEIVER_MAP_CHECK: | 2161 case RECEIVER_MAP_CHECK: |
2140 __ IncrementCounter(&Counters::call_const, 1); | 2162 __ IncrementCounter(&Counters::call_const, 1); |
2141 | 2163 |
2142 if (optimization.is_simple_api_call() && !object->IsGlobalObject()) { | 2164 if (optimization.is_simple_api_call() && !object->IsGlobalObject()) { |
2143 depth = optimization.GetPrototypeDepthOfExpectedType( | 2165 depth = optimization.GetPrototypeDepthOfExpectedType( |
2144 JSObject::cast(object), holder); | 2166 JSObject::cast(object), holder); |
2145 } | 2167 } |
2146 | 2168 |
2147 if (depth != kInvalidProtoDepth) { | 2169 if (depth != kInvalidProtoDepth) { |
2148 __ IncrementCounter(&Counters::call_const_fast_api, 1); | 2170 __ IncrementCounter(&Counters::call_const_fast_api, 1); |
2149 ReserveSpaceForFastApiCall(masm(), eax); | 2171 |
| 2172 // Allocate space for v8::Arguments implicit values. Must be initialized |
| 2173 // before to call any runtime function. |
| 2174 __ sub(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize)); |
2150 } | 2175 } |
2151 | 2176 |
2152 // Check that the maps haven't changed. | 2177 // Check that the maps haven't changed. |
2153 CheckPrototypes(JSObject::cast(object), edx, holder, | 2178 CheckPrototypes(JSObject::cast(object), edx, holder, |
2154 ebx, eax, edi, name, depth, &miss); | 2179 ebx, eax, edi, name, depth, &miss); |
2155 | 2180 |
2156 // Patch the receiver on the stack with the global proxy if | 2181 // Patch the receiver on the stack with the global proxy if |
2157 // necessary. | 2182 // necessary. |
2158 if (object->IsGlobalObject()) { | 2183 if (object->IsGlobalObject()) { |
2159 ASSERT(depth == kInvalidProtoDepth); | 2184 ASSERT(depth == kInvalidProtoDepth); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2219 } | 2244 } |
2220 break; | 2245 break; |
2221 } | 2246 } |
2222 | 2247 |
2223 default: | 2248 default: |
2224 UNREACHABLE(); | 2249 UNREACHABLE(); |
2225 } | 2250 } |
2226 | 2251 |
2227 if (depth != kInvalidProtoDepth) { | 2252 if (depth != kInvalidProtoDepth) { |
2228 Failure* failure; | 2253 Failure* failure; |
| 2254 // Move the return address on top of the stack. |
| 2255 __ mov(eax, Operand(esp, 3 * kPointerSize)); |
| 2256 __ mov(Operand(esp, 0 * kPointerSize), eax); |
| 2257 |
| 2258 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains |
| 2259 // duplicate of return address and will be overwritten. |
2229 bool success = GenerateFastApiCall(masm(), optimization, argc, &failure); | 2260 bool success = GenerateFastApiCall(masm(), optimization, argc, &failure); |
2230 if (!success) { | 2261 if (!success) { |
2231 return failure; | 2262 return failure; |
2232 } | 2263 } |
2233 } else { | 2264 } else { |
2234 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); | 2265 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); |
2235 } | 2266 } |
2236 | 2267 |
2237 // Handle call cache miss. | 2268 // Handle call cache miss. |
2238 __ bind(&miss); | 2269 __ bind(&miss); |
2239 if (depth != kInvalidProtoDepth) { | 2270 if (depth != kInvalidProtoDepth) { |
2240 FreeSpaceForFastApiCall(masm(), eax); | 2271 __ add(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize)); |
2241 } | 2272 } |
2242 __ bind(&miss_in_smi_check); | 2273 __ bind(&miss_in_smi_check); |
2243 Object* obj; | 2274 Object* obj; |
2244 { MaybeObject* maybe_obj = GenerateMissBranch(); | 2275 { MaybeObject* maybe_obj = GenerateMissBranch(); |
2245 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 2276 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
2246 } | 2277 } |
2247 | 2278 |
2248 // Return the generated code. | 2279 // Return the generated code. |
2249 return GetCode(function); | 2280 return GetCode(function); |
2250 } | 2281 } |
(...skipping 873 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3124 // Return the generated code. | 3155 // Return the generated code. |
3125 return GetCode(); | 3156 return GetCode(); |
3126 } | 3157 } |
3127 | 3158 |
3128 | 3159 |
3129 #undef __ | 3160 #undef __ |
3130 | 3161 |
3131 } } // namespace v8::internal | 3162 } } // namespace v8::internal |
3132 | 3163 |
3133 #endif // V8_TARGET_ARCH_IA32 | 3164 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |