| 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 1249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1260 // If we've skipped any global objects, it's not enough to verify that | 1260 // If we've skipped any global objects, it's not enough to verify that |
| 1261 // their maps haven't changed. We also need to check that the property | 1261 // their maps haven't changed. We also need to check that the property |
| 1262 // cell for the property is still empty. | 1262 // cell for the property is still empty. |
| 1263 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); | 1263 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); |
| 1264 | 1264 |
| 1265 // Return the register containing the holder. | 1265 // Return the register containing the holder. |
| 1266 return reg; | 1266 return reg; |
| 1267 } | 1267 } |
| 1268 | 1268 |
| 1269 | 1269 |
| 1270 void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, | 1270 void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { |
| 1271 Label* success, | |
| 1272 Label* miss) { | |
| 1273 if (!miss->is_unused()) { | 1271 if (!miss->is_unused()) { |
| 1274 __ jmp(success); | 1272 Label success; |
| 1273 __ jmp(&success); |
| 1275 __ bind(miss); | 1274 __ bind(miss); |
| 1276 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1275 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1276 __ bind(&success); |
| 1277 } | 1277 } |
| 1278 } | 1278 } |
| 1279 | 1279 |
| 1280 | 1280 |
| 1281 void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, | 1281 void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { |
| 1282 Label* success, | |
| 1283 Label* miss) { | |
| 1284 if (!miss->is_unused()) { | 1282 if (!miss->is_unused()) { |
| 1285 __ jmp(success); | 1283 Label success; |
| 1284 __ jmp(&success); |
| 1286 GenerateRestoreName(masm(), miss, name); | 1285 GenerateRestoreName(masm(), miss, name); |
| 1287 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1286 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1287 __ bind(&success); |
| 1288 } | 1288 } |
| 1289 } | 1289 } |
| 1290 | 1290 |
| 1291 | 1291 |
| 1292 Register LoadStubCompiler::CallbackHandlerFrontend( | 1292 Register LoadStubCompiler::CallbackHandlerFrontend( |
| 1293 Handle<JSObject> object, | 1293 Handle<Object> object, |
| 1294 Register object_reg, | 1294 Register object_reg, |
| 1295 Handle<JSObject> holder, | 1295 Handle<JSObject> holder, |
| 1296 Handle<Name> name, | 1296 Handle<Name> name, |
| 1297 Label* success, | |
| 1298 Handle<Object> callback) { | 1297 Handle<Object> callback) { |
| 1299 Label miss; | 1298 Label miss; |
| 1300 | 1299 |
| 1301 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); | 1300 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); |
| 1302 | 1301 |
| 1303 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { | 1302 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { |
| 1304 ASSERT(!reg.is(scratch2())); | 1303 ASSERT(!reg.is(scratch2())); |
| 1305 ASSERT(!reg.is(scratch3())); | 1304 ASSERT(!reg.is(scratch3())); |
| 1306 Register dictionary = scratch1(); | 1305 Register dictionary = scratch1(); |
| 1307 bool must_preserve_dictionary_reg = reg.is(dictionary); | 1306 bool must_preserve_dictionary_reg = reg.is(dictionary); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1337 const int kValueOffset = kElementsStartOffset + kPointerSize; | 1336 const int kValueOffset = kElementsStartOffset + kPointerSize; |
| 1338 __ mov(scratch3(), | 1337 __ mov(scratch3(), |
| 1339 Operand(dictionary, index, times_4, kValueOffset - kHeapObjectTag)); | 1338 Operand(dictionary, index, times_4, kValueOffset - kHeapObjectTag)); |
| 1340 if (must_preserve_dictionary_reg) { | 1339 if (must_preserve_dictionary_reg) { |
| 1341 __ pop(dictionary); | 1340 __ pop(dictionary); |
| 1342 } | 1341 } |
| 1343 __ cmp(scratch3(), callback); | 1342 __ cmp(scratch3(), callback); |
| 1344 __ j(not_equal, &miss); | 1343 __ j(not_equal, &miss); |
| 1345 } | 1344 } |
| 1346 | 1345 |
| 1347 HandlerFrontendFooter(name, success, &miss); | 1346 HandlerFrontendFooter(name, &miss); |
| 1348 return reg; | 1347 return reg; |
| 1349 } | 1348 } |
| 1350 | 1349 |
| 1351 | 1350 |
| 1352 void LoadStubCompiler::GenerateLoadField(Register reg, | 1351 void LoadStubCompiler::GenerateLoadField(Register reg, |
| 1353 Handle<JSObject> holder, | 1352 Handle<JSObject> holder, |
| 1354 PropertyIndex field, | 1353 PropertyIndex field, |
| 1355 Representation representation) { | 1354 Representation representation) { |
| 1356 if (!reg.is(receiver())) __ mov(receiver(), reg); | 1355 if (!reg.is(receiver())) __ mov(receiver(), reg); |
| 1357 if (kind() == Code::LOAD_IC) { | 1356 if (kind() == Code::LOAD_IC) { |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1443 | 1442 |
| 1444 void LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { | 1443 void LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { |
| 1445 // Return the constant value. | 1444 // Return the constant value. |
| 1446 __ LoadObject(eax, value); | 1445 __ LoadObject(eax, value); |
| 1447 __ ret(0); | 1446 __ ret(0); |
| 1448 } | 1447 } |
| 1449 | 1448 |
| 1450 | 1449 |
| 1451 void LoadStubCompiler::GenerateLoadInterceptor( | 1450 void LoadStubCompiler::GenerateLoadInterceptor( |
| 1452 Register holder_reg, | 1451 Register holder_reg, |
| 1453 Handle<JSObject> object, | 1452 Handle<Object> object, |
| 1454 Handle<JSObject> interceptor_holder, | 1453 Handle<JSObject> interceptor_holder, |
| 1455 LookupResult* lookup, | 1454 LookupResult* lookup, |
| 1456 Handle<Name> name) { | 1455 Handle<Name> name) { |
| 1457 ASSERT(interceptor_holder->HasNamedInterceptor()); | 1456 ASSERT(interceptor_holder->HasNamedInterceptor()); |
| 1458 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 1457 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); |
| 1459 | 1458 |
| 1460 // So far the most popular follow ups for interceptor loads are FIELD | 1459 // So far the most popular follow ups for interceptor loads are FIELD |
| 1461 // and CALLBACKS, so inline only them, other cases may be added | 1460 // and CALLBACKS, so inline only them, other cases may be added |
| 1462 // later. | 1461 // later. |
| 1463 bool compile_followup_inline = false; | 1462 bool compile_followup_inline = false; |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1698 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, | 1697 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, |
| 1699 name, &miss); | 1698 name, &miss); |
| 1700 } else { | 1699 } else { |
| 1701 ASSERT(cell->value() == *function); | 1700 ASSERT(cell->value() == *function); |
| 1702 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | 1701 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 1703 &miss); | 1702 &miss); |
| 1704 GenerateLoadFunctionFromCell(cell, function, &miss); | 1703 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 1705 } | 1704 } |
| 1706 | 1705 |
| 1707 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite(); | 1706 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite(); |
| 1708 site->set_transition_info(Smi::FromInt(GetInitialFastElementsKind())); | 1707 site->SetElementsKind(GetInitialFastElementsKind()); |
| 1709 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site); | 1708 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site); |
| 1710 __ mov(eax, Immediate(argc)); | 1709 __ mov(eax, Immediate(argc)); |
| 1711 __ mov(ebx, site_feedback_cell); | 1710 __ mov(ebx, site_feedback_cell); |
| 1712 __ mov(edi, function); | 1711 __ mov(edi, function); |
| 1713 | 1712 |
| 1714 ArrayConstructorStub stub(isolate()); | 1713 ArrayConstructorStub stub(isolate()); |
| 1715 __ TailCallStub(&stub); | 1714 __ TailCallStub(&stub); |
| 1716 | 1715 |
| 1717 __ bind(&miss); | 1716 __ bind(&miss); |
| 1718 GenerateMissBranch(); | 1717 GenerateMissBranch(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1730 Handle<String> name, | 1729 Handle<String> name, |
| 1731 Code::StubType type) { | 1730 Code::StubType type) { |
| 1732 // ----------- S t a t e ------------- | 1731 // ----------- S t a t e ------------- |
| 1733 // -- ecx : name | 1732 // -- ecx : name |
| 1734 // -- esp[0] : return address | 1733 // -- esp[0] : return address |
| 1735 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1734 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 1736 // -- ... | 1735 // -- ... |
| 1737 // -- esp[(argc + 1) * 4] : receiver | 1736 // -- esp[(argc + 1) * 4] : receiver |
| 1738 // ----------------------------------- | 1737 // ----------------------------------- |
| 1739 | 1738 |
| 1740 // If object is not an array, bail out to regular call. | 1739 // If object is not an array or is observed, bail out to regular call. |
| 1741 if (!object->IsJSArray() || !cell.is_null()) { | 1740 if (!object->IsJSArray() || |
| 1741 !cell.is_null() || |
| 1742 Handle<JSArray>::cast(object)->map()->is_observed()) { |
| 1742 return Handle<Code>::null(); | 1743 return Handle<Code>::null(); |
| 1743 } | 1744 } |
| 1744 | 1745 |
| 1745 Label miss; | 1746 Label miss; |
| 1746 | 1747 |
| 1747 GenerateNameCheck(name, &miss); | 1748 GenerateNameCheck(name, &miss); |
| 1748 | 1749 |
| 1749 // Get the receiver from the stack. | 1750 // Get the receiver from the stack. |
| 1750 const int argc = arguments().immediate(); | 1751 const int argc = arguments().immediate(); |
| 1751 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1752 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1989 Handle<String> name, | 1990 Handle<String> name, |
| 1990 Code::StubType type) { | 1991 Code::StubType type) { |
| 1991 // ----------- S t a t e ------------- | 1992 // ----------- S t a t e ------------- |
| 1992 // -- ecx : name | 1993 // -- ecx : name |
| 1993 // -- esp[0] : return address | 1994 // -- esp[0] : return address |
| 1994 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1995 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 1995 // -- ... | 1996 // -- ... |
| 1996 // -- esp[(argc + 1) * 4] : receiver | 1997 // -- esp[(argc + 1) * 4] : receiver |
| 1997 // ----------------------------------- | 1998 // ----------------------------------- |
| 1998 | 1999 |
| 1999 // If object is not an array, bail out to regular call. | 2000 // If object is not an array or is observed, bail out to regular call. |
| 2000 if (!object->IsJSArray() || !cell.is_null()) { | 2001 if (!object->IsJSArray() || |
| 2002 !cell.is_null() || |
| 2003 Handle<JSArray>::cast(object)->map()->is_observed()) { |
| 2001 return Handle<Code>::null(); | 2004 return Handle<Code>::null(); |
| 2002 } | 2005 } |
| 2003 | 2006 |
| 2004 Label miss, return_undefined, call_builtin; | 2007 Label miss, return_undefined, call_builtin; |
| 2005 | 2008 |
| 2006 GenerateNameCheck(name, &miss); | 2009 GenerateNameCheck(name, &miss); |
| 2007 | 2010 |
| 2008 // Get the receiver from the stack. | 2011 // Get the receiver from the stack. |
| 2009 const int argc = arguments().immediate(); | 2012 const int argc = arguments().immediate(); |
| 2010 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2013 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| (...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2606 __ add(esp, Immediate(kFastApiCallArguments * kPointerSize)); | 2609 __ add(esp, Immediate(kFastApiCallArguments * kPointerSize)); |
| 2607 | 2610 |
| 2608 __ bind(&miss_before_stack_reserved); | 2611 __ bind(&miss_before_stack_reserved); |
| 2609 GenerateMissBranch(); | 2612 GenerateMissBranch(); |
| 2610 | 2613 |
| 2611 // Return the generated code. | 2614 // Return the generated code. |
| 2612 return GetCode(function); | 2615 return GetCode(function); |
| 2613 } | 2616 } |
| 2614 | 2617 |
| 2615 | 2618 |
| 2619 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { |
| 2620 Label success; |
| 2621 // Check that the object is a boolean. |
| 2622 __ cmp(object, factory()->true_value()); |
| 2623 __ j(equal, &success); |
| 2624 __ cmp(object, factory()->false_value()); |
| 2625 __ j(not_equal, miss); |
| 2626 __ bind(&success); |
| 2627 } |
| 2628 |
| 2629 |
| 2616 void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object, | 2630 void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object, |
| 2617 Handle<JSObject> holder, | 2631 Handle<JSObject> holder, |
| 2618 Handle<Name> name, | 2632 Handle<Name> name, |
| 2619 CheckType check, | 2633 CheckType check) { |
| 2620 Label* success) { | |
| 2621 // ----------- S t a t e ------------- | 2634 // ----------- S t a t e ------------- |
| 2622 // -- ecx : name | 2635 // -- ecx : name |
| 2623 // -- esp[0] : return address | 2636 // -- esp[0] : return address |
| 2624 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 2637 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 2625 // -- ... | 2638 // -- ... |
| 2626 // -- esp[(argc + 1) * 4] : receiver | 2639 // -- esp[(argc + 1) * 4] : receiver |
| 2627 // ----------------------------------- | 2640 // ----------------------------------- |
| 2628 Label miss; | 2641 Label miss; |
| 2629 GenerateNameCheck(name, &miss); | 2642 GenerateNameCheck(name, &miss); |
| 2630 | 2643 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2689 __ bind(&fast); | 2702 __ bind(&fast); |
| 2690 // Check that the maps starting from the prototype haven't changed. | 2703 // Check that the maps starting from the prototype haven't changed. |
| 2691 GenerateDirectLoadGlobalFunctionPrototype( | 2704 GenerateDirectLoadGlobalFunctionPrototype( |
| 2692 masm(), Context::NUMBER_FUNCTION_INDEX, eax, &miss); | 2705 masm(), Context::NUMBER_FUNCTION_INDEX, eax, &miss); |
| 2693 CheckPrototypes( | 2706 CheckPrototypes( |
| 2694 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2707 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), |
| 2695 eax, holder, ebx, edx, edi, name, &miss); | 2708 eax, holder, ebx, edx, edi, name, &miss); |
| 2696 break; | 2709 break; |
| 2697 } | 2710 } |
| 2698 case BOOLEAN_CHECK: { | 2711 case BOOLEAN_CHECK: { |
| 2699 Label fast; | 2712 GenerateBooleanCheck(edx, &miss); |
| 2700 // Check that the object is a boolean. | |
| 2701 __ cmp(edx, factory()->true_value()); | |
| 2702 __ j(equal, &fast); | |
| 2703 __ cmp(edx, factory()->false_value()); | |
| 2704 __ j(not_equal, &miss); | |
| 2705 __ bind(&fast); | |
| 2706 // Check that the maps starting from the prototype haven't changed. | 2713 // Check that the maps starting from the prototype haven't changed. |
| 2707 GenerateDirectLoadGlobalFunctionPrototype( | 2714 GenerateDirectLoadGlobalFunctionPrototype( |
| 2708 masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, &miss); | 2715 masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, &miss); |
| 2709 CheckPrototypes( | 2716 CheckPrototypes( |
| 2710 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2717 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), |
| 2711 eax, holder, ebx, edx, edi, name, &miss); | 2718 eax, holder, ebx, edx, edi, name, &miss); |
| 2712 break; | 2719 break; |
| 2713 } | 2720 } |
| 2714 } | 2721 } |
| 2715 | 2722 |
| 2716 __ jmp(success); | 2723 Label success; |
| 2724 __ jmp(&success); |
| 2717 | 2725 |
| 2718 // Handle call cache miss. | 2726 // Handle call cache miss. |
| 2719 __ bind(&miss); | 2727 __ bind(&miss); |
| 2720 GenerateMissBranch(); | 2728 GenerateMissBranch(); |
| 2729 |
| 2730 __ bind(&success); |
| 2721 } | 2731 } |
| 2722 | 2732 |
| 2723 | 2733 |
| 2724 void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) { | 2734 void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) { |
| 2725 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2735 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2726 ? CALL_AS_FUNCTION | 2736 ? CALL_AS_FUNCTION |
| 2727 : CALL_AS_METHOD; | 2737 : CALL_AS_METHOD; |
| 2728 ParameterCount expected(function); | 2738 ParameterCount expected(function); |
| 2729 __ InvokeFunction(function, expected, arguments(), | 2739 __ InvokeFunction(function, expected, arguments(), |
| 2730 JUMP_FUNCTION, NullCallWrapper(), call_kind); | 2740 JUMP_FUNCTION, NullCallWrapper(), call_kind); |
| 2731 } | 2741 } |
| 2732 | 2742 |
| 2733 | 2743 |
| 2734 Handle<Code> CallStubCompiler::CompileCallConstant( | 2744 Handle<Code> CallStubCompiler::CompileCallConstant( |
| 2735 Handle<Object> object, | 2745 Handle<Object> object, |
| 2736 Handle<JSObject> holder, | 2746 Handle<JSObject> holder, |
| 2737 Handle<Name> name, | 2747 Handle<Name> name, |
| 2738 CheckType check, | 2748 CheckType check, |
| 2739 Handle<JSFunction> function) { | 2749 Handle<JSFunction> function) { |
| 2740 | 2750 |
| 2741 if (HasCustomCallGenerator(function)) { | 2751 if (HasCustomCallGenerator(function)) { |
| 2742 Handle<Code> code = CompileCustomCall(object, holder, | 2752 Handle<Code> code = CompileCustomCall(object, holder, |
| 2743 Handle<Cell>::null(), | 2753 Handle<Cell>::null(), |
| 2744 function, Handle<String>::cast(name), | 2754 function, Handle<String>::cast(name), |
| 2745 Code::CONSTANT); | 2755 Code::CONSTANT); |
| 2746 // A null handle means bail out to the regular compiler code below. | 2756 // A null handle means bail out to the regular compiler code below. |
| 2747 if (!code.is_null()) return code; | 2757 if (!code.is_null()) return code; |
| 2748 } | 2758 } |
| 2749 | 2759 |
| 2750 Label success; | 2760 CompileHandlerFrontend(object, holder, name, check); |
| 2751 | |
| 2752 CompileHandlerFrontend(object, holder, name, check, &success); | |
| 2753 __ bind(&success); | |
| 2754 CompileHandlerBackend(function); | 2761 CompileHandlerBackend(function); |
| 2755 | 2762 |
| 2756 // Return the generated code. | 2763 // Return the generated code. |
| 2757 return GetCode(function); | 2764 return GetCode(function); |
| 2758 } | 2765 } |
| 2759 | 2766 |
| 2760 | 2767 |
| 2761 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, | 2768 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, |
| 2762 Handle<JSObject> holder, | 2769 Handle<JSObject> holder, |
| 2763 Handle<Name> name) { | 2770 Handle<Name> name) { |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2878 // Return the generated code. | 2885 // Return the generated code. |
| 2879 return GetCode(Code::NORMAL, name); | 2886 return GetCode(Code::NORMAL, name); |
| 2880 } | 2887 } |
| 2881 | 2888 |
| 2882 | 2889 |
| 2883 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2890 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
| 2884 Handle<JSObject> object, | 2891 Handle<JSObject> object, |
| 2885 Handle<JSObject> holder, | 2892 Handle<JSObject> holder, |
| 2886 Handle<Name> name, | 2893 Handle<Name> name, |
| 2887 Handle<ExecutableAccessorInfo> callback) { | 2894 Handle<ExecutableAccessorInfo> callback) { |
| 2888 Label success; | 2895 HandlerFrontend(object, receiver(), holder, name); |
| 2889 HandlerFrontend(object, receiver(), holder, name, &success); | |
| 2890 __ bind(&success); | |
| 2891 | 2896 |
| 2892 __ pop(scratch1()); // remove the return address | 2897 __ pop(scratch1()); // remove the return address |
| 2893 __ push(receiver()); | 2898 __ push(receiver()); |
| 2894 __ Push(callback); | 2899 __ Push(callback); |
| 2895 __ Push(name); | 2900 __ Push(name); |
| 2896 __ push(value()); | 2901 __ push(value()); |
| 2897 __ push(scratch1()); // restore return address | 2902 __ push(scratch1()); // restore return address |
| 2898 | 2903 |
| 2899 // Do tail-call to the runtime system. | 2904 // Do tail-call to the runtime system. |
| 2900 ExternalReference store_callback_property = | 2905 ExternalReference store_callback_property = |
| 2901 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); | 2906 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); |
| 2902 __ TailCallExternalReference(store_callback_property, 4, 1); | 2907 __ TailCallExternalReference(store_callback_property, 4, 1); |
| 2903 | 2908 |
| 2904 // Return the generated code. | 2909 // Return the generated code. |
| 2905 return GetCode(kind(), Code::CALLBACKS, name); | 2910 return GetCode(kind(), Code::CALLBACKS, name); |
| 2906 } | 2911 } |
| 2907 | 2912 |
| 2908 | 2913 |
| 2909 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2914 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
| 2910 Handle<JSObject> object, | 2915 Handle<JSObject> object, |
| 2911 Handle<JSObject> holder, | 2916 Handle<JSObject> holder, |
| 2912 Handle<Name> name, | 2917 Handle<Name> name, |
| 2913 const CallOptimization& call_optimization) { | 2918 const CallOptimization& call_optimization) { |
| 2914 Label success; | 2919 HandlerFrontend(object, receiver(), holder, name); |
| 2915 HandlerFrontend(object, receiver(), holder, name, &success); | |
| 2916 __ bind(&success); | |
| 2917 | 2920 |
| 2918 Register values[] = { value() }; | 2921 Register values[] = { value() }; |
| 2919 GenerateFastApiCall( | 2922 GenerateFastApiCall( |
| 2920 masm(), call_optimization, receiver(), scratch1(), 1, values); | 2923 masm(), call_optimization, receiver(), scratch1(), 1, values); |
| 2921 | 2924 |
| 2922 // Return the generated code. | 2925 // Return the generated code. |
| 2923 return GetCode(kind(), Code::CALLBACKS, name); | 2926 return GetCode(kind(), Code::CALLBACKS, name); |
| 2924 } | 2927 } |
| 2925 | 2928 |
| 2926 | 2929 |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3013 __ bind(&miss); | 3016 __ bind(&miss); |
| 3014 TailCallBuiltin(masm(), MissBuiltin(kind())); | 3017 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 3015 | 3018 |
| 3016 // Return the generated code. | 3019 // Return the generated code. |
| 3017 return GetICCode( | 3020 return GetICCode( |
| 3018 kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); | 3021 kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); |
| 3019 } | 3022 } |
| 3020 | 3023 |
| 3021 | 3024 |
| 3022 Handle<Code> LoadStubCompiler::CompileLoadNonexistent( | 3025 Handle<Code> LoadStubCompiler::CompileLoadNonexistent( |
| 3023 Handle<JSObject> object, | 3026 Handle<Object> object, |
| 3024 Handle<JSObject> last, | 3027 Handle<JSObject> last, |
| 3025 Handle<Name> name, | 3028 Handle<Name> name, |
| 3026 Handle<JSGlobalObject> global) { | 3029 Handle<JSGlobalObject> global) { |
| 3027 Label success; | 3030 NonexistentHandlerFrontend(object, last, name, global); |
| 3028 | 3031 |
| 3029 NonexistentHandlerFrontend(object, last, name, &success, global); | |
| 3030 | |
| 3031 __ bind(&success); | |
| 3032 // Return undefined if maps of the full prototype chain are still the | 3032 // Return undefined if maps of the full prototype chain are still the |
| 3033 // same and no global property with this name contains a value. | 3033 // same and no global property with this name contains a value. |
| 3034 __ mov(eax, isolate()->factory()->undefined_value()); | 3034 __ mov(eax, isolate()->factory()->undefined_value()); |
| 3035 __ ret(0); | 3035 __ ret(0); |
| 3036 | 3036 |
| 3037 // Return the generated code. | 3037 // Return the generated code. |
| 3038 return GetCode(kind(), Code::NONEXISTENT, name); | 3038 return GetCode(kind(), Code::NONEXISTENT, name); |
| 3039 } | 3039 } |
| 3040 | 3040 |
| 3041 | 3041 |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3111 } | 3111 } |
| 3112 __ ret(0); | 3112 __ ret(0); |
| 3113 } | 3113 } |
| 3114 | 3114 |
| 3115 | 3115 |
| 3116 #undef __ | 3116 #undef __ |
| 3117 #define __ ACCESS_MASM(masm()) | 3117 #define __ ACCESS_MASM(masm()) |
| 3118 | 3118 |
| 3119 | 3119 |
| 3120 Handle<Code> LoadStubCompiler::CompileLoadGlobal( | 3120 Handle<Code> LoadStubCompiler::CompileLoadGlobal( |
| 3121 Handle<JSObject> object, | 3121 Handle<Object> object, |
| 3122 Handle<GlobalObject> global, | 3122 Handle<GlobalObject> global, |
| 3123 Handle<PropertyCell> cell, | 3123 Handle<PropertyCell> cell, |
| 3124 Handle<Name> name, | 3124 Handle<Name> name, |
| 3125 bool is_dont_delete) { | 3125 bool is_dont_delete) { |
| 3126 Label success, miss; | 3126 Label miss; |
| 3127 | 3127 |
| 3128 HandlerFrontendHeader(object, receiver(), global, name, &miss); | 3128 HandlerFrontendHeader(object, receiver(), global, name, &miss); |
| 3129 // Get the value from the cell. | 3129 // Get the value from the cell. |
| 3130 if (Serializer::enabled()) { | 3130 if (Serializer::enabled()) { |
| 3131 __ mov(eax, Immediate(cell)); | 3131 __ mov(eax, Immediate(cell)); |
| 3132 __ mov(eax, FieldOperand(eax, PropertyCell::kValueOffset)); | 3132 __ mov(eax, FieldOperand(eax, PropertyCell::kValueOffset)); |
| 3133 } else { | 3133 } else { |
| 3134 __ mov(eax, Operand::ForCell(cell)); | 3134 __ mov(eax, Operand::ForCell(cell)); |
| 3135 } | 3135 } |
| 3136 | 3136 |
| 3137 // Check for deleted property if property can actually be deleted. | 3137 // Check for deleted property if property can actually be deleted. |
| 3138 if (!is_dont_delete) { | 3138 if (!is_dont_delete) { |
| 3139 __ cmp(eax, factory()->the_hole_value()); | 3139 __ cmp(eax, factory()->the_hole_value()); |
| 3140 __ j(equal, &miss); | 3140 __ j(equal, &miss); |
| 3141 } else if (FLAG_debug_code) { | 3141 } else if (FLAG_debug_code) { |
| 3142 __ cmp(eax, factory()->the_hole_value()); | 3142 __ cmp(eax, factory()->the_hole_value()); |
| 3143 __ Check(not_equal, kDontDeleteCellsCannotContainTheHole); | 3143 __ Check(not_equal, kDontDeleteCellsCannotContainTheHole); |
| 3144 } | 3144 } |
| 3145 | 3145 |
| 3146 HandlerFrontendFooter(name, &success, &miss); | 3146 HandlerFrontendFooter(name, &miss); |
| 3147 __ bind(&success); | |
| 3148 | 3147 |
| 3149 Counters* counters = isolate()->counters(); | 3148 Counters* counters = isolate()->counters(); |
| 3150 __ IncrementCounter(counters->named_load_global_stub(), 1); | 3149 __ IncrementCounter(counters->named_load_global_stub(), 1); |
| 3151 // The code above already loads the result into the return register. | 3150 // The code above already loads the result into the return register. |
| 3152 __ ret(0); | 3151 __ ret(0); |
| 3153 | 3152 |
| 3154 // Return the generated code. | 3153 // Return the generated code. |
| 3155 return GetCode(kind(), Code::NORMAL, name); | 3154 return GetCode(kind(), Code::NORMAL, name); |
| 3156 } | 3155 } |
| 3157 | 3156 |
| 3158 | 3157 |
| 3159 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC( | 3158 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC( |
| 3160 MapHandleList* receiver_maps, | 3159 MapHandleList* receiver_maps, |
| 3161 CodeHandleList* handlers, | 3160 CodeHandleList* handlers, |
| 3162 Handle<Name> name, | 3161 Handle<Name> name, |
| 3163 Code::StubType type, | 3162 Code::StubType type, |
| 3164 IcCheckType check) { | 3163 IcCheckType check) { |
| 3165 Label miss; | 3164 Label miss; |
| 3166 | 3165 |
| 3167 if (check == PROPERTY) { | 3166 if (check == PROPERTY) { |
| 3168 GenerateNameCheck(name, this->name(), &miss); | 3167 GenerateNameCheck(name, this->name(), &miss); |
| 3169 } | 3168 } |
| 3170 | 3169 |
| 3171 __ JumpIfSmi(receiver(), &miss); | 3170 Label number_case; |
| 3171 Label* smi_target = HasHeapNumberMap(receiver_maps) ? &number_case : &miss; |
| 3172 __ JumpIfSmi(receiver(), smi_target); |
| 3173 |
| 3172 Register map_reg = scratch1(); | 3174 Register map_reg = scratch1(); |
| 3173 __ mov(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset)); | 3175 __ mov(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset)); |
| 3174 int receiver_count = receiver_maps->length(); | 3176 int receiver_count = receiver_maps->length(); |
| 3175 int number_of_handled_maps = 0; | 3177 int number_of_handled_maps = 0; |
| 3178 Handle<Map> heap_number_map = isolate()->factory()->heap_number_map(); |
| 3176 for (int current = 0; current < receiver_count; ++current) { | 3179 for (int current = 0; current < receiver_count; ++current) { |
| 3177 Handle<Map> map = receiver_maps->at(current); | 3180 Handle<Map> map = receiver_maps->at(current); |
| 3178 if (!map->is_deprecated()) { | 3181 if (!map->is_deprecated()) { |
| 3179 number_of_handled_maps++; | 3182 number_of_handled_maps++; |
| 3180 __ cmp(map_reg, map); | 3183 __ cmp(map_reg, map); |
| 3184 if (map.is_identical_to(heap_number_map)) { |
| 3185 ASSERT(!number_case.is_unused()); |
| 3186 __ bind(&number_case); |
| 3187 } |
| 3181 __ j(equal, handlers->at(current)); | 3188 __ j(equal, handlers->at(current)); |
| 3182 } | 3189 } |
| 3183 } | 3190 } |
| 3184 ASSERT(number_of_handled_maps != 0); | 3191 ASSERT(number_of_handled_maps != 0); |
| 3185 | 3192 |
| 3186 __ bind(&miss); | 3193 __ bind(&miss); |
| 3187 TailCallBuiltin(masm(), MissBuiltin(kind())); | 3194 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 3188 | 3195 |
| 3189 // Return the generated code. | 3196 // Return the generated code. |
| 3190 InlineCacheState state = | 3197 InlineCacheState state = |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3239 // ----------------------------------- | 3246 // ----------------------------------- |
| 3240 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); | 3247 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); |
| 3241 } | 3248 } |
| 3242 | 3249 |
| 3243 | 3250 |
| 3244 #undef __ | 3251 #undef __ |
| 3245 | 3252 |
| 3246 } } // namespace v8::internal | 3253 } } // namespace v8::internal |
| 3247 | 3254 |
| 3248 #endif // V8_TARGET_ARCH_IA32 | 3255 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |