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 761 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
772 __ j(not_equal, interceptor_succeeded); | 772 __ j(not_equal, interceptor_succeeded); |
773 } | 773 } |
774 | 774 |
775 StubCompiler* stub_compiler_; | 775 StubCompiler* stub_compiler_; |
776 const ParameterCount& arguments_; | 776 const ParameterCount& arguments_; |
777 Register name_; | 777 Register name_; |
778 Code::ExtraICState extra_state_; | 778 Code::ExtraICState extra_state_; |
779 }; | 779 }; |
780 | 780 |
781 | 781 |
782 void BaseStoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, | 782 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, |
783 Label* label, | 783 Label* label, |
784 Handle<Name> name) { | 784 Handle<Name> name) { |
785 if (!label->is_unused()) { | 785 if (!label->is_unused()) { |
786 __ bind(label); | 786 __ bind(label); |
787 __ mov(this->name(), Immediate(name)); | 787 __ mov(this->name(), Immediate(name)); |
788 } | 788 } |
789 } | 789 } |
790 | 790 |
791 | 791 |
792 // Generate code to check that a global property cell is empty. Create | 792 // Generate code to check that a global property cell is empty. Create |
793 // the property cell at compilation time if no cell exists for the | 793 // the property cell at compilation time if no cell exists for the |
794 // property. | 794 // property. |
(...skipping 10 matching lines...) Expand all Loading... |
805 __ mov(scratch, Immediate(cell)); | 805 __ mov(scratch, Immediate(cell)); |
806 __ cmp(FieldOperand(scratch, PropertyCell::kValueOffset), | 806 __ cmp(FieldOperand(scratch, PropertyCell::kValueOffset), |
807 Immediate(the_hole)); | 807 Immediate(the_hole)); |
808 } else { | 808 } else { |
809 __ cmp(Operand::ForCell(cell), Immediate(the_hole)); | 809 __ cmp(Operand::ForCell(cell), Immediate(the_hole)); |
810 } | 810 } |
811 __ j(not_equal, miss); | 811 __ j(not_equal, miss); |
812 } | 812 } |
813 | 813 |
814 | 814 |
815 void BaseStoreStubCompiler::GenerateNegativeHolderLookup( | 815 void StoreStubCompiler::GenerateNegativeHolderLookup( |
816 MacroAssembler* masm, | 816 MacroAssembler* masm, |
817 Handle<JSObject> holder, | 817 Handle<JSObject> holder, |
818 Register holder_reg, | 818 Register holder_reg, |
819 Handle<Name> name, | 819 Handle<Name> name, |
820 Label* miss) { | 820 Label* miss) { |
821 if (holder->IsJSGlobalObject()) { | 821 if (holder->IsJSGlobalObject()) { |
822 GenerateCheckPropertyCell( | 822 GenerateCheckPropertyCell( |
823 masm, Handle<GlobalObject>::cast(holder), name, scratch1(), miss); | 823 masm, Handle<GlobalObject>::cast(holder), name, scratch1(), miss); |
824 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { | 824 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { |
825 GenerateDictionaryNegativeLookup( | 825 GenerateDictionaryNegativeLookup( |
826 masm, miss, holder_reg, name, scratch1(), scratch2()); | 826 masm, miss, holder_reg, name, scratch1(), scratch2()); |
827 } | 827 } |
828 } | 828 } |
829 | 829 |
830 | 830 |
831 // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if | 831 // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if |
832 // store is successful. | 832 // store is successful. |
833 void BaseStoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm, | 833 void StoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm, |
834 Handle<JSObject> object, | 834 Handle<JSObject> object, |
835 LookupResult* lookup, | 835 LookupResult* lookup, |
836 Handle<Map> transition, | 836 Handle<Map> transition, |
837 Handle<Name> name, | 837 Handle<Name> name, |
838 Register receiver_reg, | 838 Register receiver_reg, |
839 Register storage_reg, | 839 Register storage_reg, |
840 Register value_reg, | 840 Register value_reg, |
841 Register scratch1, | 841 Register scratch1, |
842 Register scratch2, | 842 Register scratch2, |
843 Register unused, | 843 Register unused, |
844 Label* miss_label, | 844 Label* miss_label, |
845 Label* slow) { | 845 Label* slow) { |
846 int descriptor = transition->LastAdded(); | 846 int descriptor = transition->LastAdded(); |
847 DescriptorArray* descriptors = transition->instance_descriptors(); | 847 DescriptorArray* descriptors = transition->instance_descriptors(); |
848 PropertyDetails details = descriptors->GetDetails(descriptor); | 848 PropertyDetails details = descriptors->GetDetails(descriptor); |
849 Representation representation = details.representation(); | 849 Representation representation = details.representation(); |
850 ASSERT(!representation.IsNone()); | 850 ASSERT(!representation.IsNone()); |
851 | 851 |
852 if (details.type() == CONSTANT) { | 852 if (details.type() == CONSTANT) { |
853 Handle<Object> constant(descriptors->GetValue(descriptor), masm->isolate()); | 853 Handle<Object> constant(descriptors->GetValue(descriptor), masm->isolate()); |
854 __ CmpObject(value_reg, constant); | 854 __ CmpObject(value_reg, constant); |
855 __ j(not_equal, miss_label); | 855 __ j(not_equal, miss_label); |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
994 } | 994 } |
995 | 995 |
996 // Return the value (register eax). | 996 // Return the value (register eax). |
997 ASSERT(value_reg.is(eax)); | 997 ASSERT(value_reg.is(eax)); |
998 __ ret(0); | 998 __ ret(0); |
999 } | 999 } |
1000 | 1000 |
1001 | 1001 |
1002 // Both name_reg and receiver_reg are preserved on jumps to miss_label, | 1002 // Both name_reg and receiver_reg are preserved on jumps to miss_label, |
1003 // but may be destroyed if store is successful. | 1003 // but may be destroyed if store is successful. |
1004 void BaseStoreStubCompiler::GenerateStoreField(MacroAssembler* masm, | 1004 void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm, |
1005 Handle<JSObject> object, | 1005 Handle<JSObject> object, |
1006 LookupResult* lookup, | 1006 LookupResult* lookup, |
1007 Register receiver_reg, | 1007 Register receiver_reg, |
1008 Register name_reg, | 1008 Register name_reg, |
1009 Register value_reg, | 1009 Register value_reg, |
1010 Register scratch1, | 1010 Register scratch1, |
1011 Register scratch2, | 1011 Register scratch2, |
1012 Label* miss_label) { | 1012 Label* miss_label) { |
1013 // Stub never generated for non-global objects that require access | 1013 // Stub never generated for non-global objects that require access |
1014 // checks. | 1014 // checks. |
1015 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 1015 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
1016 | 1016 |
1017 int index = lookup->GetFieldIndex().field_index(); | 1017 int index = lookup->GetFieldIndex().field_index(); |
1018 | 1018 |
1019 // Adjust for the number of properties stored in the object. Even in the | 1019 // Adjust for the number of properties stored in the object. Even in the |
1020 // face of a transition we can use the old map here because the size of the | 1020 // face of a transition we can use the old map here because the size of the |
1021 // object and the number of in-object properties is not going to change. | 1021 // object and the number of in-object properties is not going to change. |
1022 index -= object->map()->inobject_properties(); | 1022 index -= object->map()->inobject_properties(); |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1266 // If we've skipped any global objects, it's not enough to verify that | 1266 // If we've skipped any global objects, it's not enough to verify that |
1267 // their maps haven't changed. We also need to check that the property | 1267 // their maps haven't changed. We also need to check that the property |
1268 // cell for the property is still empty. | 1268 // cell for the property is still empty. |
1269 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); | 1269 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); |
1270 | 1270 |
1271 // Return the register containing the holder. | 1271 // Return the register containing the holder. |
1272 return reg; | 1272 return reg; |
1273 } | 1273 } |
1274 | 1274 |
1275 | 1275 |
1276 void BaseLoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, | 1276 void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, |
1277 Label* success, | 1277 Label* success, |
1278 Label* miss) { | 1278 Label* miss) { |
1279 if (!miss->is_unused()) { | 1279 if (!miss->is_unused()) { |
1280 __ jmp(success); | 1280 __ jmp(success); |
1281 __ bind(miss); | 1281 __ bind(miss); |
1282 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1282 TailCallBuiltin(masm(), MissBuiltin(kind())); |
1283 } | 1283 } |
1284 } | 1284 } |
1285 | 1285 |
1286 | 1286 |
1287 void BaseStoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, | 1287 void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, |
1288 Label* success, | 1288 Label* success, |
1289 Label* miss) { | 1289 Label* miss) { |
1290 if (!miss->is_unused()) { | 1290 if (!miss->is_unused()) { |
1291 __ jmp(success); | 1291 __ jmp(success); |
1292 GenerateRestoreName(masm(), miss, name); | 1292 GenerateRestoreName(masm(), miss, name); |
1293 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1293 TailCallBuiltin(masm(), MissBuiltin(kind())); |
1294 } | 1294 } |
1295 } | 1295 } |
1296 | 1296 |
1297 | 1297 |
1298 Register BaseLoadStubCompiler::CallbackHandlerFrontend( | 1298 Register LoadStubCompiler::CallbackHandlerFrontend( |
1299 Handle<JSObject> object, | 1299 Handle<JSObject> object, |
1300 Register object_reg, | 1300 Register object_reg, |
1301 Handle<JSObject> holder, | 1301 Handle<JSObject> holder, |
1302 Handle<Name> name, | 1302 Handle<Name> name, |
1303 Label* success, | 1303 Label* success, |
1304 Handle<Object> callback) { | 1304 Handle<Object> callback) { |
1305 Label miss; | 1305 Label miss; |
1306 | 1306 |
1307 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); | 1307 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); |
1308 | 1308 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1348 } | 1348 } |
1349 __ cmp(scratch3(), callback); | 1349 __ cmp(scratch3(), callback); |
1350 __ j(not_equal, &miss); | 1350 __ j(not_equal, &miss); |
1351 } | 1351 } |
1352 | 1352 |
1353 HandlerFrontendFooter(name, success, &miss); | 1353 HandlerFrontendFooter(name, success, &miss); |
1354 return reg; | 1354 return reg; |
1355 } | 1355 } |
1356 | 1356 |
1357 | 1357 |
1358 void BaseLoadStubCompiler::NonexistentHandlerFrontend( | 1358 void LoadStubCompiler::NonexistentHandlerFrontend( |
1359 Handle<JSObject> object, | 1359 Handle<JSObject> object, |
1360 Handle<JSObject> last, | 1360 Handle<JSObject> last, |
1361 Handle<Name> name, | 1361 Handle<Name> name, |
1362 Label* success, | 1362 Label* success, |
1363 Handle<GlobalObject> global) { | 1363 Handle<GlobalObject> global) { |
1364 Label miss; | 1364 Label miss; |
1365 | 1365 |
1366 HandlerFrontendHeader(object, receiver(), last, name, &miss); | 1366 HandlerFrontendHeader(object, receiver(), last, name, &miss); |
1367 | 1367 |
1368 // If the last object in the prototype chain is a global object, | 1368 // If the last object in the prototype chain is a global object, |
1369 // check that the global property cell is empty. | 1369 // check that the global property cell is empty. |
1370 if (!global.is_null()) { | 1370 if (!global.is_null()) { |
1371 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); | 1371 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); |
1372 } | 1372 } |
1373 | 1373 |
1374 HandlerFrontendFooter(name, success, &miss); | 1374 HandlerFrontendFooter(name, success, &miss); |
1375 } | 1375 } |
1376 | 1376 |
1377 | 1377 |
1378 void BaseLoadStubCompiler::GenerateLoadField(Register reg, | 1378 void LoadStubCompiler::GenerateLoadField(Register reg, |
1379 Handle<JSObject> holder, | 1379 Handle<JSObject> holder, |
1380 PropertyIndex field, | 1380 PropertyIndex field, |
1381 Representation representation) { | 1381 Representation representation) { |
1382 if (!reg.is(receiver())) __ mov(receiver(), reg); | 1382 if (!reg.is(receiver())) __ mov(receiver(), reg); |
1383 if (kind() == Code::LOAD_IC) { | 1383 if (kind() == Code::LOAD_IC) { |
1384 LoadFieldStub stub(field.is_inobject(holder), | 1384 LoadFieldStub stub(field.is_inobject(holder), |
1385 field.translate(holder), | 1385 field.translate(holder), |
1386 representation); | 1386 representation); |
1387 GenerateTailCall(masm(), stub.GetCode(isolate())); | 1387 GenerateTailCall(masm(), stub.GetCode(isolate())); |
1388 } else { | 1388 } else { |
1389 KeyedLoadFieldStub stub(field.is_inobject(holder), | 1389 KeyedLoadFieldStub stub(field.is_inobject(holder), |
1390 field.translate(holder), | 1390 field.translate(holder), |
1391 representation); | 1391 representation); |
1392 GenerateTailCall(masm(), stub.GetCode(isolate())); | 1392 GenerateTailCall(masm(), stub.GetCode(isolate())); |
1393 } | 1393 } |
1394 } | 1394 } |
1395 | 1395 |
1396 | 1396 |
1397 void BaseLoadStubCompiler::GenerateLoadCallback( | 1397 void LoadStubCompiler::GenerateLoadCallback( |
1398 const CallOptimization& call_optimization) { | 1398 const CallOptimization& call_optimization) { |
1399 GenerateFastApiCall( | 1399 GenerateFastApiCall( |
1400 masm(), call_optimization, receiver(), scratch3(), 0, NULL); | 1400 masm(), call_optimization, receiver(), scratch3(), 0, NULL); |
1401 } | 1401 } |
1402 | 1402 |
1403 | 1403 |
1404 void BaseLoadStubCompiler::GenerateLoadCallback( | 1404 void LoadStubCompiler::GenerateLoadCallback( |
1405 Register reg, | 1405 Register reg, |
1406 Handle<ExecutableAccessorInfo> callback) { | 1406 Handle<ExecutableAccessorInfo> callback) { |
1407 // Insert additional parameters into the stack frame above return address. | 1407 // Insert additional parameters into the stack frame above return address. |
1408 ASSERT(!scratch3().is(reg)); | 1408 ASSERT(!scratch3().is(reg)); |
1409 __ pop(scratch3()); // Get return address to place it below. | 1409 __ pop(scratch3()); // Get return address to place it below. |
1410 | 1410 |
1411 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); | 1411 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); |
1412 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); | 1412 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); |
1413 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); | 1413 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); |
1414 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); | 1414 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1460 | 1460 |
1461 __ CallApiFunctionAndReturn(getter_address, | 1461 __ CallApiFunctionAndReturn(getter_address, |
1462 thunk_address, | 1462 thunk_address, |
1463 ApiParameterOperand(2), | 1463 ApiParameterOperand(2), |
1464 kStackSpace, | 1464 kStackSpace, |
1465 Operand(ebp, 7 * kPointerSize), | 1465 Operand(ebp, 7 * kPointerSize), |
1466 NULL); | 1466 NULL); |
1467 } | 1467 } |
1468 | 1468 |
1469 | 1469 |
1470 void BaseLoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { | 1470 void LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { |
1471 // Return the constant value. | 1471 // Return the constant value. |
1472 __ LoadObject(eax, value); | 1472 __ LoadObject(eax, value); |
1473 __ ret(0); | 1473 __ ret(0); |
1474 } | 1474 } |
1475 | 1475 |
1476 | 1476 |
1477 void BaseLoadStubCompiler::GenerateLoadInterceptor( | 1477 void LoadStubCompiler::GenerateLoadInterceptor( |
1478 Register holder_reg, | 1478 Register holder_reg, |
1479 Handle<JSObject> object, | 1479 Handle<JSObject> object, |
1480 Handle<JSObject> interceptor_holder, | 1480 Handle<JSObject> interceptor_holder, |
1481 LookupResult* lookup, | 1481 LookupResult* lookup, |
1482 Handle<Name> name) { | 1482 Handle<Name> name) { |
1483 ASSERT(interceptor_holder->HasNamedInterceptor()); | 1483 ASSERT(interceptor_holder->HasNamedInterceptor()); |
1484 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 1484 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); |
1485 | 1485 |
1486 // So far the most popular follow ups for interceptor loads are FIELD | 1486 // So far the most popular follow ups for interceptor loads are FIELD |
1487 // and CALLBACKS, so inline only them, other cases may be added | 1487 // and CALLBACKS, so inline only them, other cases may be added |
(...skipping 1619 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3107 __ cmp(name_reg, Immediate(name)); | 3107 __ cmp(name_reg, Immediate(name)); |
3108 __ j(not_equal, miss); | 3108 __ j(not_equal, miss); |
3109 } | 3109 } |
3110 | 3110 |
3111 | 3111 |
3112 #undef __ | 3112 #undef __ |
3113 #define __ ACCESS_MASM(masm) | 3113 #define __ ACCESS_MASM(masm) |
3114 | 3114 |
3115 | 3115 |
3116 void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, | 3116 void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, |
| 3117 Register receiver, |
3117 Handle<JSFunction> getter) { | 3118 Handle<JSFunction> getter) { |
3118 // ----------- S t a t e ------------- | |
3119 // -- ecx : name | |
3120 // -- edx : receiver | |
3121 // -- esp[0] : return address | |
3122 // ----------------------------------- | |
3123 { | 3119 { |
3124 FrameScope scope(masm, StackFrame::INTERNAL); | 3120 FrameScope scope(masm, StackFrame::INTERNAL); |
3125 | 3121 |
3126 if (!getter.is_null()) { | 3122 if (!getter.is_null()) { |
3127 // Call the JavaScript getter with the receiver on the stack. | 3123 // Call the JavaScript getter with the receiver on the stack. |
3128 __ push(edx); | 3124 __ push(receiver); |
3129 ParameterCount actual(0); | 3125 ParameterCount actual(0); |
3130 ParameterCount expected(getter); | 3126 ParameterCount expected(getter); |
3131 __ InvokeFunction(getter, expected, actual, | 3127 __ InvokeFunction(getter, expected, actual, |
3132 CALL_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 3128 CALL_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); |
3133 } else { | 3129 } else { |
3134 // If we generate a global code snippet for deoptimization only, remember | 3130 // If we generate a global code snippet for deoptimization only, remember |
3135 // the place to continue after deoptimization. | 3131 // the place to continue after deoptimization. |
3136 masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset()); | 3132 masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset()); |
3137 } | 3133 } |
3138 | 3134 |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3271 // ----------------------------------- | 3267 // ----------------------------------- |
3272 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); | 3268 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); |
3273 } | 3269 } |
3274 | 3270 |
3275 | 3271 |
3276 #undef __ | 3272 #undef __ |
3277 | 3273 |
3278 } } // namespace v8::internal | 3274 } } // namespace v8::internal |
3279 | 3275 |
3280 #endif // V8_TARGET_ARCH_IA32 | 3276 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |