OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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/code_generator.h" | 5 #include "vm/code_generator.h" |
6 | 6 |
7 #include "vm/assembler.h" | 7 #include "vm/assembler.h" |
8 #include "vm/ast.h" | 8 #include "vm/ast.h" |
9 #include "vm/code_patcher.h" | 9 #include "vm/code_patcher.h" |
10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
(...skipping 653 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
664 CodePatcher::GetStaticCallTargetAt(caller_frame->pc(), caller_code)); | 664 CodePatcher::GetStaticCallTargetAt(caller_frame->pc(), caller_code)); |
665 CodePatcher::PatchStaticCallAt(caller_frame->pc(), | 665 CodePatcher::PatchStaticCallAt(caller_frame->pc(), |
666 caller_code, | 666 caller_code, |
667 target_code); | 667 target_code); |
668 caller_code.SetStaticCallTargetCodeAt(caller_frame->pc(), target_code); | 668 caller_code.SetStaticCallTargetCodeAt(caller_frame->pc(), target_code); |
669 if (FLAG_trace_patching) { | 669 if (FLAG_trace_patching) { |
670 THR_Print("PatchStaticCall: patching caller pc %#" Px "" | 670 THR_Print("PatchStaticCall: patching caller pc %#" Px "" |
671 " to '%s' new entry point %#" Px " (%s)\n", | 671 " to '%s' new entry point %#" Px " (%s)\n", |
672 caller_frame->pc(), | 672 caller_frame->pc(), |
673 target_function.ToFullyQualifiedCString(), | 673 target_function.ToFullyQualifiedCString(), |
674 target_code.EntryPoint(), | 674 target_code.UncheckedEntryPoint(), |
675 target_code.is_optimized() ? "optimized" : "unoptimized"); | 675 target_code.is_optimized() ? "optimized" : "unoptimized"); |
676 } | 676 } |
677 arguments.SetReturn(target_code); | 677 arguments.SetReturn(target_code); |
678 } | 678 } |
679 | 679 |
680 | 680 |
681 // Result of an invoke may be an unhandled exception, in which case we | 681 // Result of an invoke may be an unhandled exception, in which case we |
682 // rethrow it. | 682 // rethrow it. |
683 static void CheckResultError(const Object& result) { | 683 static void CheckResultError(const Object& result) { |
684 if (result.IsError()) { | 684 if (result.IsError()) { |
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1021 OS::PrintErr("StaticCallMissHandler at %#" Px | 1021 OS::PrintErr("StaticCallMissHandler at %#" Px |
1022 " target %s (%" Pd ", %" Pd ")\n", | 1022 " target %s (%" Pd ", %" Pd ")\n", |
1023 caller_frame->pc(), target.ToCString(), cids[0], cids[1]); | 1023 caller_frame->pc(), target.ToCString(), cids[0], cids[1]); |
1024 } | 1024 } |
1025 arguments.SetReturn(target); | 1025 arguments.SetReturn(target); |
1026 } | 1026 } |
1027 | 1027 |
1028 | 1028 |
1029 // Handle a miss of a megamorphic cache. | 1029 // Handle a miss of a megamorphic cache. |
1030 // Arg0: Receiver. | 1030 // Arg0: Receiver. |
| 1031 // Returns: the ICData used to continue with a polymorphic call. |
| 1032 DEFINE_RUNTIME_ENTRY(MonomorphicMiss, 1) { |
| 1033 #if defined(TARGET_ARCH_DBC) |
| 1034 // DBC does not use switchable calls. |
| 1035 UNREACHABLE(); |
| 1036 #else |
| 1037 const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0)); |
| 1038 |
| 1039 DartFrameIterator iterator; |
| 1040 StackFrame* caller_frame = iterator.NextFrame(); |
| 1041 ASSERT(caller_frame->IsDartFrame()); |
| 1042 const Code& caller_code = Code::Handle(zone, caller_frame->LookupDartCode()); |
| 1043 const Function& caller_function = |
| 1044 Function::Handle(zone, caller_frame->LookupDartFunction()); |
| 1045 |
| 1046 Smi& old_expected_cid = Smi::Handle(zone); |
| 1047 old_expected_cid ^= CodePatcher::GetSwitchableCallDataAt(caller_frame->pc(), |
| 1048 caller_code); |
| 1049 const Code& old_target_code = |
| 1050 Code::Handle(CodePatcher::GetSwitchableCallTargetAt(caller_frame->pc(), |
| 1051 caller_code)); |
| 1052 Function& old_target = Function::Handle(zone); |
| 1053 old_target ^= old_target_code.owner(); |
| 1054 |
| 1055 // We lost the original ICData when we patched to the monomorphic case. |
| 1056 const String& name = String::Handle(zone, old_target.name()); |
| 1057 ASSERT(!old_target.HasOptionalParameters()); |
| 1058 const Array& descriptor = Array::Handle(zone, |
| 1059 ArgumentsDescriptor::New(old_target.num_fixed_parameters())); |
| 1060 const ICData& ic_data = |
| 1061 ICData::Handle(zone, ICData::New(caller_function, |
| 1062 name, |
| 1063 descriptor, |
| 1064 Thread::kNoDeoptId, |
| 1065 1, /* args_tested */ |
| 1066 false /* static_call */)); |
| 1067 |
| 1068 // Add the first target. |
| 1069 ic_data.AddReceiverCheck(old_expected_cid.Value(), old_target); |
| 1070 |
| 1071 // Maybe add the new target. |
| 1072 Class& cls = Class::Handle(zone, receiver.clazz()); |
| 1073 ArgumentsDescriptor args_desc(descriptor); |
| 1074 Function& target_function = Function::Handle(zone, |
| 1075 Resolver::ResolveDynamicForReceiverClass(cls, |
| 1076 name, |
| 1077 args_desc)); |
| 1078 if (target_function.IsNull()) { |
| 1079 target_function = InlineCacheMissHelper(receiver, descriptor, name); |
| 1080 } |
| 1081 if (target_function.IsNull()) { |
| 1082 ASSERT(!FLAG_lazy_dispatchers); |
| 1083 } else { |
| 1084 ic_data.AddReceiverCheck(receiver.GetClassId(), target_function); |
| 1085 } |
| 1086 |
| 1087 // Patch to call through stub. |
| 1088 const Code& stub = |
| 1089 Code::Handle(zone, StubCode::ICLookupThroughCode_entry()->code()); |
| 1090 ASSERT(!Isolate::Current()->compilation_allowed()); |
| 1091 CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), |
| 1092 caller_code, |
| 1093 ic_data, |
| 1094 stub); |
| 1095 |
| 1096 // Return the ICData. The miss stub will jump to continue in the IC lookup |
| 1097 // stub. |
| 1098 arguments.SetReturn(ic_data); |
| 1099 #endif // !defined(TARGET_ARCH_DBC) |
| 1100 } |
| 1101 |
| 1102 |
| 1103 // Handle a miss of a megamorphic cache. |
| 1104 // Arg0: Receiver. |
1031 // Arg1: ICData or MegamorphicCache. | 1105 // Arg1: ICData or MegamorphicCache. |
1032 // Arg2: Arguments descriptor array. | 1106 // Arg2: Arguments descriptor array. |
1033 // Returns: target function to call. | 1107 // Returns: target function to call. |
1034 DEFINE_RUNTIME_ENTRY(MegamorphicCacheMissHandler, 3) { | 1108 DEFINE_RUNTIME_ENTRY(MegamorphicCacheMissHandler, 3) { |
1035 // DBC does not use megamorphic calls right now. | 1109 #if defined(TARGET_ARCH_DBC) |
1036 #if !defined(TARGET_ARCH_DBC) | 1110 // DBC does not use megamorphic calls right now. |
| 1111 UNREACHABLE(); |
| 1112 #else |
1037 const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0)); | 1113 const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0)); |
1038 const Object& ic_data_or_cache = Object::Handle(zone, arguments.ArgAt(1)); | 1114 const Object& ic_data_or_cache = Object::Handle(zone, arguments.ArgAt(1)); |
1039 const Array& descriptor = Array::CheckedHandle(zone, arguments.ArgAt(2)); | 1115 const Array& descriptor = Array::CheckedHandle(zone, arguments.ArgAt(2)); |
1040 String& name = String::Handle(zone); | 1116 String& name = String::Handle(zone); |
1041 if (ic_data_or_cache.IsICData()) { | 1117 if (ic_data_or_cache.IsICData()) { |
1042 name = ICData::Cast(ic_data_or_cache).target_name(); | 1118 name = ICData::Cast(ic_data_or_cache).target_name(); |
1043 } else { | 1119 } else { |
1044 ASSERT(ic_data_or_cache.IsMegamorphicCache()); | 1120 ASSERT(ic_data_or_cache.IsMegamorphicCache()); |
1045 name = MegamorphicCache::Cast(ic_data_or_cache).target_name(); | 1121 name = MegamorphicCache::Cast(ic_data_or_cache).target_name(); |
1046 } | 1122 } |
(...skipping 13 matching lines...) Expand all Loading... |
1060 target_function = InlineCacheMissHelper(receiver, descriptor, name); | 1136 target_function = InlineCacheMissHelper(receiver, descriptor, name); |
1061 } | 1137 } |
1062 if (target_function.IsNull()) { | 1138 if (target_function.IsNull()) { |
1063 ASSERT(!FLAG_lazy_dispatchers); | 1139 ASSERT(!FLAG_lazy_dispatchers); |
1064 arguments.SetReturn(target_function); | 1140 arguments.SetReturn(target_function); |
1065 return; | 1141 return; |
1066 } | 1142 } |
1067 | 1143 |
1068 if (ic_data_or_cache.IsICData()) { | 1144 if (ic_data_or_cache.IsICData()) { |
1069 const ICData& ic_data = ICData::Cast(ic_data_or_cache); | 1145 const ICData& ic_data = ICData::Cast(ic_data_or_cache); |
1070 ic_data.AddReceiverCheck(receiver.GetClassId(), target_function); | 1146 |
1071 if (ic_data.NumberOfChecks() > FLAG_max_polymorphic_checks) { | 1147 if ((ic_data.NumberOfChecks() == 0) && |
1072 // Switch to megamorphic call. | 1148 !target_function.HasOptionalParameters() && |
1073 const MegamorphicCache& cache = MegamorphicCache::Handle(zone, | 1149 !Isolate::Current()->compilation_allowed()) { |
1074 MegamorphicCacheTable::Lookup(isolate, name, descriptor)); | 1150 // This call site is unlinked: transition to a monomorphic direct call. |
| 1151 // Note we cannot do this if the target has optional parameters because |
| 1152 // the monomorphic direct call does not load the arguments descriptor. |
| 1153 // We cannot do this if we are still in the middle of precompiling because |
| 1154 // the monomorphic case hides an live instance selector from the |
| 1155 // treeshaker. |
| 1156 |
| 1157 if (!target_function.HasCode()) { |
| 1158 const Error& error = |
| 1159 Error::Handle(Compiler::CompileFunction(thread, target_function)); |
| 1160 if (!error.IsNull()) { |
| 1161 Exceptions::PropagateError(error); |
| 1162 } |
| 1163 } |
| 1164 |
1075 DartFrameIterator iterator; | 1165 DartFrameIterator iterator; |
1076 StackFrame* miss_function_frame = iterator.NextFrame(); | 1166 StackFrame* miss_function_frame = iterator.NextFrame(); |
1077 ASSERT(miss_function_frame->IsDartFrame()); | 1167 ASSERT(miss_function_frame->IsDartFrame()); |
1078 StackFrame* caller_frame = iterator.NextFrame(); | 1168 StackFrame* caller_frame = iterator.NextFrame(); |
1079 ASSERT(caller_frame->IsDartFrame()); | 1169 ASSERT(caller_frame->IsDartFrame()); |
1080 const Code& code = Code::Handle(zone, caller_frame->LookupDartCode()); | 1170 const Code& caller_code = |
1081 const Code& stub = | 1171 Code::Handle(zone, caller_frame->LookupDartCode()); |
1082 Code::Handle(zone, StubCode::MegamorphicLookup_entry()->code()); | 1172 const Code& target_code = |
1083 CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), | 1173 Code::Handle(zone, target_function.CurrentCode()); |
1084 code, ic_data, cache, stub); | 1174 const Smi& expected_cid = |
| 1175 Smi::Handle(zone, Smi::New(receiver.GetClassId())); |
| 1176 |
| 1177 CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), caller_code, |
| 1178 expected_cid, target_code); |
| 1179 } else { |
| 1180 ic_data.AddReceiverCheck(receiver.GetClassId(), target_function); |
| 1181 if (ic_data.NumberOfChecks() > FLAG_max_polymorphic_checks) { |
| 1182 // Switch to megamorphic call. |
| 1183 const MegamorphicCache& cache = MegamorphicCache::Handle(zone, |
| 1184 MegamorphicCacheTable::Lookup(isolate, name, descriptor)); |
| 1185 DartFrameIterator iterator; |
| 1186 StackFrame* miss_function_frame = iterator.NextFrame(); |
| 1187 ASSERT(miss_function_frame->IsDartFrame()); |
| 1188 StackFrame* caller_frame = iterator.NextFrame(); |
| 1189 ASSERT(caller_frame->IsDartFrame()); |
| 1190 const Code& caller_code = |
| 1191 Code::Handle(zone, caller_frame->LookupDartCode()); |
| 1192 const Code& stub = |
| 1193 Code::Handle(zone, StubCode::MegamorphicLookup_entry()->code()); |
| 1194 |
| 1195 CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), caller_code, |
| 1196 cache, stub); |
| 1197 } |
1085 } | 1198 } |
1086 } else { | 1199 } else { |
1087 const MegamorphicCache& cache = MegamorphicCache::Cast(ic_data_or_cache); | 1200 const MegamorphicCache& cache = MegamorphicCache::Cast(ic_data_or_cache); |
1088 // Insert function found into cache and return it. | 1201 // Insert function found into cache and return it. |
1089 cache.EnsureCapacity(); | 1202 cache.EnsureCapacity(); |
1090 const Smi& class_id = Smi::Handle(zone, Smi::New(cls.id())); | 1203 const Smi& class_id = Smi::Handle(zone, Smi::New(cls.id())); |
1091 cache.Insert(class_id, target_function); | 1204 cache.Insert(class_id, target_function); |
1092 } | 1205 } |
1093 arguments.SetReturn(target_function); | 1206 arguments.SetReturn(target_function); |
1094 #else | |
1095 UNREACHABLE(); | |
1096 #endif // !defined(TARGET_ARCH_DBC) | 1207 #endif // !defined(TARGET_ARCH_DBC) |
1097 } | 1208 } |
1098 | 1209 |
1099 | 1210 |
1100 // Invoke appropriate noSuchMethod or closure from getter. | 1211 // Invoke appropriate noSuchMethod or closure from getter. |
1101 // Arg0: receiver | 1212 // Arg0: receiver |
1102 // Arg1: ICData or MegamorphicCache | 1213 // Arg1: ICData or MegamorphicCache |
1103 // Arg2: arguments descriptor array | 1214 // Arg2: arguments descriptor array |
1104 // Arg3: arguments array | 1215 // Arg3: arguments array |
1105 DEFINE_RUNTIME_ENTRY(InvokeNoSuchMethodDispatcher, 4) { | 1216 DEFINE_RUNTIME_ENTRY(InvokeNoSuchMethodDispatcher, 4) { |
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1454 } | 1565 } |
1455 | 1566 |
1456 const Code& optimized_code = Code::Handle(function.CurrentCode()); | 1567 const Code& optimized_code = Code::Handle(function.CurrentCode()); |
1457 // The current code will not be changed in the case that the compiler | 1568 // The current code will not be changed in the case that the compiler |
1458 // bailed out during OSR compilation. | 1569 // bailed out during OSR compilation. |
1459 if (optimized_code.raw() != original_code.raw()) { | 1570 if (optimized_code.raw() != original_code.raw()) { |
1460 // The OSR code does not work for calling the function, so restore the | 1571 // The OSR code does not work for calling the function, so restore the |
1461 // unoptimized code. Patch the stack frame to return into the OSR | 1572 // unoptimized code. Patch the stack frame to return into the OSR |
1462 // code. | 1573 // code. |
1463 uword optimized_entry = | 1574 uword optimized_entry = |
1464 Instructions::Handle(optimized_code.instructions()).EntryPoint(); | 1575 Instructions::UncheckedEntryPoint(optimized_code.instructions()); |
1465 function.AttachCode(original_code); | 1576 function.AttachCode(original_code); |
1466 frame->set_pc(optimized_entry); | 1577 frame->set_pc(optimized_entry); |
1467 frame->set_pc_marker(optimized_code.raw()); | 1578 frame->set_pc_marker(optimized_code.raw()); |
1468 } | 1579 } |
1469 } | 1580 } |
1470 } | 1581 } |
1471 | 1582 |
1472 | 1583 |
1473 DEFINE_RUNTIME_ENTRY(TraceICCall, 2) { | 1584 DEFINE_RUNTIME_ENTRY(TraceICCall, 2) { |
1474 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(0)); | 1585 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(0)); |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1589 zone, target_function.CurrentCode()); | 1700 zone, target_function.CurrentCode()); |
1590 CodePatcher::PatchStaticCallAt(frame->pc(), | 1701 CodePatcher::PatchStaticCallAt(frame->pc(), |
1591 caller_code, | 1702 caller_code, |
1592 current_target_code); | 1703 current_target_code); |
1593 caller_code.SetStaticCallTargetCodeAt(frame->pc(), current_target_code); | 1704 caller_code.SetStaticCallTargetCodeAt(frame->pc(), current_target_code); |
1594 if (FLAG_trace_patching) { | 1705 if (FLAG_trace_patching) { |
1595 OS::PrintErr("FixCallersTarget: caller %#" Px " " | 1706 OS::PrintErr("FixCallersTarget: caller %#" Px " " |
1596 "target '%s' -> %#" Px "\n", | 1707 "target '%s' -> %#" Px "\n", |
1597 frame->pc(), | 1708 frame->pc(), |
1598 target_function.ToFullyQualifiedCString(), | 1709 target_function.ToFullyQualifiedCString(), |
1599 current_target_code.EntryPoint()); | 1710 current_target_code.UncheckedEntryPoint()); |
1600 } | 1711 } |
1601 arguments.SetReturn(current_target_code); | 1712 arguments.SetReturn(current_target_code); |
1602 } | 1713 } |
1603 | 1714 |
1604 | 1715 |
1605 // The caller tried to allocate an instance via an invalidated allocation | 1716 // The caller tried to allocate an instance via an invalidated allocation |
1606 // stub. | 1717 // stub. |
1607 DEFINE_RUNTIME_ENTRY(FixAllocationStubTarget, 0) { | 1718 DEFINE_RUNTIME_ENTRY(FixAllocationStubTarget, 0) { |
1608 #if !defined(DART_PRECOMPILED_RUNTIME) | 1719 #if !defined(DART_PRECOMPILED_RUNTIME) |
1609 StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames); | 1720 StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames); |
(...skipping 21 matching lines...) Expand all Loading... |
1631 } | 1742 } |
1632 CodePatcher::PatchStaticCallAt(frame->pc(), | 1743 CodePatcher::PatchStaticCallAt(frame->pc(), |
1633 caller_code, | 1744 caller_code, |
1634 alloc_stub); | 1745 alloc_stub); |
1635 caller_code.SetStubCallTargetCodeAt(frame->pc(), alloc_stub); | 1746 caller_code.SetStubCallTargetCodeAt(frame->pc(), alloc_stub); |
1636 if (FLAG_trace_patching) { | 1747 if (FLAG_trace_patching) { |
1637 OS::PrintErr("FixAllocationStubTarget: caller %#" Px " alloc-class %s " | 1748 OS::PrintErr("FixAllocationStubTarget: caller %#" Px " alloc-class %s " |
1638 " -> %#" Px "\n", | 1749 " -> %#" Px "\n", |
1639 frame->pc(), | 1750 frame->pc(), |
1640 alloc_class.ToCString(), | 1751 alloc_class.ToCString(), |
1641 alloc_stub.EntryPoint()); | 1752 alloc_stub.UncheckedEntryPoint()); |
1642 } | 1753 } |
1643 arguments.SetReturn(alloc_stub); | 1754 arguments.SetReturn(alloc_stub); |
1644 #else | 1755 #else |
1645 UNREACHABLE(); | 1756 UNREACHABLE(); |
1646 #endif | 1757 #endif |
1647 } | 1758 } |
1648 | 1759 |
1649 | 1760 |
1650 const char* DeoptReasonToCString(ICData::DeoptReasonId deopt_reason) { | 1761 const char* DeoptReasonToCString(ICData::DeoptReasonId deopt_reason) { |
1651 switch (deopt_reason) { | 1762 switch (deopt_reason) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1683 } | 1794 } |
1684 // Patch call site (lazy deoptimization is quite rare, patching it twice | 1795 // Patch call site (lazy deoptimization is quite rare, patching it twice |
1685 // is not a performance issue). | 1796 // is not a performance issue). |
1686 uword lazy_deopt_jump = optimized_code.GetLazyDeoptPc(); | 1797 uword lazy_deopt_jump = optimized_code.GetLazyDeoptPc(); |
1687 #if !defined(TARGET_ARCH_DBC) | 1798 #if !defined(TARGET_ARCH_DBC) |
1688 ASSERT(lazy_deopt_jump != 0); | 1799 ASSERT(lazy_deopt_jump != 0); |
1689 #endif | 1800 #endif |
1690 const Instructions& instrs = | 1801 const Instructions& instrs = |
1691 Instructions::Handle(zone, optimized_code.instructions()); | 1802 Instructions::Handle(zone, optimized_code.instructions()); |
1692 { | 1803 { |
1693 WritableInstructionsScope writable(instrs.EntryPoint(), instrs.size()); | 1804 WritableInstructionsScope writable(instrs.PayloadStart(), instrs.size()); |
1694 CodePatcher::InsertDeoptimizationCallAt(pc, lazy_deopt_jump); | 1805 CodePatcher::InsertDeoptimizationCallAt(pc, lazy_deopt_jump); |
1695 } | 1806 } |
1696 if (FLAG_trace_patching) { | 1807 if (FLAG_trace_patching) { |
1697 const String& name = String::Handle(function.name()); | 1808 const String& name = String::Handle(function.name()); |
1698 OS::PrintErr("InsertDeoptimizationCallAt: %" Px " to %" Px " for %s\n", pc, | 1809 OS::PrintErr("InsertDeoptimizationCallAt: %" Px " to %" Px " for %s\n", pc, |
1699 lazy_deopt_jump, name.ToCString()); | 1810 lazy_deopt_jump, name.ToCString()); |
1700 } | 1811 } |
1701 // Mark code as dead (do not GC its embedded objects). | 1812 // Mark code as dead (do not GC its embedded objects). |
1702 optimized_code.set_is_alive(false); | 1813 optimized_code.set_is_alive(false); |
1703 } | 1814 } |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1959 const intptr_t elm_size = old_data.ElementSizeInBytes(); | 2070 const intptr_t elm_size = old_data.ElementSizeInBytes(); |
1960 const TypedData& new_data = | 2071 const TypedData& new_data = |
1961 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); | 2072 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); |
1962 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); | 2073 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); |
1963 typed_data_cell.SetAt(0, new_data); | 2074 typed_data_cell.SetAt(0, new_data); |
1964 arguments.SetReturn(new_data); | 2075 arguments.SetReturn(new_data); |
1965 } | 2076 } |
1966 | 2077 |
1967 | 2078 |
1968 } // namespace dart | 2079 } // namespace dart |
OLD | NEW |