OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64. |
6 #if defined(TARGET_ARCH_ARM64) | 6 #if defined(TARGET_ARCH_ARM64) |
7 | 7 |
8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
9 | 9 |
10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
(...skipping 1530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1541 | 1541 |
1542 for (intptr_t i = 0; i < num_temps; i++) { | 1542 for (intptr_t i = 0; i < num_temps; i++) { |
1543 summary->set_temp(i, Location::RequiresRegister()); | 1543 summary->set_temp(i, Location::RequiresRegister()); |
1544 } | 1544 } |
1545 | 1545 |
1546 return summary; | 1546 return summary; |
1547 } | 1547 } |
1548 | 1548 |
1549 | 1549 |
1550 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1550 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1551 ASSERT(sizeof(classid_t) == kInt32Size); | 1551 ASSERT(sizeof(classid_t) == kInt16Size); |
1552 const intptr_t value_cid = value()->Type()->ToCid(); | 1552 const intptr_t value_cid = value()->Type()->ToCid(); |
1553 const intptr_t field_cid = field().guarded_cid(); | 1553 const intptr_t field_cid = field().guarded_cid(); |
1554 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; | 1554 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; |
1555 | 1555 |
1556 if (field_cid == kDynamicCid) { | 1556 if (field_cid == kDynamicCid) { |
1557 if (Compiler::IsBackgroundCompilation()) { | 1557 if (Compiler::IsBackgroundCompilation()) { |
1558 // Field state changed while compiling. | 1558 // Field state changed while compiling. |
1559 Compiler::AbortBackgroundCompilation( | 1559 Compiler::AbortBackgroundCompilation( |
1560 deopt_id(), | 1560 deopt_id(), |
1561 "GuardFieldClassInstr: field state changed while compiling"); | 1561 "GuardFieldClassInstr: field state changed while compiling"); |
(...skipping 25 matching lines...) Expand all Loading... |
1587 compiler->is_optimizing() | 1587 compiler->is_optimizing() |
1588 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) | 1588 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) |
1589 : NULL; | 1589 : NULL; |
1590 | 1590 |
1591 Label* fail = (deopt != NULL) ? deopt : &fail_label; | 1591 Label* fail = (deopt != NULL) ? deopt : &fail_label; |
1592 | 1592 |
1593 if (emit_full_guard) { | 1593 if (emit_full_guard) { |
1594 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); | 1594 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); |
1595 | 1595 |
1596 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset(), | 1596 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset(), |
1597 kUnsignedWord); | 1597 kUnsignedHalfword); |
1598 FieldAddress field_nullability_operand( | 1598 FieldAddress field_nullability_operand( |
1599 field_reg, Field::is_nullable_offset(), kUnsignedWord); | 1599 field_reg, Field::is_nullable_offset(), kUnsignedHalfword); |
1600 | 1600 |
1601 if (value_cid == kDynamicCid) { | 1601 if (value_cid == kDynamicCid) { |
1602 LoadValueCid(compiler, value_cid_reg, value_reg); | 1602 LoadValueCid(compiler, value_cid_reg, value_reg); |
1603 Label skip_length_check; | 1603 Label skip_length_check; |
1604 __ ldr(TMP, field_cid_operand, kUnsignedWord); | 1604 __ ldr(TMP, field_cid_operand, kUnsignedHalfword); |
1605 __ CompareRegisters(value_cid_reg, TMP); | 1605 __ CompareRegisters(value_cid_reg, TMP); |
1606 __ b(&ok, EQ); | 1606 __ b(&ok, EQ); |
1607 __ ldr(TMP, field_nullability_operand, kUnsignedWord); | 1607 __ ldr(TMP, field_nullability_operand, kUnsignedHalfword); |
1608 __ CompareRegisters(value_cid_reg, TMP); | 1608 __ CompareRegisters(value_cid_reg, TMP); |
1609 } else if (value_cid == kNullCid) { | 1609 } else if (value_cid == kNullCid) { |
1610 __ ldr(value_cid_reg, field_nullability_operand, kUnsignedWord); | 1610 __ ldr(value_cid_reg, field_nullability_operand, kUnsignedHalfword); |
1611 __ CompareImmediate(value_cid_reg, value_cid); | 1611 __ CompareImmediate(value_cid_reg, value_cid); |
1612 } else { | 1612 } else { |
1613 Label skip_length_check; | 1613 Label skip_length_check; |
1614 __ ldr(value_cid_reg, field_cid_operand, kUnsignedWord); | 1614 __ ldr(value_cid_reg, field_cid_operand, kUnsignedHalfword); |
1615 __ CompareImmediate(value_cid_reg, value_cid); | 1615 __ CompareImmediate(value_cid_reg, value_cid); |
1616 } | 1616 } |
1617 __ b(&ok, EQ); | 1617 __ b(&ok, EQ); |
1618 | 1618 |
1619 // Check if the tracked state of the guarded field can be initialized | 1619 // Check if the tracked state of the guarded field can be initialized |
1620 // inline. If the field needs length check we fall through to runtime | 1620 // inline. If the field needs length check we fall through to runtime |
1621 // which is responsible for computing offset of the length field | 1621 // which is responsible for computing offset of the length field |
1622 // based on the class id. | 1622 // based on the class id. |
1623 // Length guard will be emitted separately when needed via GuardFieldLength | 1623 // Length guard will be emitted separately when needed via GuardFieldLength |
1624 // instruction after GuardFieldClass. | 1624 // instruction after GuardFieldClass. |
1625 if (!field().needs_length_check()) { | 1625 if (!field().needs_length_check()) { |
1626 // Uninitialized field can be handled inline. Check if the | 1626 // Uninitialized field can be handled inline. Check if the |
1627 // field is still unitialized. | 1627 // field is still unitialized. |
1628 __ ldr(TMP, field_cid_operand, kUnsignedWord); | 1628 __ ldr(TMP, field_cid_operand, kUnsignedHalfword); |
1629 __ CompareImmediate(TMP, kIllegalCid); | 1629 __ CompareImmediate(TMP, kIllegalCid); |
1630 __ b(fail, NE); | 1630 __ b(fail, NE); |
1631 | 1631 |
1632 if (value_cid == kDynamicCid) { | 1632 if (value_cid == kDynamicCid) { |
1633 __ str(value_cid_reg, field_cid_operand, kUnsignedWord); | 1633 __ str(value_cid_reg, field_cid_operand, kUnsignedHalfword); |
1634 __ str(value_cid_reg, field_nullability_operand, kUnsignedWord); | 1634 __ str(value_cid_reg, field_nullability_operand, kUnsignedHalfword); |
1635 } else { | 1635 } else { |
1636 __ LoadImmediate(TMP, value_cid); | 1636 __ LoadImmediate(TMP, value_cid); |
1637 __ str(TMP, field_cid_operand, kUnsignedWord); | 1637 __ str(TMP, field_cid_operand, kUnsignedHalfword); |
1638 __ str(TMP, field_nullability_operand, kUnsignedWord); | 1638 __ str(TMP, field_nullability_operand, kUnsignedHalfword); |
1639 } | 1639 } |
1640 | 1640 |
1641 if (deopt == NULL) { | 1641 if (deopt == NULL) { |
1642 ASSERT(!compiler->is_optimizing()); | 1642 ASSERT(!compiler->is_optimizing()); |
1643 __ b(&ok); | 1643 __ b(&ok); |
1644 } | 1644 } |
1645 } | 1645 } |
1646 | 1646 |
1647 if (deopt == NULL) { | 1647 if (deopt == NULL) { |
1648 ASSERT(!compiler->is_optimizing()); | 1648 ASSERT(!compiler->is_optimizing()); |
1649 __ Bind(fail); | 1649 __ Bind(fail); |
1650 | 1650 |
1651 __ LoadFieldFromOffset(TMP, field_reg, Field::guarded_cid_offset(), | 1651 __ LoadFieldFromOffset(TMP, field_reg, Field::guarded_cid_offset(), |
1652 kUnsignedWord); | 1652 kUnsignedHalfword); |
1653 __ CompareImmediate(TMP, kDynamicCid); | 1653 __ CompareImmediate(TMP, kDynamicCid); |
1654 __ b(&ok, EQ); | 1654 __ b(&ok, EQ); |
1655 | 1655 |
1656 __ Push(field_reg); | 1656 __ Push(field_reg); |
1657 __ Push(value_reg); | 1657 __ Push(value_reg); |
1658 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2); | 1658 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2); |
1659 __ Drop(2); // Drop the field and the value. | 1659 __ Drop(2); // Drop the field and the value. |
1660 } | 1660 } |
1661 } else { | 1661 } else { |
1662 ASSERT(compiler->is_optimizing()); | 1662 ASSERT(compiler->is_optimizing()); |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1881 } else { | 1881 } else { |
1882 summary->set_in(1, ShouldEmitStoreBarrier() | 1882 summary->set_in(1, ShouldEmitStoreBarrier() |
1883 ? Location::WritableRegister() | 1883 ? Location::WritableRegister() |
1884 : Location::RegisterOrConstant(value())); | 1884 : Location::RegisterOrConstant(value())); |
1885 } | 1885 } |
1886 return summary; | 1886 return summary; |
1887 } | 1887 } |
1888 | 1888 |
1889 | 1889 |
1890 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1890 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1891 ASSERT(sizeof(classid_t) == kInt32Size); | 1891 ASSERT(sizeof(classid_t) == kInt16Size); |
1892 Label skip_store; | 1892 Label skip_store; |
1893 | 1893 |
1894 const Register instance_reg = locs()->in(0).reg(); | 1894 const Register instance_reg = locs()->in(0).reg(); |
1895 | 1895 |
1896 if (IsUnboxedStore() && compiler->is_optimizing()) { | 1896 if (IsUnboxedStore() && compiler->is_optimizing()) { |
1897 const VRegister value = locs()->in(1).fpu_reg(); | 1897 const VRegister value = locs()->in(1).fpu_reg(); |
1898 const Register temp = locs()->temp(0).reg(); | 1898 const Register temp = locs()->temp(0).reg(); |
1899 const Register temp2 = locs()->temp(1).reg(); | 1899 const Register temp2 = locs()->temp(1).reg(); |
1900 const intptr_t cid = field().UnboxedFieldCid(); | 1900 const intptr_t cid = field().UnboxedFieldCid(); |
1901 | 1901 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1953 } | 1953 } |
1954 | 1954 |
1955 Label store_pointer; | 1955 Label store_pointer; |
1956 Label store_double; | 1956 Label store_double; |
1957 Label store_float32x4; | 1957 Label store_float32x4; |
1958 Label store_float64x2; | 1958 Label store_float64x2; |
1959 | 1959 |
1960 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); | 1960 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); |
1961 | 1961 |
1962 __ LoadFieldFromOffset(temp2, temp, Field::is_nullable_offset(), | 1962 __ LoadFieldFromOffset(temp2, temp, Field::is_nullable_offset(), |
1963 kUnsignedWord); | 1963 kUnsignedHalfword); |
1964 __ CompareImmediate(temp2, kNullCid); | 1964 __ CompareImmediate(temp2, kNullCid); |
1965 __ b(&store_pointer, EQ); | 1965 __ b(&store_pointer, EQ); |
1966 | 1966 |
1967 __ LoadFromOffset(temp2, temp, Field::kind_bits_offset() - kHeapObjectTag, | 1967 __ LoadFromOffset(temp2, temp, Field::kind_bits_offset() - kHeapObjectTag, |
1968 kUnsignedByte); | 1968 kUnsignedByte); |
1969 __ tsti(temp2, Immediate(1 << Field::kUnboxingCandidateBit)); | 1969 __ tsti(temp2, Immediate(1 << Field::kUnboxingCandidateBit)); |
1970 __ b(&store_pointer, EQ); | 1970 __ b(&store_pointer, EQ); |
1971 | 1971 |
1972 __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), | 1972 __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), |
1973 kUnsignedWord); | 1973 kUnsignedHalfword); |
1974 __ CompareImmediate(temp2, kDoubleCid); | 1974 __ CompareImmediate(temp2, kDoubleCid); |
1975 __ b(&store_double, EQ); | 1975 __ b(&store_double, EQ); |
1976 | 1976 |
1977 __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), | 1977 __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), |
1978 kUnsignedWord); | 1978 kUnsignedHalfword); |
1979 __ CompareImmediate(temp2, kFloat32x4Cid); | 1979 __ CompareImmediate(temp2, kFloat32x4Cid); |
1980 __ b(&store_float32x4, EQ); | 1980 __ b(&store_float32x4, EQ); |
1981 | 1981 |
1982 __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), | 1982 __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), |
1983 kUnsignedWord); | 1983 kUnsignedHalfword); |
1984 __ CompareImmediate(temp2, kFloat64x2Cid); | 1984 __ CompareImmediate(temp2, kFloat64x2Cid); |
1985 __ b(&store_float64x2, EQ); | 1985 __ b(&store_float64x2, EQ); |
1986 | 1986 |
1987 // Fall through. | 1987 // Fall through. |
1988 __ b(&store_pointer); | 1988 __ b(&store_pointer); |
1989 | 1989 |
1990 if (!compiler->is_optimizing()) { | 1990 if (!compiler->is_optimizing()) { |
1991 locs()->live_registers()->Add(locs()->in(0)); | 1991 locs()->live_registers()->Add(locs()->in(0)); |
1992 locs()->live_registers()->Add(locs()->in(1)); | 1992 locs()->live_registers()->Add(locs()->in(1)); |
1993 } | 1993 } |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2237 locs->set_temp(0, Location::RequiresRegister()); | 2237 locs->set_temp(0, Location::RequiresRegister()); |
2238 } else if (IsPotentialUnboxedLoad()) { | 2238 } else if (IsPotentialUnboxedLoad()) { |
2239 locs->set_temp(0, Location::RequiresRegister()); | 2239 locs->set_temp(0, Location::RequiresRegister()); |
2240 } | 2240 } |
2241 locs->set_out(0, Location::RequiresRegister()); | 2241 locs->set_out(0, Location::RequiresRegister()); |
2242 return locs; | 2242 return locs; |
2243 } | 2243 } |
2244 | 2244 |
2245 | 2245 |
2246 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2246 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2247 ASSERT(sizeof(classid_t) == kInt32Size); | 2247 ASSERT(sizeof(classid_t) == kInt16Size); |
2248 const Register instance_reg = locs()->in(0).reg(); | 2248 const Register instance_reg = locs()->in(0).reg(); |
2249 if (IsUnboxedLoad() && compiler->is_optimizing()) { | 2249 if (IsUnboxedLoad() && compiler->is_optimizing()) { |
2250 const VRegister result = locs()->out(0).fpu_reg(); | 2250 const VRegister result = locs()->out(0).fpu_reg(); |
2251 const Register temp = locs()->temp(0).reg(); | 2251 const Register temp = locs()->temp(0).reg(); |
2252 __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes()); | 2252 __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes()); |
2253 const intptr_t cid = field()->UnboxedFieldCid(); | 2253 const intptr_t cid = field()->UnboxedFieldCid(); |
2254 switch (cid) { | 2254 switch (cid) { |
2255 case kDoubleCid: | 2255 case kDoubleCid: |
2256 __ Comment("UnboxedDoubleLoadFieldInstr"); | 2256 __ Comment("UnboxedDoubleLoadFieldInstr"); |
2257 __ LoadDFieldFromOffset(result, temp, Double::value_offset()); | 2257 __ LoadDFieldFromOffset(result, temp, Double::value_offset()); |
(...skipping 16 matching lines...) Expand all Loading... |
2274 const Register temp = locs()->temp(0).reg(); | 2274 const Register temp = locs()->temp(0).reg(); |
2275 | 2275 |
2276 Label load_pointer; | 2276 Label load_pointer; |
2277 Label load_double; | 2277 Label load_double; |
2278 Label load_float32x4; | 2278 Label load_float32x4; |
2279 Label load_float64x2; | 2279 Label load_float64x2; |
2280 | 2280 |
2281 __ LoadObject(result_reg, Field::ZoneHandle(field()->Original())); | 2281 __ LoadObject(result_reg, Field::ZoneHandle(field()->Original())); |
2282 | 2282 |
2283 FieldAddress field_cid_operand(result_reg, Field::guarded_cid_offset(), | 2283 FieldAddress field_cid_operand(result_reg, Field::guarded_cid_offset(), |
2284 kUnsignedWord); | 2284 kUnsignedHalfword); |
2285 FieldAddress field_nullability_operand( | 2285 FieldAddress field_nullability_operand( |
2286 result_reg, Field::is_nullable_offset(), kUnsignedWord); | 2286 result_reg, Field::is_nullable_offset(), kUnsignedHalfword); |
2287 | 2287 |
2288 __ ldr(temp, field_nullability_operand, kUnsignedWord); | 2288 __ ldr(temp, field_nullability_operand, kUnsignedHalfword); |
2289 __ CompareImmediate(temp, kNullCid); | 2289 __ CompareImmediate(temp, kNullCid); |
2290 __ b(&load_pointer, EQ); | 2290 __ b(&load_pointer, EQ); |
2291 | 2291 |
2292 __ ldr(temp, field_cid_operand, kUnsignedWord); | 2292 __ ldr(temp, field_cid_operand, kUnsignedHalfword); |
2293 __ CompareImmediate(temp, kDoubleCid); | 2293 __ CompareImmediate(temp, kDoubleCid); |
2294 __ b(&load_double, EQ); | 2294 __ b(&load_double, EQ); |
2295 | 2295 |
2296 __ ldr(temp, field_cid_operand, kUnsignedWord); | 2296 __ ldr(temp, field_cid_operand, kUnsignedHalfword); |
2297 __ CompareImmediate(temp, kFloat32x4Cid); | 2297 __ CompareImmediate(temp, kFloat32x4Cid); |
2298 __ b(&load_float32x4, EQ); | 2298 __ b(&load_float32x4, EQ); |
2299 | 2299 |
2300 __ ldr(temp, field_cid_operand, kUnsignedWord); | 2300 __ ldr(temp, field_cid_operand, kUnsignedHalfword); |
2301 __ CompareImmediate(temp, kFloat64x2Cid); | 2301 __ CompareImmediate(temp, kFloat64x2Cid); |
2302 __ b(&load_float64x2, EQ); | 2302 __ b(&load_float64x2, EQ); |
2303 | 2303 |
2304 // Fall through. | 2304 // Fall through. |
2305 __ b(&load_pointer); | 2305 __ b(&load_pointer); |
2306 | 2306 |
2307 if (!compiler->is_optimizing()) { | 2307 if (!compiler->is_optimizing()) { |
2308 locs()->live_registers()->Add(locs()->in(0)); | 2308 locs()->live_registers()->Add(locs()->in(0)); |
2309 } | 2309 } |
2310 | 2310 |
(...skipping 3766 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6077 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, deopt_id(), | 6077 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, deopt_id(), |
6078 kGrowRegExpStackRuntimeEntry, 1, locs()); | 6078 kGrowRegExpStackRuntimeEntry, 1, locs()); |
6079 __ Drop(1); | 6079 __ Drop(1); |
6080 __ Pop(result); | 6080 __ Pop(result); |
6081 } | 6081 } |
6082 | 6082 |
6083 | 6083 |
6084 } // namespace dart | 6084 } // namespace dart |
6085 | 6085 |
6086 #endif // defined TARGET_ARCH_ARM64 | 6086 #endif // defined TARGET_ARCH_ARM64 |
OLD | NEW |