| 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 1182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1193 // If we've skipped any global objects, it's not enough to verify that | 1193 // If we've skipped any global objects, it's not enough to verify that |
| 1194 // their maps haven't changed. We also need to check that the property | 1194 // their maps haven't changed. We also need to check that the property |
| 1195 // cell for the property is still empty. | 1195 // cell for the property is still empty. |
| 1196 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); | 1196 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); |
| 1197 | 1197 |
| 1198 // Return the register containing the holder. | 1198 // Return the register containing the holder. |
| 1199 return reg; | 1199 return reg; |
| 1200 } | 1200 } |
| 1201 | 1201 |
| 1202 | 1202 |
| 1203 void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, | 1203 void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { |
| 1204 Label* success, | |
| 1205 Label* miss) { | |
| 1206 if (!miss->is_unused()) { | 1204 if (!miss->is_unused()) { |
| 1207 __ jmp(success); | 1205 Label success; |
| 1206 __ jmp(&success); |
| 1208 __ bind(miss); | 1207 __ bind(miss); |
| 1209 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1208 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1209 __ bind(&success); |
| 1210 } | 1210 } |
| 1211 } | 1211 } |
| 1212 | 1212 |
| 1213 | 1213 |
| 1214 void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, | 1214 void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { |
| 1215 Label* success, | |
| 1216 Label* miss) { | |
| 1217 if (!miss->is_unused()) { | 1215 if (!miss->is_unused()) { |
| 1218 __ jmp(success); | 1216 Label success; |
| 1217 __ jmp(&success); |
| 1219 GenerateRestoreName(masm(), miss, name); | 1218 GenerateRestoreName(masm(), miss, name); |
| 1220 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1219 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1220 __ bind(&success); |
| 1221 } | 1221 } |
| 1222 } | 1222 } |
| 1223 | 1223 |
| 1224 | 1224 |
| 1225 Register LoadStubCompiler::CallbackHandlerFrontend( | 1225 Register LoadStubCompiler::CallbackHandlerFrontend( |
| 1226 Handle<JSObject> object, | 1226 Handle<Object> object, |
| 1227 Register object_reg, | 1227 Register object_reg, |
| 1228 Handle<JSObject> holder, | 1228 Handle<JSObject> holder, |
| 1229 Handle<Name> name, | 1229 Handle<Name> name, |
| 1230 Label* success, | |
| 1231 Handle<Object> callback) { | 1230 Handle<Object> callback) { |
| 1232 Label miss; | 1231 Label miss; |
| 1233 | 1232 |
| 1234 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); | 1233 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); |
| 1235 | 1234 |
| 1236 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { | 1235 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { |
| 1237 ASSERT(!reg.is(scratch2())); | 1236 ASSERT(!reg.is(scratch2())); |
| 1238 ASSERT(!reg.is(scratch3())); | 1237 ASSERT(!reg.is(scratch3())); |
| 1239 ASSERT(!reg.is(scratch4())); | 1238 ASSERT(!reg.is(scratch4())); |
| 1240 | 1239 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1261 NameDictionary::kElementsStartIndex * kPointerSize; | 1260 NameDictionary::kElementsStartIndex * kPointerSize; |
| 1262 const int kValueOffset = kElementsStartOffset + kPointerSize; | 1261 const int kValueOffset = kElementsStartOffset + kPointerSize; |
| 1263 __ movq(scratch2(), | 1262 __ movq(scratch2(), |
| 1264 Operand(dictionary, index, times_pointer_size, | 1263 Operand(dictionary, index, times_pointer_size, |
| 1265 kValueOffset - kHeapObjectTag)); | 1264 kValueOffset - kHeapObjectTag)); |
| 1266 __ movq(scratch3(), callback, RelocInfo::EMBEDDED_OBJECT); | 1265 __ movq(scratch3(), callback, RelocInfo::EMBEDDED_OBJECT); |
| 1267 __ cmpq(scratch2(), scratch3()); | 1266 __ cmpq(scratch2(), scratch3()); |
| 1268 __ j(not_equal, &miss); | 1267 __ j(not_equal, &miss); |
| 1269 } | 1268 } |
| 1270 | 1269 |
| 1271 HandlerFrontendFooter(name, success, &miss); | 1270 HandlerFrontendFooter(name, &miss); |
| 1272 return reg; | 1271 return reg; |
| 1273 } | 1272 } |
| 1274 | 1273 |
| 1275 | 1274 |
| 1276 void LoadStubCompiler::GenerateLoadField(Register reg, | 1275 void LoadStubCompiler::GenerateLoadField(Register reg, |
| 1277 Handle<JSObject> holder, | 1276 Handle<JSObject> holder, |
| 1278 PropertyIndex field, | 1277 PropertyIndex field, |
| 1279 Representation representation) { | 1278 Representation representation) { |
| 1280 if (!reg.is(receiver())) __ movq(receiver(), reg); | 1279 if (!reg.is(receiver())) __ movq(receiver(), reg); |
| 1281 if (kind() == Code::LOAD_IC) { | 1280 if (kind() == Code::LOAD_IC) { |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1382 | 1381 |
| 1383 void LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { | 1382 void LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { |
| 1384 // Return the constant value. | 1383 // Return the constant value. |
| 1385 __ Move(rax, value); | 1384 __ Move(rax, value); |
| 1386 __ ret(0); | 1385 __ ret(0); |
| 1387 } | 1386 } |
| 1388 | 1387 |
| 1389 | 1388 |
| 1390 void LoadStubCompiler::GenerateLoadInterceptor( | 1389 void LoadStubCompiler::GenerateLoadInterceptor( |
| 1391 Register holder_reg, | 1390 Register holder_reg, |
| 1392 Handle<JSObject> object, | 1391 Handle<Object> object, |
| 1393 Handle<JSObject> interceptor_holder, | 1392 Handle<JSObject> interceptor_holder, |
| 1394 LookupResult* lookup, | 1393 LookupResult* lookup, |
| 1395 Handle<Name> name) { | 1394 Handle<Name> name) { |
| 1396 ASSERT(interceptor_holder->HasNamedInterceptor()); | 1395 ASSERT(interceptor_holder->HasNamedInterceptor()); |
| 1397 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 1396 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); |
| 1398 | 1397 |
| 1399 // So far the most popular follow ups for interceptor loads are FIELD | 1398 // So far the most popular follow ups for interceptor loads are FIELD |
| 1400 // and CALLBACKS, so inline only them, other cases may be added | 1399 // and CALLBACKS, so inline only them, other cases may be added |
| 1401 // later. | 1400 // later. |
| 1402 bool compile_followup_inline = false; | 1401 bool compile_followup_inline = false; |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1622 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, | 1621 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, |
| 1623 name, &miss); | 1622 name, &miss); |
| 1624 } else { | 1623 } else { |
| 1625 ASSERT(cell->value() == *function); | 1624 ASSERT(cell->value() == *function); |
| 1626 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | 1625 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 1627 &miss); | 1626 &miss); |
| 1628 GenerateLoadFunctionFromCell(cell, function, &miss); | 1627 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 1629 } | 1628 } |
| 1630 | 1629 |
| 1631 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite(); | 1630 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite(); |
| 1632 site->set_transition_info(Smi::FromInt(GetInitialFastElementsKind())); | 1631 site->SetElementsKind(GetInitialFastElementsKind()); |
| 1633 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site); | 1632 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site); |
| 1634 __ movq(rax, Immediate(argc)); | 1633 __ movq(rax, Immediate(argc)); |
| 1635 __ Move(rbx, site_feedback_cell); | 1634 __ Move(rbx, site_feedback_cell); |
| 1636 __ Move(rdi, function); | 1635 __ Move(rdi, function); |
| 1637 | 1636 |
| 1638 ArrayConstructorStub stub(isolate()); | 1637 ArrayConstructorStub stub(isolate()); |
| 1639 __ TailCallStub(&stub); | 1638 __ TailCallStub(&stub); |
| 1640 | 1639 |
| 1641 __ bind(&miss); | 1640 __ bind(&miss); |
| 1642 GenerateMissBranch(); | 1641 GenerateMissBranch(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1654 Handle<String> name, | 1653 Handle<String> name, |
| 1655 Code::StubType type) { | 1654 Code::StubType type) { |
| 1656 // ----------- S t a t e ------------- | 1655 // ----------- S t a t e ------------- |
| 1657 // -- rcx : name | 1656 // -- rcx : name |
| 1658 // -- rsp[0] : return address | 1657 // -- rsp[0] : return address |
| 1659 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | 1658 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) |
| 1660 // -- ... | 1659 // -- ... |
| 1661 // -- rsp[(argc + 1) * 8] : receiver | 1660 // -- rsp[(argc + 1) * 8] : receiver |
| 1662 // ----------------------------------- | 1661 // ----------------------------------- |
| 1663 | 1662 |
| 1664 // If object is not an array, bail out to regular call. | 1663 // If object is not an array or is observed, bail out to regular call. |
| 1665 if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null(); | 1664 if (!object->IsJSArray() || |
| 1665 !cell.is_null() || |
| 1666 Handle<JSArray>::cast(object)->map()->is_observed()) { |
| 1667 return Handle<Code>::null(); |
| 1668 } |
| 1666 | 1669 |
| 1667 Label miss; | 1670 Label miss; |
| 1668 GenerateNameCheck(name, &miss); | 1671 GenerateNameCheck(name, &miss); |
| 1669 | 1672 |
| 1670 const int argc = arguments().immediate(); | 1673 const int argc = arguments().immediate(); |
| 1671 StackArgumentsAccessor args(rsp, argc); | 1674 StackArgumentsAccessor args(rsp, argc); |
| 1672 __ movq(rdx, args.GetReceiverOperand()); | 1675 __ movq(rdx, args.GetReceiverOperand()); |
| 1673 | 1676 |
| 1674 // Check that the receiver isn't a smi. | 1677 // Check that the receiver isn't a smi. |
| 1675 __ JumpIfSmi(rdx, &miss); | 1678 __ JumpIfSmi(rdx, &miss); |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1905 Handle<String> name, | 1908 Handle<String> name, |
| 1906 Code::StubType type) { | 1909 Code::StubType type) { |
| 1907 // ----------- S t a t e ------------- | 1910 // ----------- S t a t e ------------- |
| 1908 // -- rcx : name | 1911 // -- rcx : name |
| 1909 // -- rsp[0] : return address | 1912 // -- rsp[0] : return address |
| 1910 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | 1913 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) |
| 1911 // -- ... | 1914 // -- ... |
| 1912 // -- rsp[(argc + 1) * 8] : receiver | 1915 // -- rsp[(argc + 1) * 8] : receiver |
| 1913 // ----------------------------------- | 1916 // ----------------------------------- |
| 1914 | 1917 |
| 1915 // If object is not an array, bail out to regular call. | 1918 // If object is not an array or is observed, bail out to regular call. |
| 1916 if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null(); | 1919 if (!object->IsJSArray() || |
| 1920 !cell.is_null() || |
| 1921 Handle<JSArray>::cast(object)->map()->is_observed()) { |
| 1922 return Handle<Code>::null(); |
| 1923 } |
| 1917 | 1924 |
| 1918 Label miss, return_undefined, call_builtin; | 1925 Label miss, return_undefined, call_builtin; |
| 1919 GenerateNameCheck(name, &miss); | 1926 GenerateNameCheck(name, &miss); |
| 1920 | 1927 |
| 1921 const int argc = arguments().immediate(); | 1928 const int argc = arguments().immediate(); |
| 1922 StackArgumentsAccessor args(rsp, argc); | 1929 StackArgumentsAccessor args(rsp, argc); |
| 1923 __ movq(rdx, args.GetReceiverOperand()); | 1930 __ movq(rdx, args.GetReceiverOperand()); |
| 1924 | 1931 |
| 1925 // Check that the receiver isn't a smi. | 1932 // Check that the receiver isn't a smi. |
| 1926 __ JumpIfSmi(rdx, &miss); | 1933 __ JumpIfSmi(rdx, &miss); |
| (...skipping 573 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2500 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); | 2507 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); |
| 2501 | 2508 |
| 2502 __ bind(&miss_before_stack_reserved); | 2509 __ bind(&miss_before_stack_reserved); |
| 2503 GenerateMissBranch(); | 2510 GenerateMissBranch(); |
| 2504 | 2511 |
| 2505 // Return the generated code. | 2512 // Return the generated code. |
| 2506 return GetCode(function); | 2513 return GetCode(function); |
| 2507 } | 2514 } |
| 2508 | 2515 |
| 2509 | 2516 |
| 2517 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { |
| 2518 Label success; |
| 2519 // Check that the object is a boolean. |
| 2520 __ CompareRoot(object, Heap::kTrueValueRootIndex); |
| 2521 __ j(equal, &success); |
| 2522 __ CompareRoot(object, Heap::kFalseValueRootIndex); |
| 2523 __ j(not_equal, miss); |
| 2524 __ bind(&success); |
| 2525 } |
| 2526 |
| 2527 |
| 2510 void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object, | 2528 void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object, |
| 2511 Handle<JSObject> holder, | 2529 Handle<JSObject> holder, |
| 2512 Handle<Name> name, | 2530 Handle<Name> name, |
| 2513 CheckType check, | 2531 CheckType check) { |
| 2514 Label* success) { | |
| 2515 // ----------- S t a t e ------------- | 2532 // ----------- S t a t e ------------- |
| 2516 // rcx : function name | 2533 // rcx : function name |
| 2517 // rsp[0] : return address | 2534 // rsp[0] : return address |
| 2518 // rsp[8] : argument argc | 2535 // rsp[8] : argument argc |
| 2519 // rsp[16] : argument argc - 1 | 2536 // rsp[16] : argument argc - 1 |
| 2520 // ... | 2537 // ... |
| 2521 // rsp[argc * 8] : argument 1 | 2538 // rsp[argc * 8] : argument 1 |
| 2522 // rsp[(argc + 1) * 8] : argument 0 = receiver | 2539 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 2523 // ----------------------------------- | 2540 // ----------------------------------- |
| 2524 Label miss; | 2541 Label miss; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2586 __ bind(&fast); | 2603 __ bind(&fast); |
| 2587 // Check that the maps starting from the prototype haven't changed. | 2604 // Check that the maps starting from the prototype haven't changed. |
| 2588 GenerateDirectLoadGlobalFunctionPrototype( | 2605 GenerateDirectLoadGlobalFunctionPrototype( |
| 2589 masm(), Context::NUMBER_FUNCTION_INDEX, rax, &miss); | 2606 masm(), Context::NUMBER_FUNCTION_INDEX, rax, &miss); |
| 2590 CheckPrototypes( | 2607 CheckPrototypes( |
| 2591 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2608 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), |
| 2592 rax, holder, rbx, rdx, rdi, name, &miss); | 2609 rax, holder, rbx, rdx, rdi, name, &miss); |
| 2593 break; | 2610 break; |
| 2594 } | 2611 } |
| 2595 case BOOLEAN_CHECK: { | 2612 case BOOLEAN_CHECK: { |
| 2596 Label fast; | 2613 GenerateBooleanCheck(rdx, &miss); |
| 2597 // Check that the object is a boolean. | |
| 2598 __ CompareRoot(rdx, Heap::kTrueValueRootIndex); | |
| 2599 __ j(equal, &fast); | |
| 2600 __ CompareRoot(rdx, Heap::kFalseValueRootIndex); | |
| 2601 __ j(not_equal, &miss); | |
| 2602 __ bind(&fast); | |
| 2603 // Check that the maps starting from the prototype haven't changed. | 2614 // Check that the maps starting from the prototype haven't changed. |
| 2604 GenerateDirectLoadGlobalFunctionPrototype( | 2615 GenerateDirectLoadGlobalFunctionPrototype( |
| 2605 masm(), Context::BOOLEAN_FUNCTION_INDEX, rax, &miss); | 2616 masm(), Context::BOOLEAN_FUNCTION_INDEX, rax, &miss); |
| 2606 CheckPrototypes( | 2617 CheckPrototypes( |
| 2607 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2618 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), |
| 2608 rax, holder, rbx, rdx, rdi, name, &miss); | 2619 rax, holder, rbx, rdx, rdi, name, &miss); |
| 2609 break; | 2620 break; |
| 2610 } | 2621 } |
| 2611 } | 2622 } |
| 2612 | 2623 |
| 2613 __ jmp(success); | 2624 Label success; |
| 2625 __ jmp(&success); |
| 2614 | 2626 |
| 2615 // Handle call cache miss. | 2627 // Handle call cache miss. |
| 2616 __ bind(&miss); | 2628 __ bind(&miss); |
| 2617 GenerateMissBranch(); | 2629 GenerateMissBranch(); |
| 2630 |
| 2631 __ bind(&success); |
| 2618 } | 2632 } |
| 2619 | 2633 |
| 2620 | 2634 |
| 2621 void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) { | 2635 void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) { |
| 2622 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2636 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2623 ? CALL_AS_FUNCTION | 2637 ? CALL_AS_FUNCTION |
| 2624 : CALL_AS_METHOD; | 2638 : CALL_AS_METHOD; |
| 2625 ParameterCount expected(function); | 2639 ParameterCount expected(function); |
| 2626 __ InvokeFunction(function, expected, arguments(), | 2640 __ InvokeFunction(function, expected, arguments(), |
| 2627 JUMP_FUNCTION, NullCallWrapper(), call_kind); | 2641 JUMP_FUNCTION, NullCallWrapper(), call_kind); |
| 2628 } | 2642 } |
| 2629 | 2643 |
| 2630 | 2644 |
| 2631 Handle<Code> CallStubCompiler::CompileCallConstant( | 2645 Handle<Code> CallStubCompiler::CompileCallConstant( |
| 2632 Handle<Object> object, | 2646 Handle<Object> object, |
| 2633 Handle<JSObject> holder, | 2647 Handle<JSObject> holder, |
| 2634 Handle<Name> name, | 2648 Handle<Name> name, |
| 2635 CheckType check, | 2649 CheckType check, |
| 2636 Handle<JSFunction> function) { | 2650 Handle<JSFunction> function) { |
| 2637 if (HasCustomCallGenerator(function)) { | 2651 if (HasCustomCallGenerator(function)) { |
| 2638 Handle<Code> code = CompileCustomCall(object, holder, | 2652 Handle<Code> code = CompileCustomCall(object, holder, |
| 2639 Handle<PropertyCell>::null(), | 2653 Handle<PropertyCell>::null(), |
| 2640 function, Handle<String>::cast(name), | 2654 function, Handle<String>::cast(name), |
| 2641 Code::CONSTANT); | 2655 Code::CONSTANT); |
| 2642 // A null handle means bail out to the regular compiler code below. | 2656 // A null handle means bail out to the regular compiler code below. |
| 2643 if (!code.is_null()) return code; | 2657 if (!code.is_null()) return code; |
| 2644 } | 2658 } |
| 2645 | 2659 |
| 2646 Label success; | 2660 CompileHandlerFrontend(object, holder, name, check); |
| 2647 | |
| 2648 CompileHandlerFrontend(object, holder, name, check, &success); | |
| 2649 __ bind(&success); | |
| 2650 CompileHandlerBackend(function); | 2661 CompileHandlerBackend(function); |
| 2651 | 2662 |
| 2652 // Return the generated code. | 2663 // Return the generated code. |
| 2653 return GetCode(function); | 2664 return GetCode(function); |
| 2654 } | 2665 } |
| 2655 | 2666 |
| 2656 | 2667 |
| 2657 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, | 2668 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, |
| 2658 Handle<JSObject> holder, | 2669 Handle<JSObject> holder, |
| 2659 Handle<Name> name) { | 2670 Handle<Name> name) { |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2775 // Return the generated code. | 2786 // Return the generated code. |
| 2776 return GetCode(Code::NORMAL, name); | 2787 return GetCode(Code::NORMAL, name); |
| 2777 } | 2788 } |
| 2778 | 2789 |
| 2779 | 2790 |
| 2780 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2791 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
| 2781 Handle<JSObject> object, | 2792 Handle<JSObject> object, |
| 2782 Handle<JSObject> holder, | 2793 Handle<JSObject> holder, |
| 2783 Handle<Name> name, | 2794 Handle<Name> name, |
| 2784 Handle<ExecutableAccessorInfo> callback) { | 2795 Handle<ExecutableAccessorInfo> callback) { |
| 2785 Label success; | 2796 HandlerFrontend(object, receiver(), holder, name); |
| 2786 HandlerFrontend(object, receiver(), holder, name, &success); | |
| 2787 __ bind(&success); | |
| 2788 | 2797 |
| 2789 __ PopReturnAddressTo(scratch1()); | 2798 __ PopReturnAddressTo(scratch1()); |
| 2790 __ push(receiver()); | 2799 __ push(receiver()); |
| 2791 __ Push(callback); // callback info | 2800 __ Push(callback); // callback info |
| 2792 __ Push(name); | 2801 __ Push(name); |
| 2793 __ push(value()); | 2802 __ push(value()); |
| 2794 __ PushReturnAddressFrom(scratch1()); | 2803 __ PushReturnAddressFrom(scratch1()); |
| 2795 | 2804 |
| 2796 // Do tail-call to the runtime system. | 2805 // Do tail-call to the runtime system. |
| 2797 ExternalReference store_callback_property = | 2806 ExternalReference store_callback_property = |
| 2798 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); | 2807 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); |
| 2799 __ TailCallExternalReference(store_callback_property, 4, 1); | 2808 __ TailCallExternalReference(store_callback_property, 4, 1); |
| 2800 | 2809 |
| 2801 // Return the generated code. | 2810 // Return the generated code. |
| 2802 return GetCode(kind(), Code::CALLBACKS, name); | 2811 return GetCode(kind(), Code::CALLBACKS, name); |
| 2803 } | 2812 } |
| 2804 | 2813 |
| 2805 | 2814 |
| 2806 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2815 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
| 2807 Handle<JSObject> object, | 2816 Handle<JSObject> object, |
| 2808 Handle<JSObject> holder, | 2817 Handle<JSObject> holder, |
| 2809 Handle<Name> name, | 2818 Handle<Name> name, |
| 2810 const CallOptimization& call_optimization) { | 2819 const CallOptimization& call_optimization) { |
| 2811 Label success; | 2820 HandlerFrontend(object, receiver(), holder, name); |
| 2812 HandlerFrontend(object, receiver(), holder, name, &success); | |
| 2813 __ bind(&success); | |
| 2814 | 2821 |
| 2815 Register values[] = { value() }; | 2822 Register values[] = { value() }; |
| 2816 GenerateFastApiCall( | 2823 GenerateFastApiCall( |
| 2817 masm(), call_optimization, receiver(), scratch3(), 1, values); | 2824 masm(), call_optimization, receiver(), scratch3(), 1, values); |
| 2818 | 2825 |
| 2819 // Return the generated code. | 2826 // Return the generated code. |
| 2820 return GetCode(kind(), Code::CALLBACKS, name); | 2827 return GetCode(kind(), Code::CALLBACKS, name); |
| 2821 } | 2828 } |
| 2822 | 2829 |
| 2823 | 2830 |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2917 | 2924 |
| 2918 TailCallBuiltin(masm(), MissBuiltin(kind())); | 2925 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 2919 | 2926 |
| 2920 // Return the generated code. | 2927 // Return the generated code. |
| 2921 return GetICCode( | 2928 return GetICCode( |
| 2922 kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); | 2929 kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); |
| 2923 } | 2930 } |
| 2924 | 2931 |
| 2925 | 2932 |
| 2926 Handle<Code> LoadStubCompiler::CompileLoadNonexistent( | 2933 Handle<Code> LoadStubCompiler::CompileLoadNonexistent( |
| 2927 Handle<JSObject> object, | 2934 Handle<Object> object, |
| 2928 Handle<JSObject> last, | 2935 Handle<JSObject> last, |
| 2929 Handle<Name> name, | 2936 Handle<Name> name, |
| 2930 Handle<JSGlobalObject> global) { | 2937 Handle<JSGlobalObject> global) { |
| 2931 Label success; | 2938 NonexistentHandlerFrontend(object, last, name, global); |
| 2932 | 2939 |
| 2933 NonexistentHandlerFrontend(object, last, name, &success, global); | |
| 2934 | |
| 2935 __ bind(&success); | |
| 2936 // Return undefined if maps of the full prototype chain are still the | 2940 // Return undefined if maps of the full prototype chain are still the |
| 2937 // same and no global property with this name contains a value. | 2941 // same and no global property with this name contains a value. |
| 2938 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 2942 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); |
| 2939 __ ret(0); | 2943 __ ret(0); |
| 2940 | 2944 |
| 2941 // Return the generated code. | 2945 // Return the generated code. |
| 2942 return GetCode(kind(), Code::NONEXISTENT, name); | 2946 return GetCode(kind(), Code::NONEXISTENT, name); |
| 2943 } | 2947 } |
| 2944 | 2948 |
| 2945 | 2949 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3020 } | 3024 } |
| 3021 __ ret(0); | 3025 __ ret(0); |
| 3022 } | 3026 } |
| 3023 | 3027 |
| 3024 | 3028 |
| 3025 #undef __ | 3029 #undef __ |
| 3026 #define __ ACCESS_MASM(masm()) | 3030 #define __ ACCESS_MASM(masm()) |
| 3027 | 3031 |
| 3028 | 3032 |
| 3029 Handle<Code> LoadStubCompiler::CompileLoadGlobal( | 3033 Handle<Code> LoadStubCompiler::CompileLoadGlobal( |
| 3030 Handle<JSObject> object, | 3034 Handle<Object> object, |
| 3031 Handle<GlobalObject> global, | 3035 Handle<GlobalObject> global, |
| 3032 Handle<PropertyCell> cell, | 3036 Handle<PropertyCell> cell, |
| 3033 Handle<Name> name, | 3037 Handle<Name> name, |
| 3034 bool is_dont_delete) { | 3038 bool is_dont_delete) { |
| 3035 Label success, miss; | 3039 Label miss; |
| 3036 // TODO(verwaest): Directly store to rax. Currently we cannot do this, since | 3040 // TODO(verwaest): Directly store to rax. Currently we cannot do this, since |
| 3037 // rax is used as receiver(), which we would otherwise clobber before a | 3041 // rax is used as receiver(), which we would otherwise clobber before a |
| 3038 // potential miss. | 3042 // potential miss. |
| 3039 HandlerFrontendHeader(object, receiver(), global, name, &miss); | 3043 HandlerFrontendHeader(object, receiver(), global, name, &miss); |
| 3040 | 3044 |
| 3041 // Get the value from the cell. | 3045 // Get the value from the cell. |
| 3042 __ Move(rbx, cell); | 3046 __ Move(rbx, cell); |
| 3043 __ movq(rbx, FieldOperand(rbx, PropertyCell::kValueOffset)); | 3047 __ movq(rbx, FieldOperand(rbx, PropertyCell::kValueOffset)); |
| 3044 | 3048 |
| 3045 // Check for deleted property if property can actually be deleted. | 3049 // Check for deleted property if property can actually be deleted. |
| 3046 if (!is_dont_delete) { | 3050 if (!is_dont_delete) { |
| 3047 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); | 3051 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); |
| 3048 __ j(equal, &miss); | 3052 __ j(equal, &miss); |
| 3049 } else if (FLAG_debug_code) { | 3053 } else if (FLAG_debug_code) { |
| 3050 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); | 3054 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); |
| 3051 __ Check(not_equal, kDontDeleteCellsCannotContainTheHole); | 3055 __ Check(not_equal, kDontDeleteCellsCannotContainTheHole); |
| 3052 } | 3056 } |
| 3053 | 3057 |
| 3054 HandlerFrontendFooter(name, &success, &miss); | 3058 HandlerFrontendFooter(name, &miss); |
| 3055 __ bind(&success); | |
| 3056 | 3059 |
| 3057 Counters* counters = isolate()->counters(); | 3060 Counters* counters = isolate()->counters(); |
| 3058 __ IncrementCounter(counters->named_load_global_stub(), 1); | 3061 __ IncrementCounter(counters->named_load_global_stub(), 1); |
| 3059 __ movq(rax, rbx); | 3062 __ movq(rax, rbx); |
| 3060 __ ret(0); | 3063 __ ret(0); |
| 3061 | 3064 |
| 3062 // Return the generated code. | 3065 // Return the generated code. |
| 3063 return GetCode(kind(), Code::NORMAL, name); | 3066 return GetCode(kind(), Code::NORMAL, name); |
| 3064 } | 3067 } |
| 3065 | 3068 |
| 3066 | 3069 |
| 3067 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC( | 3070 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC( |
| 3068 MapHandleList* receiver_maps, | 3071 MapHandleList* receiver_maps, |
| 3069 CodeHandleList* handlers, | 3072 CodeHandleList* handlers, |
| 3070 Handle<Name> name, | 3073 Handle<Name> name, |
| 3071 Code::StubType type, | 3074 Code::StubType type, |
| 3072 IcCheckType check) { | 3075 IcCheckType check) { |
| 3073 Label miss; | 3076 Label miss; |
| 3074 | 3077 |
| 3075 if (check == PROPERTY) { | 3078 if (check == PROPERTY) { |
| 3076 GenerateNameCheck(name, this->name(), &miss); | 3079 GenerateNameCheck(name, this->name(), &miss); |
| 3077 } | 3080 } |
| 3078 | 3081 |
| 3079 __ JumpIfSmi(receiver(), &miss); | 3082 Label number_case; |
| 3083 Label* smi_target = HasHeapNumberMap(receiver_maps) ? &number_case : &miss; |
| 3084 __ JumpIfSmi(receiver(), smi_target); |
| 3085 |
| 3080 Register map_reg = scratch1(); | 3086 Register map_reg = scratch1(); |
| 3081 __ movq(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset)); | 3087 __ movq(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset)); |
| 3082 int receiver_count = receiver_maps->length(); | 3088 int receiver_count = receiver_maps->length(); |
| 3083 int number_of_handled_maps = 0; | 3089 int number_of_handled_maps = 0; |
| 3090 Handle<Map> heap_number_map = isolate()->factory()->heap_number_map(); |
| 3084 for (int current = 0; current < receiver_count; ++current) { | 3091 for (int current = 0; current < receiver_count; ++current) { |
| 3085 Handle<Map> map = receiver_maps->at(current); | 3092 Handle<Map> map = receiver_maps->at(current); |
| 3086 if (!map->is_deprecated()) { | 3093 if (!map->is_deprecated()) { |
| 3087 number_of_handled_maps++; | 3094 number_of_handled_maps++; |
| 3088 // Check map and tail call if there's a match | 3095 // Check map and tail call if there's a match |
| 3089 __ Cmp(map_reg, receiver_maps->at(current)); | 3096 __ Cmp(map_reg, receiver_maps->at(current)); |
| 3097 if (map.is_identical_to(heap_number_map)) { |
| 3098 ASSERT(!number_case.is_unused()); |
| 3099 __ bind(&number_case); |
| 3100 } |
| 3090 __ j(equal, handlers->at(current), RelocInfo::CODE_TARGET); | 3101 __ j(equal, handlers->at(current), RelocInfo::CODE_TARGET); |
| 3091 } | 3102 } |
| 3092 } | 3103 } |
| 3093 ASSERT(number_of_handled_maps > 0); | 3104 ASSERT(number_of_handled_maps > 0); |
| 3094 | 3105 |
| 3095 __ bind(&miss); | 3106 __ bind(&miss); |
| 3096 TailCallBuiltin(masm(), MissBuiltin(kind())); | 3107 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 3097 | 3108 |
| 3098 // Return the generated code. | 3109 // Return the generated code. |
| 3099 InlineCacheState state = | 3110 InlineCacheState state = |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3146 // ----------------------------------- | 3157 // ----------------------------------- |
| 3147 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); | 3158 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); |
| 3148 } | 3159 } |
| 3149 | 3160 |
| 3150 | 3161 |
| 3151 #undef __ | 3162 #undef __ |
| 3152 | 3163 |
| 3153 } } // namespace v8::internal | 3164 } } // namespace v8::internal |
| 3154 | 3165 |
| 3155 #endif // V8_TARGET_ARCH_X64 | 3166 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |