| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 1268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1279 // If we've skipped any global objects, it's not enough to verify that | 1279 // If we've skipped any global objects, it's not enough to verify that |
| 1280 // their maps haven't changed. We also need to check that the property | 1280 // their maps haven't changed. We also need to check that the property |
| 1281 // cell for the property is still empty. | 1281 // cell for the property is still empty. |
| 1282 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); | 1282 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); |
| 1283 | 1283 |
| 1284 // Return the register containing the holder. | 1284 // Return the register containing the holder. |
| 1285 return reg; | 1285 return reg; |
| 1286 } | 1286 } |
| 1287 | 1287 |
| 1288 | 1288 |
| 1289 void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, | 1289 void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { |
| 1290 Label* success, | |
| 1291 Label* miss) { | |
| 1292 if (!miss->is_unused()) { | 1290 if (!miss->is_unused()) { |
| 1293 __ B(success); | 1291 Label success; |
| 1292 __ B(&success); |
| 1293 |
| 1294 __ Bind(miss); | 1294 __ Bind(miss); |
| 1295 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1295 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1296 |
| 1297 __ Bind(&success); |
| 1296 } | 1298 } |
| 1297 } | 1299 } |
| 1298 | 1300 |
| 1299 | 1301 |
| 1300 void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, | 1302 void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { |
| 1301 Label* success, | |
| 1302 Label* miss) { | |
| 1303 if (!miss->is_unused()) { | 1303 if (!miss->is_unused()) { |
| 1304 __ B(success); | 1304 Label success; |
| 1305 __ B(&success); |
| 1306 |
| 1305 GenerateRestoreName(masm(), miss, name); | 1307 GenerateRestoreName(masm(), miss, name); |
| 1306 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1308 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1309 |
| 1310 __ Bind(&success); |
| 1307 } | 1311 } |
| 1308 } | 1312 } |
| 1309 | 1313 |
| 1310 | 1314 |
| 1311 Register LoadStubCompiler::CallbackHandlerFrontend(Handle<JSObject> object, | 1315 Register LoadStubCompiler::CallbackHandlerFrontend(Handle<Object> object, |
| 1312 Register object_reg, | 1316 Register object_reg, |
| 1313 Handle<JSObject> holder, | 1317 Handle<JSObject> holder, |
| 1314 Handle<Name> name, | 1318 Handle<Name> name, |
| 1315 Label* success, | |
| 1316 Handle<Object> callback) { | 1319 Handle<Object> callback) { |
| 1317 Label miss; | 1320 Label miss; |
| 1318 | 1321 |
| 1319 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); | 1322 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); |
| 1320 | 1323 |
| 1321 // TODO(jbramely): HandlerFrontendHeader returns its result in scratch1(), so | 1324 // TODO(jbramely): HandlerFrontendHeader returns its result in scratch1(), so |
| 1322 // we can't use it below, but that isn't very obvious. Is there a better way | 1325 // we can't use it below, but that isn't very obvious. Is there a better way |
| 1323 // of handling this? | 1326 // of handling this? |
| 1324 | 1327 |
| 1325 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { | 1328 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1344 // pointer into the dictionary. Check that the value is the callback. | 1347 // pointer into the dictionary. Check that the value is the callback. |
| 1345 Register pointer = scratch3(); | 1348 Register pointer = scratch3(); |
| 1346 const int kElementsStartOffset = NameDictionary::kHeaderSize + | 1349 const int kElementsStartOffset = NameDictionary::kHeaderSize + |
| 1347 NameDictionary::kElementsStartIndex * kPointerSize; | 1350 NameDictionary::kElementsStartIndex * kPointerSize; |
| 1348 const int kValueOffset = kElementsStartOffset + kPointerSize; | 1351 const int kValueOffset = kElementsStartOffset + kPointerSize; |
| 1349 __ Ldr(scratch2(), FieldMemOperand(pointer, kValueOffset)); | 1352 __ Ldr(scratch2(), FieldMemOperand(pointer, kValueOffset)); |
| 1350 __ Cmp(scratch2(), Operand(callback)); | 1353 __ Cmp(scratch2(), Operand(callback)); |
| 1351 __ B(ne, &miss); | 1354 __ B(ne, &miss); |
| 1352 } | 1355 } |
| 1353 | 1356 |
| 1354 HandlerFrontendFooter(name, success, &miss); | 1357 HandlerFrontendFooter(name, &miss); |
| 1355 return reg; | 1358 return reg; |
| 1356 } | 1359 } |
| 1357 | 1360 |
| 1358 | 1361 |
| 1359 void LoadStubCompiler::GenerateLoadField(Register reg, | 1362 void LoadStubCompiler::GenerateLoadField(Register reg, |
| 1360 Handle<JSObject> holder, | 1363 Handle<JSObject> holder, |
| 1361 PropertyIndex field, | 1364 PropertyIndex field, |
| 1362 Representation representation) { | 1365 Representation representation) { |
| 1363 __ Mov(receiver(), reg); | 1366 __ Mov(receiver(), reg); |
| 1364 if (kind() == Code::LOAD_IC) { | 1367 if (kind() == Code::LOAD_IC) { |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1484 x2, | 1487 x2, |
| 1485 kStackUnwindSpace, | 1488 kStackUnwindSpace, |
| 1486 spill_offset, | 1489 spill_offset, |
| 1487 MemOperand(fp, 6 * kPointerSize), | 1490 MemOperand(fp, 6 * kPointerSize), |
| 1488 NULL); | 1491 NULL); |
| 1489 } | 1492 } |
| 1490 | 1493 |
| 1491 | 1494 |
| 1492 void LoadStubCompiler::GenerateLoadInterceptor( | 1495 void LoadStubCompiler::GenerateLoadInterceptor( |
| 1493 Register holder_reg, | 1496 Register holder_reg, |
| 1494 Handle<JSObject> object, | 1497 Handle<Object> object, |
| 1495 Handle<JSObject> interceptor_holder, | 1498 Handle<JSObject> interceptor_holder, |
| 1496 LookupResult* lookup, | 1499 LookupResult* lookup, |
| 1497 Handle<Name> name) { | 1500 Handle<Name> name) { |
| 1498 ASSERT(!AreAliased(receiver(), this->name(), | 1501 ASSERT(!AreAliased(receiver(), this->name(), |
| 1499 scratch1(), scratch2(), scratch3())); | 1502 scratch1(), scratch2(), scratch3())); |
| 1500 ASSERT(interceptor_holder->HasNamedInterceptor()); | 1503 ASSERT(interceptor_holder->HasNamedInterceptor()); |
| 1501 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 1504 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); |
| 1502 | 1505 |
| 1503 // So far the most popular follow ups for interceptor loads are FIELD | 1506 // So far the most popular follow ups for interceptor loads are FIELD |
| 1504 // and CALLBACKS, so inline only them, other cases may be added later. | 1507 // and CALLBACKS, so inline only them, other cases may be added later. |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1719 CheckPrototypes(Handle<JSObject>::cast(object), receiver, holder, x3, x0, | 1722 CheckPrototypes(Handle<JSObject>::cast(object), receiver, holder, x3, x0, |
| 1720 x4, name, &miss); | 1723 x4, name, &miss); |
| 1721 } else { | 1724 } else { |
| 1722 ASSERT(cell->value() == *function); | 1725 ASSERT(cell->value() == *function); |
| 1723 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | 1726 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 1724 &miss); | 1727 &miss); |
| 1725 GenerateLoadFunctionFromCell(cell, function, &miss); | 1728 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 1726 } | 1729 } |
| 1727 | 1730 |
| 1728 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite(); | 1731 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite(); |
| 1729 site->set_transition_info(Smi::FromInt(GetInitialFastElementsKind())); | 1732 site->SetElementsKind(GetInitialFastElementsKind()); |
| 1730 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site); | 1733 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site); |
| 1731 __ Mov(x0, argc); | 1734 __ Mov(x0, argc); |
| 1732 __ Mov(x1, Operand(function)); | 1735 __ Mov(x1, Operand(function)); |
| 1733 __ Mov(x2, Operand(site_feedback_cell)); | 1736 __ Mov(x2, Operand(site_feedback_cell)); |
| 1734 | 1737 |
| 1735 ArrayConstructorStub stub(isolate()); | 1738 ArrayConstructorStub stub(isolate()); |
| 1736 __ TailCallStub(&stub); | 1739 __ TailCallStub(&stub); |
| 1737 | 1740 |
| 1738 __ Bind(&miss); | 1741 __ Bind(&miss); |
| 1739 GenerateMissBranch(); | 1742 GenerateMissBranch(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1751 Handle<String> name, | 1754 Handle<String> name, |
| 1752 Code::StubType type) { | 1755 Code::StubType type) { |
| 1753 // ----------- S t a t e ------------- | 1756 // ----------- S t a t e ------------- |
| 1754 // -- x2 : name (Must be preserved on miss.) | 1757 // -- x2 : name (Must be preserved on miss.) |
| 1755 // -- lr : return address | 1758 // -- lr : return address |
| 1756 // -- sp[(argc - n - 1) * 8] : arg[n] (zero-based) | 1759 // -- sp[(argc - n - 1) * 8] : arg[n] (zero-based) |
| 1757 // -- ... | 1760 // -- ... |
| 1758 // -- sp[argc * 8] : receiver | 1761 // -- sp[argc * 8] : receiver |
| 1759 // ----------------------------------- | 1762 // ----------------------------------- |
| 1760 | 1763 |
| 1761 // If object is not an array, bail out to regular call. | 1764 // If object is not an array or is observed, bail out to regular call. |
| 1762 if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null(); | 1765 if (!object->IsJSArray() || |
| 1766 !cell.is_null() || |
| 1767 Handle<JSArray>::cast(object)->map()->is_observed()) { |
| 1768 return Handle<Code>::null(); |
| 1769 } |
| 1763 | 1770 |
| 1764 Label miss; | 1771 Label miss; |
| 1765 Register result = x0; | 1772 Register result = x0; |
| 1766 const int argc = arguments().immediate(); | 1773 const int argc = arguments().immediate(); |
| 1767 | 1774 |
| 1768 GenerateNameCheck(name, &miss); | 1775 GenerateNameCheck(name, &miss); |
| 1769 | 1776 |
| 1770 // Get the receiver from the stack | 1777 // Get the receiver from the stack |
| 1771 Register receiver = x1; | 1778 Register receiver = x1; |
| 1772 __ Peek(receiver, argc * kPointerSize); | 1779 __ Peek(receiver, argc * kPointerSize); |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2021 Handle<String> name, | 2028 Handle<String> name, |
| 2022 Code::StubType type) { | 2029 Code::StubType type) { |
| 2023 // ----------- S t a t e ------------- | 2030 // ----------- S t a t e ------------- |
| 2024 // -- x2 : name | 2031 // -- x2 : name |
| 2025 // -- lr : return address | 2032 // -- lr : return address |
| 2026 // -- sp[(argc - n - 1) * 8] : arg[n] (zero-based) | 2033 // -- sp[(argc - n - 1) * 8] : arg[n] (zero-based) |
| 2027 // -- ... | 2034 // -- ... |
| 2028 // -- sp[argc * 8] : receiver | 2035 // -- sp[argc * 8] : receiver |
| 2029 // ----------------------------------- | 2036 // ----------------------------------- |
| 2030 | 2037 |
| 2031 // If object is not an array, bail out to regular call. | 2038 // If object is not an array or is observed, bail out to regular call. |
| 2032 if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null(); | 2039 if (!object->IsJSArray() || |
| 2040 !cell.is_null() || |
| 2041 Handle<JSArray>::cast(object)->map()->is_observed()) { |
| 2042 return Handle<Code>::null(); |
| 2043 } |
| 2033 | 2044 |
| 2034 const int argc = arguments().immediate(); | 2045 const int argc = arguments().immediate(); |
| 2035 Register result = x0; | 2046 Register result = x0; |
| 2036 Label miss, return_undefined, call_builtin; | 2047 Label miss, return_undefined, call_builtin; |
| 2037 | 2048 |
| 2038 GenerateNameCheck(name, &miss); | 2049 GenerateNameCheck(name, &miss); |
| 2039 | 2050 |
| 2040 // Get the receiver from the stack | 2051 // Get the receiver from the stack |
| 2041 Register receiver = x1; | 2052 Register receiver = x1; |
| 2042 __ Peek(receiver, argc * kPointerSize); | 2053 __ Peek(receiver, argc * kPointerSize); |
| (...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2591 FreeSpaceForFastApiCall(masm()); | 2602 FreeSpaceForFastApiCall(masm()); |
| 2592 | 2603 |
| 2593 __ Bind(&miss_before_stack_reserved); | 2604 __ Bind(&miss_before_stack_reserved); |
| 2594 GenerateMissBranch(); | 2605 GenerateMissBranch(); |
| 2595 | 2606 |
| 2596 // Return the generated code. | 2607 // Return the generated code. |
| 2597 return GetCode(function); | 2608 return GetCode(function); |
| 2598 } | 2609 } |
| 2599 | 2610 |
| 2600 | 2611 |
| 2612 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { |
| 2613 Label success; |
| 2614 // Check that the object is a boolean. |
| 2615 // TODO(all): Optimize this like LCodeGen::DoDeferredTaggedToI. |
| 2616 __ JumpIfRoot(object, Heap::kTrueValueRootIndex, &success); |
| 2617 __ JumpIfNotRoot(object, Heap::kFalseValueRootIndex, miss); |
| 2618 __ Bind(&success); |
| 2619 } |
| 2620 |
| 2621 |
| 2601 void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object, | 2622 void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object, |
| 2602 Handle<JSObject> holder, | 2623 Handle<JSObject> holder, |
| 2603 Handle<Name> name, | 2624 Handle<Name> name, |
| 2604 CheckType check, | 2625 CheckType check) { |
| 2605 Label* success) { | |
| 2606 // ----------- S t a t e ------------- | 2626 // ----------- S t a t e ------------- |
| 2607 // -- x2 : name | 2627 // -- x2 : name |
| 2608 // -- lr : return address | 2628 // -- lr : return address |
| 2609 // ----------------------------------- | 2629 // ----------------------------------- |
| 2610 Label miss; | 2630 Label miss; |
| 2611 GenerateNameCheck(name, &miss); | 2631 GenerateNameCheck(name, &miss); |
| 2612 | 2632 |
| 2613 // Get the receiver from the stack. | 2633 // Get the receiver from the stack. |
| 2614 const int argc = arguments().immediate(); | 2634 const int argc = arguments().immediate(); |
| 2615 Register receiver = x1; | 2635 Register receiver = x1; |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2674 // Check that the maps starting from the prototype haven't changed. | 2694 // Check that the maps starting from the prototype haven't changed. |
| 2675 Register prototype = x0; | 2695 Register prototype = x0; |
| 2676 GenerateDirectLoadGlobalFunctionPrototype( | 2696 GenerateDirectLoadGlobalFunctionPrototype( |
| 2677 masm(), Context::NUMBER_FUNCTION_INDEX, prototype, &miss); | 2697 masm(), Context::NUMBER_FUNCTION_INDEX, prototype, &miss); |
| 2678 CheckPrototypes( | 2698 CheckPrototypes( |
| 2679 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2699 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), |
| 2680 prototype, holder, x3, x1, x4, name, &miss); | 2700 prototype, holder, x3, x1, x4, name, &miss); |
| 2681 break; | 2701 break; |
| 2682 } | 2702 } |
| 2683 case BOOLEAN_CHECK: { | 2703 case BOOLEAN_CHECK: { |
| 2684 Label fast; | 2704 GenerateBooleanCheck(receiver, &miss); |
| 2685 // Check that the object is a boolean. | |
| 2686 __ JumpIfRoot(receiver, Heap::kTrueValueRootIndex, &fast); | |
| 2687 __ JumpIfNotRoot(receiver, Heap::kFalseValueRootIndex, &miss); | |
| 2688 | 2705 |
| 2689 __ Bind(&fast); | |
| 2690 // Check that the maps starting from the prototype haven't changed. | 2706 // Check that the maps starting from the prototype haven't changed. |
| 2691 Register prototype = x0; | 2707 Register prototype = x0; |
| 2692 GenerateDirectLoadGlobalFunctionPrototype( | 2708 GenerateDirectLoadGlobalFunctionPrototype( |
| 2693 masm(), Context::BOOLEAN_FUNCTION_INDEX, prototype, &miss); | 2709 masm(), Context::BOOLEAN_FUNCTION_INDEX, prototype, &miss); |
| 2694 CheckPrototypes( | 2710 CheckPrototypes( |
| 2695 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2711 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), |
| 2696 prototype, holder, x3, x1, x4, name, &miss); | 2712 prototype, holder, x3, x1, x4, name, &miss); |
| 2697 break; | 2713 break; |
| 2698 } | 2714 } |
| 2699 } | 2715 } |
| 2700 | 2716 |
| 2701 __ B(success); | 2717 Label success; |
| 2718 __ B(&success); |
| 2702 | 2719 |
| 2703 // Handle call cache miss. | 2720 // Handle call cache miss. |
| 2704 __ Bind(&miss); | 2721 __ Bind(&miss); |
| 2705 GenerateMissBranch(); | 2722 GenerateMissBranch(); |
| 2723 |
| 2724 __ Bind(&success); |
| 2706 } | 2725 } |
| 2707 | 2726 |
| 2708 | 2727 |
| 2709 void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) { | 2728 void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) { |
| 2710 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2729 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2711 ? CALL_AS_FUNCTION | 2730 ? CALL_AS_FUNCTION |
| 2712 : CALL_AS_METHOD; | 2731 : CALL_AS_METHOD; |
| 2713 ParameterCount expected(function); | 2732 ParameterCount expected(function); |
| 2714 __ InvokeFunction(function, expected, arguments(), | 2733 __ InvokeFunction(function, expected, arguments(), |
| 2715 JUMP_FUNCTION, NullCallWrapper(), call_kind); | 2734 JUMP_FUNCTION, NullCallWrapper(), call_kind); |
| 2716 } | 2735 } |
| 2717 | 2736 |
| 2718 | 2737 |
| 2719 Handle<Code> CallStubCompiler::CompileCallConstant( | 2738 Handle<Code> CallStubCompiler::CompileCallConstant( |
| 2720 Handle<Object> object, | 2739 Handle<Object> object, |
| 2721 Handle<JSObject> holder, | 2740 Handle<JSObject> holder, |
| 2722 Handle<Name> name, | 2741 Handle<Name> name, |
| 2723 CheckType check, | 2742 CheckType check, |
| 2724 Handle<JSFunction> function) { | 2743 Handle<JSFunction> function) { |
| 2725 if (HasCustomCallGenerator(function)) { | 2744 if (HasCustomCallGenerator(function)) { |
| 2726 Handle<Code> code = CompileCustomCall(object, holder, | 2745 Handle<Code> code = CompileCustomCall(object, holder, |
| 2727 Handle<Cell>::null(), | 2746 Handle<Cell>::null(), |
| 2728 function, Handle<String>::cast(name), | 2747 function, Handle<String>::cast(name), |
| 2729 Code::CONSTANT); | 2748 Code::CONSTANT); |
| 2730 // A null handle means bail out to the regular compiler code below. | 2749 // A null handle means bail out to the regular compiler code below. |
| 2731 if (!code.is_null()) return code; | 2750 if (!code.is_null()) return code; |
| 2732 } | 2751 } |
| 2733 | 2752 |
| 2734 Label success; | 2753 CompileHandlerFrontend(object, holder, name, check); |
| 2735 | |
| 2736 CompileHandlerFrontend(object, holder, name, check, &success); | |
| 2737 __ Bind(&success); | |
| 2738 CompileHandlerBackend(function); | 2754 CompileHandlerBackend(function); |
| 2739 | 2755 |
| 2740 // Return the generated code. | 2756 // Return the generated code. |
| 2741 return GetCode(function); | 2757 return GetCode(function); |
| 2742 } | 2758 } |
| 2743 | 2759 |
| 2744 | 2760 |
| 2745 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, | 2761 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, |
| 2746 Handle<JSObject> holder, | 2762 Handle<JSObject> holder, |
| 2747 Handle<Name> name) { | 2763 Handle<Name> name) { |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2849 return GetCode(Code::NORMAL, name); | 2865 return GetCode(Code::NORMAL, name); |
| 2850 } | 2866 } |
| 2851 | 2867 |
| 2852 | 2868 |
| 2853 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2869 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
| 2854 Handle<JSObject> object, | 2870 Handle<JSObject> object, |
| 2855 Handle<JSObject> holder, | 2871 Handle<JSObject> holder, |
| 2856 Handle<Name> name, | 2872 Handle<Name> name, |
| 2857 Handle<ExecutableAccessorInfo> callback) { | 2873 Handle<ExecutableAccessorInfo> callback) { |
| 2858 ASM_LOCATION("StoreStubCompiler::CompileStoreCallback"); | 2874 ASM_LOCATION("StoreStubCompiler::CompileStoreCallback"); |
| 2859 | 2875 HandlerFrontend(object, receiver(), holder, name); |
| 2860 Label success; | |
| 2861 HandlerFrontend(object, receiver(), holder, name, &success); | |
| 2862 __ Bind(&success); | |
| 2863 | 2876 |
| 2864 // Stub never generated for non-global objects that require access checks. | 2877 // Stub never generated for non-global objects that require access checks. |
| 2865 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | 2878 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
| 2866 | 2879 |
| 2867 __ Mov(scratch1(), Operand(callback)); | 2880 __ Mov(scratch1(), Operand(callback)); |
| 2868 __ Mov(scratch2(), Operand(name)); | 2881 __ Mov(scratch2(), Operand(name)); |
| 2869 __ Push(receiver(), scratch1(), scratch2(), value()); | 2882 __ Push(receiver(), scratch1(), scratch2(), value()); |
| 2870 | 2883 |
| 2871 // Do tail-call to the runtime system. | 2884 // Do tail-call to the runtime system. |
| 2872 ExternalReference store_callback_property = | 2885 ExternalReference store_callback_property = |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2958 // Handle store cache miss. | 2971 // Handle store cache miss. |
| 2959 __ Bind(&miss); | 2972 __ Bind(&miss); |
| 2960 TailCallBuiltin(masm(), MissBuiltin(kind())); | 2973 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 2961 | 2974 |
| 2962 // Return the generated code. | 2975 // Return the generated code. |
| 2963 return GetCode(kind(), Code::INTERCEPTOR, name); | 2976 return GetCode(kind(), Code::INTERCEPTOR, name); |
| 2964 } | 2977 } |
| 2965 | 2978 |
| 2966 | 2979 |
| 2967 Handle<Code> LoadStubCompiler::CompileLoadNonexistent( | 2980 Handle<Code> LoadStubCompiler::CompileLoadNonexistent( |
| 2968 Handle<JSObject> object, | 2981 Handle<Object> object, |
| 2969 Handle<JSObject> last, | 2982 Handle<JSObject> last, |
| 2970 Handle<Name> name, | 2983 Handle<Name> name, |
| 2971 Handle<JSGlobalObject> global) { | 2984 Handle<JSGlobalObject> global) { |
| 2972 Label success; | 2985 NonexistentHandlerFrontend(object, last, name, global); |
| 2973 NonexistentHandlerFrontend(object, last, name, &success, global); | |
| 2974 | 2986 |
| 2975 __ Bind(&success); | |
| 2976 // Return undefined if maps of the full prototype chain are still the | 2987 // Return undefined if maps of the full prototype chain are still the |
| 2977 // same and no global property with this name contains a value. | 2988 // same and no global property with this name contains a value. |
| 2978 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); | 2989 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); |
| 2979 __ Ret(); | 2990 __ Ret(); |
| 2980 | 2991 |
| 2981 // Return the generated code. | 2992 // Return the generated code. |
| 2982 return GetCode(kind(), Code::NONEXISTENT, name); | 2993 return GetCode(kind(), Code::NONEXISTENT, name); |
| 2983 } | 2994 } |
| 2984 | 2995 |
| 2985 | 2996 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3066 } | 3077 } |
| 3067 __ Ret(); | 3078 __ Ret(); |
| 3068 } | 3079 } |
| 3069 | 3080 |
| 3070 | 3081 |
| 3071 #undef __ | 3082 #undef __ |
| 3072 #define __ ACCESS_MASM(masm()) | 3083 #define __ ACCESS_MASM(masm()) |
| 3073 | 3084 |
| 3074 | 3085 |
| 3075 Handle<Code> LoadStubCompiler::CompileLoadGlobal( | 3086 Handle<Code> LoadStubCompiler::CompileLoadGlobal( |
| 3076 Handle<JSObject> object, | 3087 Handle<Object> object, |
| 3077 Handle<GlobalObject> global, | 3088 Handle<GlobalObject> global, |
| 3078 Handle<PropertyCell> cell, | 3089 Handle<PropertyCell> cell, |
| 3079 Handle<Name> name, | 3090 Handle<Name> name, |
| 3080 bool is_dont_delete) { | 3091 bool is_dont_delete) { |
| 3081 Label success, miss; | 3092 Label miss; |
| 3082 | 3093 |
| 3083 HandlerFrontendHeader(object, receiver(), global, name, &miss); | 3094 HandlerFrontendHeader(object, receiver(), global, name, &miss); |
| 3084 | 3095 |
| 3085 // Get the value from the cell. | 3096 // Get the value from the cell. |
| 3086 __ Mov(x3, Operand(cell)); | 3097 __ Mov(x3, Operand(cell)); |
| 3087 __ Ldr(x4, FieldMemOperand(x3, Cell::kValueOffset)); | 3098 __ Ldr(x4, FieldMemOperand(x3, Cell::kValueOffset)); |
| 3088 | 3099 |
| 3089 // Check for deleted property if property can actually be deleted. | 3100 // Check for deleted property if property can actually be deleted. |
| 3090 if (!is_dont_delete) { | 3101 if (!is_dont_delete) { |
| 3091 __ JumpIfRoot(x4, Heap::kTheHoleValueRootIndex, &miss); | 3102 __ JumpIfRoot(x4, Heap::kTheHoleValueRootIndex, &miss); |
| 3092 } | 3103 } |
| 3093 | 3104 |
| 3094 HandlerFrontendFooter(name, &success, &miss); | 3105 HandlerFrontendFooter(name, &miss); |
| 3095 __ Bind(&success); | |
| 3096 | 3106 |
| 3097 Counters* counters = isolate()->counters(); | 3107 Counters* counters = isolate()->counters(); |
| 3098 __ IncrementCounter(counters->named_load_global_stub(), 1, x1, x3); | 3108 __ IncrementCounter(counters->named_load_global_stub(), 1, x1, x3); |
| 3099 __ Mov(x0, x4); | 3109 __ Mov(x0, x4); |
| 3100 __ Ret(); | 3110 __ Ret(); |
| 3101 | 3111 |
| 3102 // Return the generated code. | 3112 // Return the generated code. |
| 3103 return GetCode(kind(), Code::NORMAL, name); | 3113 return GetCode(kind(), Code::NORMAL, name); |
| 3104 } | 3114 } |
| 3105 | 3115 |
| 3106 | 3116 |
| 3107 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC( | 3117 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC( |
| 3108 MapHandleList* receiver_maps, | 3118 MapHandleList* receiver_maps, |
| 3109 CodeHandleList* handlers, | 3119 CodeHandleList* handlers, |
| 3110 Handle<Name> name, | 3120 Handle<Name> name, |
| 3111 Code::StubType type, | 3121 Code::StubType type, |
| 3112 IcCheckType check) { | 3122 IcCheckType check) { |
| 3113 Label miss; | 3123 Label miss; |
| 3114 | 3124 |
| 3115 if (check == PROPERTY) { | 3125 if (check == PROPERTY) { |
| 3116 GenerateNameCheck(name, this->name(), &miss); | 3126 GenerateNameCheck(name, this->name(), &miss); |
| 3117 } | 3127 } |
| 3118 | 3128 |
| 3119 __ JumpIfSmi(receiver(), &miss); | 3129 Label number_case; |
| 3130 Label* smi_target = HasHeapNumberMap(receiver_maps) ? &number_case : &miss; |
| 3131 __ JumpIfSmi(receiver(), smi_target); |
| 3120 | 3132 |
| 3121 Register map_reg = scratch1(); | 3133 Register map_reg = scratch1(); |
| 3122 __ Ldr(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset)); | 3134 __ Ldr(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset)); |
| 3135 Handle<Map> heap_number_map = isolate()->factory()->heap_number_map(); |
| 3123 int receiver_count = receiver_maps->length(); | 3136 int receiver_count = receiver_maps->length(); |
| 3124 int number_of_handled_maps = 0; | 3137 int number_of_handled_maps = 0; |
| 3125 for (int current = 0; current < receiver_count; ++current) { | 3138 for (int current = 0; current < receiver_count; ++current) { |
| 3126 Handle<Map> map = receiver_maps->at(current); | 3139 Handle<Map> map = receiver_maps->at(current); |
| 3127 if (!map->is_deprecated()) { | 3140 if (!map->is_deprecated()) { |
| 3128 number_of_handled_maps++; | 3141 number_of_handled_maps++; |
| 3129 Label try_next; | 3142 Label try_next; |
| 3130 __ Cmp(map_reg, Operand(receiver_maps->at(current))); | 3143 __ Cmp(map_reg, Operand(receiver_maps->at(current))); |
| 3131 __ B(ne, &try_next); | 3144 __ B(ne, &try_next); |
| 3145 if (map.is_identical_to(heap_number_map)) { |
| 3146 ASSERT(!number_case.is_unused()); |
| 3147 __ Bind(&number_case); |
| 3148 } |
| 3132 __ Jump(handlers->at(current), RelocInfo::CODE_TARGET); | 3149 __ Jump(handlers->at(current), RelocInfo::CODE_TARGET); |
| 3133 __ Bind(&try_next); | 3150 __ Bind(&try_next); |
| 3134 } | 3151 } |
| 3135 } | 3152 } |
| 3136 ASSERT(number_of_handled_maps != 0); | 3153 ASSERT(number_of_handled_maps != 0); |
| 3137 | 3154 |
| 3138 __ Bind(&miss); | 3155 __ Bind(&miss); |
| 3139 TailCallBuiltin(masm(), MissBuiltin(kind())); | 3156 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 3140 | 3157 |
| 3141 // Return the generated code. | 3158 // Return the generated code. |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3177 return GetICCode( | 3194 return GetICCode( |
| 3178 kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); | 3195 kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); |
| 3179 } | 3196 } |
| 3180 | 3197 |
| 3181 | 3198 |
| 3182 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 3199 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
| 3183 Handle<JSObject> object, | 3200 Handle<JSObject> object, |
| 3184 Handle<JSObject> holder, | 3201 Handle<JSObject> holder, |
| 3185 Handle<Name> name, | 3202 Handle<Name> name, |
| 3186 const CallOptimization& call_optimization) { | 3203 const CallOptimization& call_optimization) { |
| 3187 Label success; | 3204 HandlerFrontend(object, receiver(), holder, name); |
| 3188 HandlerFrontend(object, receiver(), holder, name, &success); | |
| 3189 __ Bind(&success); | |
| 3190 | 3205 |
| 3191 Register values[] = { value() }; | 3206 Register values[] = { value() }; |
| 3192 GenerateFastApiCall( | 3207 GenerateFastApiCall( |
| 3193 masm(), call_optimization, receiver(), scratch3(), 1, values); | 3208 masm(), call_optimization, receiver(), scratch3(), 1, values); |
| 3194 | 3209 |
| 3195 // Return the generated code. | 3210 // Return the generated code. |
| 3196 return GetCode(kind(), Code::CALLBACKS, name); | 3211 return GetCode(kind(), Code::CALLBACKS, name); |
| 3197 } | 3212 } |
| 3198 | 3213 |
| 3199 | 3214 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 3225 | 3240 |
| 3226 // Miss case, call the runtime. | 3241 // Miss case, call the runtime. |
| 3227 __ Bind(&miss_force_generic); | 3242 __ Bind(&miss_force_generic); |
| 3228 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); | 3243 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); |
| 3229 } | 3244 } |
| 3230 | 3245 |
| 3231 | 3246 |
| 3232 } } // namespace v8::internal | 3247 } } // namespace v8::internal |
| 3233 | 3248 |
| 3234 #endif // V8_TARGET_ARCH_A64 | 3249 #endif // V8_TARGET_ARCH_A64 |
| OLD | NEW |