OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #if V8_TARGET_ARCH_ARM64 | 5 #if V8_TARGET_ARCH_ARM64 |
6 | 6 |
7 #include "src/code-stubs.h" | 7 #include "src/code-stubs.h" |
8 #include "src/api-arguments.h" | 8 #include "src/api-arguments.h" |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 1486 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1497 | 1497 |
1498 StubRuntimeCallHelper call_helper; | 1498 StubRuntimeCallHelper call_helper; |
1499 char_at_generator.GenerateSlow(masm, PART_OF_IC_HANDLER, call_helper); | 1499 char_at_generator.GenerateSlow(masm, PART_OF_IC_HANDLER, call_helper); |
1500 | 1500 |
1501 __ Bind(&miss); | 1501 __ Bind(&miss); |
1502 PropertyAccessCompiler::TailCallBuiltin( | 1502 PropertyAccessCompiler::TailCallBuiltin( |
1503 masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC)); | 1503 masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC)); |
1504 } | 1504 } |
1505 | 1505 |
1506 | 1506 |
1507 void InstanceOfStub::Generate(MacroAssembler* masm) { | |
1508 Register const object = x1; // Object (lhs). | |
1509 Register const function = x0; // Function (rhs). | |
1510 Register const object_map = x2; // Map of {object}. | |
1511 Register const function_map = x3; // Map of {function}. | |
1512 Register const function_prototype = x4; // Prototype of {function}. | |
1513 Register const scratch = x5; | |
1514 | |
1515 DCHECK(object.is(InstanceOfDescriptor::LeftRegister())); | |
1516 DCHECK(function.is(InstanceOfDescriptor::RightRegister())); | |
1517 | |
1518 // Check if {object} is a smi. | |
1519 Label object_is_smi; | |
1520 __ JumpIfSmi(object, &object_is_smi); | |
1521 | |
1522 // Lookup the {function} and the {object} map in the global instanceof cache. | |
1523 // Note: This is safe because we clear the global instanceof cache whenever | |
1524 // we change the prototype of any object. | |
1525 Label fast_case, slow_case; | |
1526 __ Ldr(object_map, FieldMemOperand(object, HeapObject::kMapOffset)); | |
1527 __ JumpIfNotRoot(function, Heap::kInstanceofCacheFunctionRootIndex, | |
1528 &fast_case); | |
1529 __ JumpIfNotRoot(object_map, Heap::kInstanceofCacheMapRootIndex, &fast_case); | |
1530 __ LoadRoot(x0, Heap::kInstanceofCacheAnswerRootIndex); | |
1531 __ Ret(); | |
1532 | |
1533 // If {object} is a smi we can safely return false if {function} is a JS | |
1534 // function, otherwise we have to miss to the runtime and throw an exception. | |
1535 __ Bind(&object_is_smi); | |
1536 __ JumpIfSmi(function, &slow_case); | |
1537 __ JumpIfNotObjectType(function, function_map, scratch, JS_FUNCTION_TYPE, | |
1538 &slow_case); | |
1539 __ LoadRoot(x0, Heap::kFalseValueRootIndex); | |
1540 __ Ret(); | |
1541 | |
1542 // Fast-case: The {function} must be a valid JSFunction. | |
1543 __ Bind(&fast_case); | |
1544 __ JumpIfSmi(function, &slow_case); | |
1545 __ JumpIfNotObjectType(function, function_map, scratch, JS_FUNCTION_TYPE, | |
1546 &slow_case); | |
1547 | |
1548 // Go to the runtime if the function is not a constructor. | |
1549 __ Ldrb(scratch, FieldMemOperand(function_map, Map::kBitFieldOffset)); | |
1550 __ Tbz(scratch, Map::kIsConstructor, &slow_case); | |
1551 | |
1552 // Ensure that {function} has an instance prototype. | |
1553 __ Tbnz(scratch, Map::kHasNonInstancePrototype, &slow_case); | |
1554 | |
1555 // Get the "prototype" (or initial map) of the {function}. | |
1556 __ Ldr(function_prototype, | |
1557 FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); | |
1558 __ AssertNotSmi(function_prototype); | |
1559 | |
1560 // Resolve the prototype if the {function} has an initial map. Afterwards the | |
1561 // {function_prototype} will be either the JSReceiver prototype object or the | |
1562 // hole value, which means that no instances of the {function} were created so | |
1563 // far and hence we should return false. | |
1564 Label function_prototype_valid; | |
1565 __ JumpIfNotObjectType(function_prototype, scratch, scratch, MAP_TYPE, | |
1566 &function_prototype_valid); | |
1567 __ Ldr(function_prototype, | |
1568 FieldMemOperand(function_prototype, Map::kPrototypeOffset)); | |
1569 __ Bind(&function_prototype_valid); | |
1570 __ AssertNotSmi(function_prototype); | |
1571 | |
1572 // Update the global instanceof cache with the current {object} map and | |
1573 // {function}. The cached answer will be set when it is known below. | |
1574 __ StoreRoot(function, Heap::kInstanceofCacheFunctionRootIndex); | |
1575 __ StoreRoot(object_map, Heap::kInstanceofCacheMapRootIndex); | |
1576 | |
1577 // Loop through the prototype chain looking for the {function} prototype. | |
1578 // Assume true, and change to false if not found. | |
1579 Register const object_instance_type = function_map; | |
1580 Register const map_bit_field = function_map; | |
1581 Register const null = scratch; | |
1582 Register const result = x0; | |
1583 | |
1584 Label done, loop, fast_runtime_fallback; | |
1585 __ LoadRoot(result, Heap::kTrueValueRootIndex); | |
1586 __ LoadRoot(null, Heap::kNullValueRootIndex); | |
1587 __ Bind(&loop); | |
1588 | |
1589 // Check if the object needs to be access checked. | |
1590 __ Ldrb(map_bit_field, FieldMemOperand(object_map, Map::kBitFieldOffset)); | |
1591 __ TestAndBranchIfAnySet(map_bit_field, 1 << Map::kIsAccessCheckNeeded, | |
1592 &fast_runtime_fallback); | |
1593 // Check if the current object is a Proxy. | |
1594 __ CompareInstanceType(object_map, object_instance_type, JS_PROXY_TYPE); | |
1595 __ B(eq, &fast_runtime_fallback); | |
1596 | |
1597 __ Ldr(object, FieldMemOperand(object_map, Map::kPrototypeOffset)); | |
1598 __ Cmp(object, function_prototype); | |
1599 __ B(eq, &done); | |
1600 __ Cmp(object, null); | |
1601 __ Ldr(object_map, FieldMemOperand(object, HeapObject::kMapOffset)); | |
1602 __ B(ne, &loop); | |
1603 __ LoadRoot(result, Heap::kFalseValueRootIndex); | |
1604 __ Bind(&done); | |
1605 __ StoreRoot(result, Heap::kInstanceofCacheAnswerRootIndex); | |
1606 __ Ret(); | |
1607 | |
1608 // Found Proxy or access check needed: Call the runtime | |
1609 __ Bind(&fast_runtime_fallback); | |
1610 __ Push(object, function_prototype); | |
1611 // Invalidate the instanceof cache. | |
1612 __ Move(scratch, Smi::FromInt(0)); | |
1613 __ StoreRoot(scratch, Heap::kInstanceofCacheFunctionRootIndex); | |
1614 __ TailCallRuntime(Runtime::kHasInPrototypeChain); | |
1615 | |
1616 // Slow-case: Call the %InstanceOf runtime function. | |
1617 __ bind(&slow_case); | |
1618 __ Push(object, function); | |
1619 __ TailCallRuntime(is_es6_instanceof() ? Runtime::kOrdinaryHasInstance | |
1620 : Runtime::kInstanceOf); | |
1621 } | |
1622 | |
1623 | |
1624 void RegExpExecStub::Generate(MacroAssembler* masm) { | 1507 void RegExpExecStub::Generate(MacroAssembler* masm) { |
1625 #ifdef V8_INTERPRETED_REGEXP | 1508 #ifdef V8_INTERPRETED_REGEXP |
1626 __ TailCallRuntime(Runtime::kRegExpExec); | 1509 __ TailCallRuntime(Runtime::kRegExpExec); |
1627 #else // V8_INTERPRETED_REGEXP | 1510 #else // V8_INTERPRETED_REGEXP |
1628 | 1511 |
1629 // Stack frame on entry. | 1512 // Stack frame on entry. |
1630 // jssp[0]: last_match_info (expected JSArray) | 1513 // jssp[0]: last_match_info (expected JSArray) |
1631 // jssp[8]: previous index | 1514 // jssp[8]: previous index |
1632 // jssp[16]: subject string | 1515 // jssp[16]: subject string |
1633 // jssp[24]: JSRegExp object | 1516 // jssp[24]: JSRegExp object |
(...skipping 4315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5949 kStackUnwindSpace, NULL, spill_offset, | 5832 kStackUnwindSpace, NULL, spill_offset, |
5950 return_value_operand, NULL); | 5833 return_value_operand, NULL); |
5951 } | 5834 } |
5952 | 5835 |
5953 #undef __ | 5836 #undef __ |
5954 | 5837 |
5955 } // namespace internal | 5838 } // namespace internal |
5956 } // namespace v8 | 5839 } // namespace v8 |
5957 | 5840 |
5958 #endif // V8_TARGET_ARCH_ARM64 | 5841 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |