 Chromium Code Reviews
 Chromium Code Reviews Issue 4695003:
  Removing redundant stubs for API functions.  (Closed) 
  Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
    
  
    Issue 4695003:
  Removing redundant stubs for API functions.  (Closed) 
  Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/| 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 477 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 488 | 488 | 
| 489 // Prepare arguments for ApiCallEntryStub. | 489 // Prepare arguments for ApiCallEntryStub. | 
| 490 __ lea(eax, Operand(esp, 3 * kPointerSize)); | 490 __ lea(eax, Operand(esp, 3 * kPointerSize)); | 
| 491 __ lea(ebx, Operand(esp, (argc + 3) * kPointerSize)); | 491 __ lea(ebx, Operand(esp, (argc + 3) * kPointerSize)); | 
| 492 __ Set(edx, Immediate(argc)); | 492 __ Set(edx, Immediate(argc)); | 
| 493 | 493 | 
| 494 Object* callback = optimization.api_call_info()->callback(); | 494 Object* callback = optimization.api_call_info()->callback(); | 
| 495 Address api_function_address = v8::ToCData<Address>(callback); | 495 Address api_function_address = v8::ToCData<Address>(callback); | 
| 496 ApiFunction fun(api_function_address); | 496 ApiFunction fun(api_function_address); | 
| 497 | 497 | 
| 498 ApiCallEntryStub stub(api_call_info_handle, &fun); | 498 const int kApiArgc = 1; // API function gets reference to the v8::Arguments. | 
| 499 | 499 | 
| 500 __ EnterInternalFrame(); | 500 // Allocate the v8::Arguments structure in the arguments' space since | 
| 501 // it's not controlled by GC. | |
| 502 const int kApiStackSpace = 4; | |
| 503 | |
| 504 __ PrepareCallApiFunction(argc + kFastApiCallArguments + 1, | |
| 
antonm
2010/11/10 14:53:54
not sure if it's worth it, but maybe unify exit fr
 
SeRya
2010/11/11 15:50:39
Please, explain what do you mean by that?
 
antonm
2010/11/12 18:35:55
Sure and sorry for not making it clear.
Take a lo
 
SeRya
2010/11/13 09:19:49
Apparently push is shorter than mov and may be it
 | |
| 505 kApiArgc + kApiStackSpace); | |
| 506 | |
| 507 __ mov(ApiParameterOperand(1), eax); // v8::Arguments::implicit_args_. | |
| 508 __ mov(ApiParameterOperand(2), ebx); // v8::Arguments::values_. | |
| 509 __ mov(ApiParameterOperand(3), edx); // v8::Arguments::length_. | |
| 
antonm
2010/11/10 14:53:54
cannot we fuse those moves and moves above (ln. 49
 
SeRya
2010/11/11 15:50:39
Sure. I just forgot to do it.
 
antonm
2010/11/12 18:35:55
Is it the only opportunity?  For example we could
 
SeRya
2010/11/13 09:19:49
Done.
 | |
| 510 // v8::Arguments::is_construct_call_. | |
| 511 __ mov(ApiParameterOperand(4), Immediate(0)); | |
| 512 | |
| 513 // v8::InvocationCallback's argument. | |
| 514 __ lea(eax, ApiParameterOperand(1)); | |
| 515 __ mov(ApiParameterOperand(0), eax); | |
| 501 | 516 | 
| 502 // Emitting a stub call may try to allocate (if the code is not | 517 // Emitting a stub call may try to allocate (if the code is not | 
| 503 // already generated). Do not allow the assembler to perform a | 518 // already generated). Do not allow the assembler to perform a | 
| 504 // garbage collection but instead return the allocation failure | 519 // garbage collection but instead return the allocation failure | 
| 505 // object. | 520 // object. | 
| 506 MaybeObject* result = masm->TryCallStub(&stub); | 521 MaybeObject* result = masm->TryCallApiFunctionAndReturn(&fun, kApiArgc + | 
| 
antonm
2010/11/10 14:53:54
that might be just me, but I am slightly uneasy wi
 
SeRya
2010/11/11 15:50:39
Done.
 | |
| 522 kApiStackSpace); | |
| 507 if (result->IsFailure()) { | 523 if (result->IsFailure()) { | 
| 508 *failure = Failure::cast(result); | 524 *failure = Failure::cast(result); | 
| 509 return false; | 525 return false; | 
| 510 } | 526 } | 
| 511 | |
| 512 __ LeaveInternalFrame(); | |
| 513 __ ret((argc + 4) * kPointerSize); | |
| 514 return true; | 527 return true; | 
| 515 } | 528 } | 
| 516 | 529 | 
| 517 | 530 | 
| 518 class CallInterceptorCompiler BASE_EMBEDDED { | 531 class CallInterceptorCompiler BASE_EMBEDDED { | 
| 519 public: | 532 public: | 
| 520 CallInterceptorCompiler(StubCompiler* stub_compiler, | 533 CallInterceptorCompiler(StubCompiler* stub_compiler, | 
| 521 const ParameterCount& arguments, | 534 const ParameterCount& arguments, | 
| 522 Register name) | 535 Register name) | 
| 523 : stub_compiler_(stub_compiler), | 536 : stub_compiler_(stub_compiler), | 
| (...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1056 __ test(receiver, Immediate(kSmiTagMask)); | 1069 __ test(receiver, Immediate(kSmiTagMask)); | 
| 1057 __ j(zero, miss, not_taken); | 1070 __ j(zero, miss, not_taken); | 
| 1058 | 1071 | 
| 1059 // Check that the maps haven't changed. | 1072 // Check that the maps haven't changed. | 
| 1060 Register reg = | 1073 Register reg = | 
| 1061 CheckPrototypes(object, receiver, holder, scratch1, | 1074 CheckPrototypes(object, receiver, holder, scratch1, | 
| 1062 scratch2, scratch3, name, miss); | 1075 scratch2, scratch3, name, miss); | 
| 1063 | 1076 | 
| 1064 Handle<AccessorInfo> callback_handle(callback); | 1077 Handle<AccessorInfo> callback_handle(callback); | 
| 1065 | 1078 | 
| 1066 __ EnterInternalFrame(); | 1079 // Insert additional parameters into the stack frame above return address. | 
| 
antonm
2010/11/10 14:53:54
are we sure it is always safe to piggy back on out
 
SeRya
2010/11/11 15:50:39
Technically this is not outer frame, it's our own.
 | |
| 1067 // Push the stack address where the list of arguments ends. | 1080 ASSERT(!scratch3.is(reg)); | 
| 
antonm
2010/11/10 14:53:54
shouldn't you check as well that !scratch{2,3}.is(
 
SeRya
2010/11/11 15:50:39
Caller code must give 5 different registers. If th
 
antonm
2010/11/12 18:35:55
I personally find this check somewhat misleading.
 
SeRya
2010/11/13 09:19:49
This asserts what we are not trying to use a regis
 | |
| 1068 __ lea(scratch2, Operand(esp, -2 * kPointerSize)); | 1081 __ pop(scratch3); // Get return address to place it below. | 
| 1069 __ push(scratch2); | 1082 | 
| 1070 __ push(receiver); // receiver | 1083 __ push(receiver); // receiver | 
| 1084 __ mov(scratch2, Operand(esp)); | |
| 1085 ASSERT(!scratch2.is(reg)); | |
| 1071 __ push(reg); // holder | 1086 __ push(reg); // holder | 
| 1072 // Push data from AccessorInfo. | 1087 // Push data from AccessorInfo. | 
| 1073 if (Heap::InNewSpace(callback_handle->data())) { | 1088 if (Heap::InNewSpace(callback_handle->data())) { | 
| 1074 __ mov(scratch2, Immediate(callback_handle)); | 1089 __ mov(scratch1, Immediate(callback_handle)); | 
| 1075 __ push(FieldOperand(scratch2, AccessorInfo::kDataOffset)); | 1090 __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset)); | 
| 1076 } else { | 1091 } else { | 
| 1077 __ push(Immediate(Handle<Object>(callback_handle->data()))); | 1092 __ push(Immediate(Handle<Object>(callback_handle->data()))); | 
| 1078 } | 1093 } | 
| 1094 // Push the stack address where the list of arguments ends. | |
| 1095 __ push(scratch2); | |
| 1096 | |
| 1079 __ push(name_reg); // name | 1097 __ push(name_reg); // name | 
| 1080 // Save a pointer to where we pushed the arguments pointer. | 1098 // Save a pointer to where we pushed the arguments pointer. | 
| 1081 // This will be passed as the const AccessorInfo& to the C++ callback. | 1099 // This will be passed as the const AccessorInfo& to the C++ callback. | 
| 1082 STATIC_ASSERT(ApiGetterEntryStub::kStackSpace == 5); | |
| 1083 __ lea(eax, Operand(esp, 4 * kPointerSize)); | |
| 1084 __ mov(ebx, esp); | 1100 __ mov(ebx, esp); | 
| 1085 | 1101 | 
| 1102 __ push(scratch3); // Restore return addresss. | |
| 1103 | |
| 1086 // Do call through the api. | 1104 // Do call through the api. | 
| 1087 Address getter_address = v8::ToCData<Address>(callback->getter()); | 1105 Address getter_address = v8::ToCData<Address>(callback->getter()); | 
| 1088 ApiFunction fun(getter_address); | 1106 ApiFunction fun(getter_address); | 
| 1089 ApiGetterEntryStub stub(callback_handle, &fun); | 1107 | 
| 1108 // 3 elements array for v8::Agruments::values_, handler for name and pointer | |
| 1109 // to the values (it considered as smi in GC). | |
| 
antonm
2010/11/10 14:53:54
are you talking about ApiParameters below?  if yes
 
SeRya
2010/11/11 15:50:39
stake space (the first parameter of PrepareCallApi
 | |
| 1110 const int kStackSpace = 5; | |
| 1111 const int kApiArgc = 2; | |
| 1112 | |
| 1113 __ PrepareCallApiFunction(kStackSpace, kApiArgc); | |
| 
antonm
2010/11/10 14:53:54
again, couldn't we merge pushing and exit frame se
 | |
| 1114 __ lea(eax, Operand(ebx, 1 * kPointerSize)); | |
| 1115 __ mov(ApiParameterOperand(0), ebx); // name. | |
| 1116 __ mov(ApiParameterOperand(1), eax); // arguments pointer. | |
| 
antonm
2010/11/10 14:53:54
I won't be surprised if __mov(APO(0), ebx); __ add
 
SeRya
2010/11/11 15:50:39
Done.
 | |
| 1117 | |
| 1090 // Emitting a stub call may try to allocate (if the code is not | 1118 // Emitting a stub call may try to allocate (if the code is not | 
| 1091 // already generated). Do not allow the assembler to perform a | 1119 // already generated). Do not allow the assembler to perform a | 
| 1092 // garbage collection but instead return the allocation failure | 1120 // garbage collection but instead return the allocation failure | 
| 1093 // object. | 1121 // object. | 
| 1094 Object* result = NULL; // Initialization to please compiler. | 1122 MaybeObject* result = masm()->TryCallApiFunctionAndReturn(&fun, kApiArgc); | 
| 1095 { MaybeObject* try_call_result = masm()->TryCallStub(&stub); | 1123 if (result->IsFailure()) { | 
| 1096 if (!try_call_result->ToObject(&result)) { | 1124 *failure = Failure::cast(result); | 
| 1097 *failure = Failure::cast(try_call_result); | 1125 return false; | 
| 1098 return false; | |
| 1099 } | |
| 1100 } | 1126 } | 
| 1101 __ LeaveInternalFrame(); | |
| 1102 | 1127 | 
| 1103 __ ret(0); | |
| 1104 return true; | 1128 return true; | 
| 1105 } | 1129 } | 
| 1106 | 1130 | 
| 1107 | 1131 | 
| 1108 void StubCompiler::GenerateLoadConstant(JSObject* object, | 1132 void StubCompiler::GenerateLoadConstant(JSObject* object, | 
| 1109 JSObject* holder, | 1133 JSObject* holder, | 
| 1110 Register receiver, | 1134 Register receiver, | 
| 1111 Register scratch1, | 1135 Register scratch1, | 
| 1112 Register scratch2, | 1136 Register scratch2, | 
| 1113 Register scratch3, | 1137 Register scratch3, | 
| (...skipping 2010 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3124 // Return the generated code. | 3148 // Return the generated code. | 
| 3125 return GetCode(); | 3149 return GetCode(); | 
| 3126 } | 3150 } | 
| 3127 | 3151 | 
| 3128 | 3152 | 
| 3129 #undef __ | 3153 #undef __ | 
| 3130 | 3154 | 
| 3131 } } // namespace v8::internal | 3155 } } // namespace v8::internal | 
| 3132 | 3156 | 
| 3133 #endif // V8_TARGET_ARCH_IA32 | 3157 #endif // V8_TARGET_ARCH_IA32 | 
| OLD | NEW |