OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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 #include "src/wasm/wasm-interpreter.h" | 5 #include "src/wasm/wasm-interpreter.h" |
6 | 6 |
7 #include "src/utils.h" | 7 #include "src/utils.h" |
8 #include "src/wasm/decoder.h" | 8 #include "src/wasm/decoder.h" |
9 #include "src/wasm/function-body-decoder.h" | 9 #include "src/wasm/function-body-decoder.h" |
10 #include "src/wasm/wasm-external-refs.h" | 10 #include "src/wasm/wasm-external-refs.h" |
(...skipping 907 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
918 | 918 |
919 namespace { | 919 namespace { |
920 // Responsible for executing code directly. | 920 // Responsible for executing code directly. |
921 class ThreadImpl { | 921 class ThreadImpl { |
922 public: | 922 public: |
923 ThreadImpl(Zone* zone, CodeMap* codemap, WasmInstance* instance) | 923 ThreadImpl(Zone* zone, CodeMap* codemap, WasmInstance* instance) |
924 : codemap_(codemap), | 924 : codemap_(codemap), |
925 instance_(instance), | 925 instance_(instance), |
926 stack_(zone), | 926 stack_(zone), |
927 frames_(zone), | 927 frames_(zone), |
928 blocks_(zone), | 928 blocks_(zone) {} |
929 state_(WasmInterpreter::STOPPED), | |
930 break_pc_(kInvalidPc), | |
931 trap_reason_(kTrapCount), | |
932 possible_nondeterminism_(false) {} | |
933 | 929 |
934 //========================================================================== | 930 //========================================================================== |
935 // Implementation of public interface for WasmInterpreter::Thread. | 931 // Implementation of public interface for WasmInterpreter::Thread. |
936 //========================================================================== | 932 //========================================================================== |
937 | 933 |
938 WasmInterpreter::State state() { return state_; } | 934 WasmInterpreter::State state() { return state_; } |
939 | 935 |
940 void PushFrame(const WasmFunction* function, WasmVal* args) { | 936 void PushFrame(const WasmFunction* function, WasmVal* args) { |
941 InterpreterCode* code = codemap()->FindCode(function); | 937 InterpreterCode* code = codemap()->FindCode(function); |
942 CHECK_NOT_NULL(code); | 938 CHECK_NOT_NULL(code); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1007 if (state_ == WasmInterpreter::TRAPPED) return WasmVal(0xdeadbeef); | 1003 if (state_ == WasmInterpreter::TRAPPED) return WasmVal(0xdeadbeef); |
1008 CHECK_EQ(WasmInterpreter::FINISHED, state_); | 1004 CHECK_EQ(WasmInterpreter::FINISHED, state_); |
1009 CHECK_LT(static_cast<size_t>(index), stack_.size()); | 1005 CHECK_LT(static_cast<size_t>(index), stack_.size()); |
1010 return stack_[index]; | 1006 return stack_[index]; |
1011 } | 1007 } |
1012 | 1008 |
1013 pc_t GetBreakpointPc() { return break_pc_; } | 1009 pc_t GetBreakpointPc() { return break_pc_; } |
1014 | 1010 |
1015 bool PossibleNondeterminism() { return possible_nondeterminism_; } | 1011 bool PossibleNondeterminism() { return possible_nondeterminism_; } |
1016 | 1012 |
| 1013 void AddBreakFlags(uint8_t flags) { break_flags_ |= flags; } |
| 1014 |
| 1015 void ClearBreakFlags() { break_flags_ = WasmInterpreter::BreakFlag::None; } |
| 1016 |
1017 private: | 1017 private: |
1018 // Entries on the stack of functions being evaluated. | 1018 // Entries on the stack of functions being evaluated. |
1019 struct Frame { | 1019 struct Frame { |
1020 InterpreterCode* code; | 1020 InterpreterCode* code; |
1021 pc_t call_pc; | 1021 pc_t call_pc; |
1022 pc_t ret_pc; | 1022 pc_t ret_pc; |
1023 sp_t sp; | 1023 sp_t sp; |
1024 | 1024 |
1025 // Limit of parameters. | 1025 // Limit of parameters. |
1026 sp_t plimit() { return sp + code->function->sig->parameter_count(); } | 1026 sp_t plimit() { return sp + code->function->sig->parameter_count(); } |
1027 // Limit of locals. | 1027 // Limit of locals. |
1028 sp_t llimit() { return plimit() + code->locals.type_list.size(); } | 1028 sp_t llimit() { return plimit() + code->locals.type_list.size(); } |
1029 }; | 1029 }; |
1030 | 1030 |
1031 struct Block { | 1031 struct Block { |
1032 pc_t pc; | 1032 pc_t pc; |
1033 sp_t sp; | 1033 sp_t sp; |
1034 size_t fp; | 1034 size_t fp; |
1035 unsigned arity; | 1035 unsigned arity; |
1036 }; | 1036 }; |
1037 | 1037 |
1038 CodeMap* codemap_; | 1038 CodeMap* codemap_; |
1039 WasmInstance* instance_; | 1039 WasmInstance* instance_; |
1040 ZoneVector<WasmVal> stack_; | 1040 ZoneVector<WasmVal> stack_; |
1041 ZoneVector<Frame> frames_; | 1041 ZoneVector<Frame> frames_; |
1042 ZoneVector<Block> blocks_; | 1042 ZoneVector<Block> blocks_; |
1043 WasmInterpreter::State state_; | 1043 WasmInterpreter::State state_ = WasmInterpreter::STOPPED; |
1044 pc_t break_pc_; | 1044 pc_t break_pc_ = kInvalidPc; |
1045 TrapReason trap_reason_; | 1045 TrapReason trap_reason_ = kTrapCount; |
1046 bool possible_nondeterminism_; | 1046 bool possible_nondeterminism_ = false; |
| 1047 uint8_t break_flags_ = 0; // a combination of WasmInterpreter::BreakFlag |
1047 | 1048 |
1048 CodeMap* codemap() { return codemap_; } | 1049 CodeMap* codemap() { return codemap_; } |
1049 WasmInstance* instance() { return instance_; } | 1050 WasmInstance* instance() { return instance_; } |
1050 const WasmModule* module() { return instance_->module; } | 1051 const WasmModule* module() { return instance_->module; } |
1051 | 1052 |
1052 void DoTrap(TrapReason trap, pc_t pc) { | 1053 void DoTrap(TrapReason trap, pc_t pc) { |
1053 state_ = WasmInterpreter::TRAPPED; | 1054 state_ = WasmInterpreter::TRAPPED; |
1054 trap_reason_ = trap; | 1055 trap_reason_ = trap; |
1055 CommitPc(pc); | 1056 CommitPc(pc); |
1056 } | 1057 } |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1171 size_t pop_count = stack_.size() - dest - arity; | 1172 size_t pop_count = stack_.size() - dest - arity; |
1172 for (size_t i = 0; i < arity; i++) { | 1173 for (size_t i = 0; i < arity; i++) { |
1173 stack_[dest + i] = stack_[dest + pop_count + i]; | 1174 stack_[dest + i] = stack_[dest + pop_count + i]; |
1174 } | 1175 } |
1175 stack_.resize(stack_.size() - pop_count); | 1176 stack_.resize(stack_.size() - pop_count); |
1176 } | 1177 } |
1177 | 1178 |
1178 void Execute(InterpreterCode* code, pc_t pc, int max) { | 1179 void Execute(InterpreterCode* code, pc_t pc, int max) { |
1179 Decoder decoder(code->start, code->end); | 1180 Decoder decoder(code->start, code->end); |
1180 pc_t limit = code->end - code->start; | 1181 pc_t limit = code->end - code->start; |
1181 while (true) { | 1182 while (--max >= 0) { |
1182 if (max-- <= 0) { | 1183 #define PAUSE_IF_BREAK_FLAG(flag) \ |
1183 // Maximum number of instructions reached. | 1184 if (V8_UNLIKELY(break_flags_ & WasmInterpreter::BreakFlag::flag)) max = 0; |
1184 state_ = WasmInterpreter::PAUSED; | |
1185 return CommitPc(pc); | |
1186 } | |
1187 | 1185 |
1188 if (pc >= limit) { | 1186 if (pc >= limit) { |
1189 // Fell off end of code; do an implicit return. | 1187 // Fell off end of code; do an implicit return. |
1190 TRACE("@%-3zu: ImplicitReturn\n", pc); | 1188 TRACE("@%-3zu: ImplicitReturn\n", pc); |
1191 if (!DoReturn(&code, &pc, &limit, code->function->sig->return_count())) | 1189 if (!DoReturn(&code, &pc, &limit, code->function->sig->return_count())) |
1192 return; | 1190 return; |
1193 decoder.Reset(code->start, code->end); | 1191 decoder.Reset(code->start, code->end); |
| 1192 PAUSE_IF_BREAK_FLAG(AfterReturn); |
1194 continue; | 1193 continue; |
1195 } | 1194 } |
1196 | 1195 |
1197 const char* skip = " "; | 1196 const char* skip = " "; |
1198 int len = 1; | 1197 int len = 1; |
1199 byte opcode = code->start[pc]; | 1198 byte opcode = code->start[pc]; |
1200 byte orig = opcode; | 1199 byte orig = opcode; |
1201 if (opcode == kInternalBreakpoint) { | 1200 if (V8_UNLIKELY(opcode == kInternalBreakpoint)) { |
1202 orig = code->orig_start[pc]; | 1201 orig = code->orig_start[pc]; |
1203 if (SkipBreakpoint(code, pc)) { | 1202 if (SkipBreakpoint(code, pc)) { |
1204 // skip breakpoint by switching on original code. | 1203 // skip breakpoint by switching on original code. |
1205 skip = "[skip] "; | 1204 skip = "[skip] "; |
1206 } else { | 1205 } else { |
1207 state_ = WasmInterpreter::PAUSED; | 1206 state_ = WasmInterpreter::PAUSED; |
1208 TRACE("@%-3zu: [break] %-24s:", pc, | 1207 TRACE("@%-3zu: [break] %-24s:", pc, |
1209 WasmOpcodes::OpcodeName(static_cast<WasmOpcode>(orig))); | 1208 WasmOpcodes::OpcodeName(static_cast<WasmOpcode>(orig))); |
1210 TraceValueStack(); | 1209 TraceValueStack(); |
1211 TRACE("\n"); | 1210 TRACE("\n"); |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1293 depth = iterator.next(); | 1292 depth = iterator.next(); |
1294 } | 1293 } |
1295 len = key + DoBreak(code, pc + key, static_cast<size_t>(depth)); | 1294 len = key + DoBreak(code, pc + key, static_cast<size_t>(depth)); |
1296 TRACE(" br[%u] => @%zu\n", key, pc + key + len); | 1295 TRACE(" br[%u] => @%zu\n", key, pc + key + len); |
1297 break; | 1296 break; |
1298 } | 1297 } |
1299 case kExprReturn: { | 1298 case kExprReturn: { |
1300 size_t arity = code->function->sig->return_count(); | 1299 size_t arity = code->function->sig->return_count(); |
1301 if (!DoReturn(&code, &pc, &limit, arity)) return; | 1300 if (!DoReturn(&code, &pc, &limit, arity)) return; |
1302 decoder.Reset(code->start, code->end); | 1301 decoder.Reset(code->start, code->end); |
| 1302 PAUSE_IF_BREAK_FLAG(AfterReturn); |
1303 continue; | 1303 continue; |
1304 } | 1304 } |
1305 case kExprUnreachable: { | 1305 case kExprUnreachable: { |
1306 DoTrap(kTrapUnreachable, pc); | 1306 DoTrap(kTrapUnreachable, pc); |
1307 return CommitPc(pc); | 1307 return CommitPc(pc); |
1308 } | 1308 } |
1309 case kExprEnd: { | 1309 case kExprEnd: { |
1310 blocks_.pop_back(); | 1310 blocks_.pop_back(); |
1311 break; | 1311 break; |
1312 } | 1312 } |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1358 case kExprDrop: { | 1358 case kExprDrop: { |
1359 Pop(); | 1359 Pop(); |
1360 break; | 1360 break; |
1361 } | 1361 } |
1362 case kExprCallFunction: { | 1362 case kExprCallFunction: { |
1363 CallFunctionOperand operand(&decoder, code->at(pc)); | 1363 CallFunctionOperand operand(&decoder, code->at(pc)); |
1364 InterpreterCode* target = codemap()->GetCode(operand.index); | 1364 InterpreterCode* target = codemap()->GetCode(operand.index); |
1365 DoCall(target, &pc, pc + 1 + operand.length, &limit); | 1365 DoCall(target, &pc, pc + 1 + operand.length, &limit); |
1366 code = target; | 1366 code = target; |
1367 decoder.Reset(code->start, code->end); | 1367 decoder.Reset(code->start, code->end); |
| 1368 PAUSE_IF_BREAK_FLAG(AfterCall); |
1368 continue; | 1369 continue; |
1369 } | 1370 } |
1370 case kExprCallIndirect: { | 1371 case kExprCallIndirect: { |
1371 CallIndirectOperand operand(&decoder, code->at(pc)); | 1372 CallIndirectOperand operand(&decoder, code->at(pc)); |
1372 uint32_t entry_index = Pop().to<uint32_t>(); | 1373 uint32_t entry_index = Pop().to<uint32_t>(); |
1373 // Assume only one table for now. | 1374 // Assume only one table for now. |
1374 DCHECK_LE(module()->function_tables.size(), 1u); | 1375 DCHECK_LE(module()->function_tables.size(), 1u); |
1375 InterpreterCode* target = codemap()->GetIndirectCode(0, entry_index); | 1376 InterpreterCode* target = codemap()->GetIndirectCode(0, entry_index); |
1376 if (target == nullptr) { | 1377 if (target == nullptr) { |
1377 return DoTrap(kTrapFuncInvalid, pc); | 1378 return DoTrap(kTrapFuncInvalid, pc); |
1378 } else if (target->function->sig_index != operand.index) { | 1379 } else if (target->function->sig_index != operand.index) { |
1379 // If not an exact match, we have to do a canonical check. | 1380 // If not an exact match, we have to do a canonical check. |
1380 // TODO(titzer): make this faster with some kind of caching? | 1381 // TODO(titzer): make this faster with some kind of caching? |
1381 const WasmIndirectFunctionTable* table = | 1382 const WasmIndirectFunctionTable* table = |
1382 &module()->function_tables[0]; | 1383 &module()->function_tables[0]; |
1383 int function_key = table->map.Find(target->function->sig); | 1384 int function_key = table->map.Find(target->function->sig); |
1384 if (function_key < 0 || | 1385 if (function_key < 0 || |
1385 (function_key != | 1386 (function_key != |
1386 table->map.Find(module()->signatures[operand.index]))) { | 1387 table->map.Find(module()->signatures[operand.index]))) { |
1387 return DoTrap(kTrapFuncSigMismatch, pc); | 1388 return DoTrap(kTrapFuncSigMismatch, pc); |
1388 } | 1389 } |
1389 } | 1390 } |
1390 | 1391 |
1391 DoCall(target, &pc, pc + 1 + operand.length, &limit); | 1392 DoCall(target, &pc, pc + 1 + operand.length, &limit); |
1392 code = target; | 1393 code = target; |
1393 decoder.Reset(code->start, code->end); | 1394 decoder.Reset(code->start, code->end); |
| 1395 PAUSE_IF_BREAK_FLAG(AfterCall); |
1394 continue; | 1396 continue; |
1395 } | 1397 } |
1396 case kExprGetGlobal: { | 1398 case kExprGetGlobal: { |
1397 GlobalIndexOperand operand(&decoder, code->at(pc)); | 1399 GlobalIndexOperand operand(&decoder, code->at(pc)); |
1398 const WasmGlobal* global = &module()->globals[operand.index]; | 1400 const WasmGlobal* global = &module()->globals[operand.index]; |
1399 byte* ptr = instance()->globals_start + global->offset; | 1401 byte* ptr = instance()->globals_start + global->offset; |
1400 ValueType type = global->type; | 1402 ValueType type = global->type; |
1401 WasmVal val; | 1403 WasmVal val; |
1402 if (type == kWasmI32) { | 1404 if (type == kWasmI32) { |
1403 val = WasmVal(*reinterpret_cast<int32_t*>(ptr)); | 1405 val = WasmVal(*reinterpret_cast<int32_t*>(ptr)); |
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1629 #undef EXECUTE_OTHER_UNOP_NAN | 1631 #undef EXECUTE_OTHER_UNOP_NAN |
1630 | 1632 |
1631 default: | 1633 default: |
1632 V8_Fatal(__FILE__, __LINE__, "Unknown or unimplemented opcode #%d:%s", | 1634 V8_Fatal(__FILE__, __LINE__, "Unknown or unimplemented opcode #%d:%s", |
1633 code->start[pc], OpcodeName(code->start[pc])); | 1635 code->start[pc], OpcodeName(code->start[pc])); |
1634 UNREACHABLE(); | 1636 UNREACHABLE(); |
1635 } | 1637 } |
1636 | 1638 |
1637 pc += len; | 1639 pc += len; |
1638 } | 1640 } |
1639 UNREACHABLE(); // above decoding loop should run forever. | 1641 state_ = WasmInterpreter::PAUSED; |
| 1642 CommitPc(pc); |
1640 } | 1643 } |
1641 | 1644 |
1642 WasmVal Pop() { | 1645 WasmVal Pop() { |
1643 DCHECK_GT(stack_.size(), 0); | 1646 DCHECK_GT(stack_.size(), 0); |
1644 DCHECK_GT(frames_.size(), 0); | 1647 DCHECK_GT(frames_.size(), 0); |
1645 DCHECK_GT(stack_.size(), frames_.back().llimit()); // can't pop into locals | 1648 DCHECK_GT(stack_.size(), frames_.back().llimit()); // can't pop into locals |
1646 WasmVal val = stack_.back(); | 1649 WasmVal val = stack_.back(); |
1647 stack_.pop_back(); | 1650 stack_.pop_back(); |
1648 return val; | 1651 return val; |
1649 } | 1652 } |
(...skipping 19 matching lines...) Expand all Loading... |
1669 | 1672 |
1670 void TraceStack(const char* phase, pc_t pc) { | 1673 void TraceStack(const char* phase, pc_t pc) { |
1671 if (FLAG_trace_wasm_interpreter) { | 1674 if (FLAG_trace_wasm_interpreter) { |
1672 PrintF("%s @%zu", phase, pc); | 1675 PrintF("%s @%zu", phase, pc); |
1673 UNIMPLEMENTED(); | 1676 UNIMPLEMENTED(); |
1674 PrintF("\n"); | 1677 PrintF("\n"); |
1675 } | 1678 } |
1676 } | 1679 } |
1677 | 1680 |
1678 void TraceValueStack() { | 1681 void TraceValueStack() { |
| 1682 #ifdef DEBUG |
1679 Frame* top = frames_.size() > 0 ? &frames_.back() : nullptr; | 1683 Frame* top = frames_.size() > 0 ? &frames_.back() : nullptr; |
1680 sp_t sp = top ? top->sp : 0; | 1684 sp_t sp = top ? top->sp : 0; |
1681 sp_t plimit = top ? top->plimit() : 0; | 1685 sp_t plimit = top ? top->plimit() : 0; |
1682 sp_t llimit = top ? top->llimit() : 0; | 1686 sp_t llimit = top ? top->llimit() : 0; |
1683 if (FLAG_trace_wasm_interpreter) { | 1687 if (FLAG_trace_wasm_interpreter) { |
1684 for (size_t i = sp; i < stack_.size(); ++i) { | 1688 for (size_t i = sp; i < stack_.size(); ++i) { |
1685 if (i < plimit) | 1689 if (i < plimit) |
1686 PrintF(" p%zu:", i); | 1690 PrintF(" p%zu:", i); |
1687 else if (i < llimit) | 1691 else if (i < llimit) |
1688 PrintF(" l%zu:", i); | 1692 PrintF(" l%zu:", i); |
(...skipping 15 matching lines...) Expand all Loading... |
1704 break; | 1708 break; |
1705 case kWasmStmt: | 1709 case kWasmStmt: |
1706 PrintF("void"); | 1710 PrintF("void"); |
1707 break; | 1711 break; |
1708 default: | 1712 default: |
1709 UNREACHABLE(); | 1713 UNREACHABLE(); |
1710 break; | 1714 break; |
1711 } | 1715 } |
1712 } | 1716 } |
1713 } | 1717 } |
| 1718 #endif // DEBUG |
1714 } | 1719 } |
1715 }; | 1720 }; |
1716 | 1721 |
1717 // Converters between WasmInterpreter::Thread and WasmInterpreter::ThreadImpl. | 1722 // Converters between WasmInterpreter::Thread and WasmInterpreter::ThreadImpl. |
1718 // Thread* is the public interface, without knowledge of the object layout. | 1723 // Thread* is the public interface, without knowledge of the object layout. |
1719 // This cast is potentially risky, but as long as we always cast it back before | 1724 // This cast is potentially risky, but as long as we always cast it back before |
1720 // accessing any data, it should be fine. UBSan is not complaining. | 1725 // accessing any data, it should be fine. UBSan is not complaining. |
1721 WasmInterpreter::Thread* ToThread(ThreadImpl* impl) { | 1726 WasmInterpreter::Thread* ToThread(ThreadImpl* impl) { |
1722 return reinterpret_cast<WasmInterpreter::Thread*>(impl); | 1727 return reinterpret_cast<WasmInterpreter::Thread*>(impl); |
1723 } | 1728 } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1763 return InterpretedFrame(function, pc, fp, sp); | 1768 return InterpretedFrame(function, pc, fp, sp); |
1764 }; | 1769 }; |
1765 return ToImpl(this)->GetMutableFrame(index, frame_cons); | 1770 return ToImpl(this)->GetMutableFrame(index, frame_cons); |
1766 } | 1771 } |
1767 WasmVal WasmInterpreter::Thread::GetReturnValue(int index) { | 1772 WasmVal WasmInterpreter::Thread::GetReturnValue(int index) { |
1768 return ToImpl(this)->GetReturnValue(index); | 1773 return ToImpl(this)->GetReturnValue(index); |
1769 } | 1774 } |
1770 bool WasmInterpreter::Thread::PossibleNondeterminism() { | 1775 bool WasmInterpreter::Thread::PossibleNondeterminism() { |
1771 return ToImpl(this)->PossibleNondeterminism(); | 1776 return ToImpl(this)->PossibleNondeterminism(); |
1772 } | 1777 } |
| 1778 void WasmInterpreter::Thread::AddBreakFlags(uint8_t flags) { |
| 1779 ToImpl(this)->AddBreakFlags(flags); |
| 1780 } |
| 1781 void WasmInterpreter::Thread::ClearBreakFlags() { |
| 1782 ToImpl(this)->ClearBreakFlags(); |
| 1783 } |
1773 | 1784 |
1774 //============================================================================ | 1785 //============================================================================ |
1775 // The implementation details of the interpreter. | 1786 // The implementation details of the interpreter. |
1776 //============================================================================ | 1787 //============================================================================ |
1777 class WasmInterpreterInternals : public ZoneObject { | 1788 class WasmInterpreterInternals : public ZoneObject { |
1778 public: | 1789 public: |
1779 WasmInstance* instance_; | 1790 WasmInstance* instance_; |
1780 // Create a copy of the module bytes for the interpreter, since the passed | 1791 // Create a copy of the module bytes for the interpreter, since the passed |
1781 // pointer might be invalidated after constructing the interpreter. | 1792 // pointer might be invalidated after constructing the interpreter. |
1782 const ZoneVector<uint8_t> module_bytes_; | 1793 const ZoneVector<uint8_t> module_bytes_; |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1910 return none; | 1921 return none; |
1911 } | 1922 } |
1912 | 1923 |
1913 void InterpretedFrame::SetLocalVal(int index, WasmVal val) { UNIMPLEMENTED(); } | 1924 void InterpretedFrame::SetLocalVal(int index, WasmVal val) { UNIMPLEMENTED(); } |
1914 | 1925 |
1915 void InterpretedFrame::SetExprVal(int pc, WasmVal val) { UNIMPLEMENTED(); } | 1926 void InterpretedFrame::SetExprVal(int pc, WasmVal val) { UNIMPLEMENTED(); } |
1916 | 1927 |
1917 } // namespace wasm | 1928 } // namespace wasm |
1918 } // namespace internal | 1929 } // namespace internal |
1919 } // namespace v8 | 1930 } // namespace v8 |
OLD | NEW |