| 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 |