Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(162)

Side by Side Diff: src/wasm/wasm-debug.cc

Issue 2625093004: [wasm] Instantiate the interpreter on demand (Closed)
Patch Set: Remove partilly dead variable Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/wasm/wasm-module.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/assembler-inl.h"
5 #include "src/assert-scope.h" 6 #include "src/assert-scope.h"
7 #include "src/compiler/wasm-compiler.h"
6 #include "src/debug/debug.h" 8 #include "src/debug/debug.h"
7 #include "src/factory.h" 9 #include "src/factory.h"
10 #include "src/frames-inl.h"
8 #include "src/isolate.h" 11 #include "src/isolate.h"
9 #include "src/wasm/module-decoder.h" 12 #include "src/wasm/module-decoder.h"
13 #include "src/wasm/wasm-interpreter.h"
10 #include "src/wasm/wasm-module.h" 14 #include "src/wasm/wasm-module.h"
11 #include "src/wasm/wasm-objects.h" 15 #include "src/wasm/wasm-objects.h"
16 #include "src/zone/accounting-allocator.h"
12 17
13 using namespace v8::internal; 18 using namespace v8::internal;
14 using namespace v8::internal::wasm; 19 using namespace v8::internal::wasm;
15 20
21 namespace {
22
23 class InterpreterHandle {
24 AccountingAllocator allocator_;
25 WasmInstance instance_;
26 WasmInterpreter interpreter_;
27
28 public:
29 // Initialize in the right order, using helper methods to make this possible.
30 // WasmInterpreter has to be allocated in place, since it is not movable.
31 InterpreterHandle(Isolate *isolate, WasmDebugInfo *debug_info)
32 : instance_(debug_info->wasm_instance()->compiled_module()->module()),
33 interpreter_(GetBytesEnv(&instance_, debug_info), &allocator_) {
34 Handle<JSArrayBuffer> mem_buffer =
35 handle(debug_info->wasm_instance()->memory_buffer(), isolate);
36 if (mem_buffer->IsUndefined(isolate)) {
37 DCHECK_EQ(0, instance_.module->min_mem_pages);
38 instance_.mem_start = nullptr;
39 instance_.mem_size = 0;
40 } else {
41 instance_.mem_start =
42 reinterpret_cast<byte *>(mem_buffer->backing_store());
43 CHECK(mem_buffer->byte_length()->ToUint32(&instance_.mem_size));
44 }
45 }
46
47 static ModuleBytesEnv GetBytesEnv(WasmInstance *instance,
48 WasmDebugInfo *debug_info) {
49 // Return raw pointer into heap. The WasmInterpreter will make its own copy
50 // of this data anyway, and there is no heap allocation in-between.
51 SeqOneByteString *bytes_str =
52 debug_info->wasm_instance()->compiled_module()->module_bytes();
53 Vector<const byte> bytes(bytes_str->GetChars(), bytes_str->length());
54 return ModuleBytesEnv(instance->module, instance, bytes);
55 }
56
57 WasmInterpreter *interpreter() { return &interpreter_; }
58 const WasmModule *module() { return instance_.module; }
59
60 void Execute(uint32_t func_index, uint8_t *arg_buffer) {
61 DCHECK_GE(module()->functions.size(), func_index);
62 FunctionSig *sig = module()->functions[func_index].sig;
63 DCHECK_GE(kMaxInt, sig->parameter_count());
64 int num_params = static_cast<int>(sig->parameter_count());
65 ScopedVector<WasmVal> wasm_args(num_params);
66 uint8_t *arg_buf_ptr = arg_buffer;
67 for (int i = 0; i < num_params; ++i) {
68 uint32_t param_size = 1 << ElementSizeLog2Of(sig->GetParam(i));
69 #define CASE_ARG_TYPE(type, ctype) \
70 case type: \
71 DCHECK_EQ(param_size, sizeof(ctype)); \
72 wasm_args[i] = WasmVal(*reinterpret_cast<ctype *>(arg_buf_ptr)); \
73 break;
74 switch (sig->GetParam(i)) {
75 CASE_ARG_TYPE(kWasmI32, uint32_t)
76 CASE_ARG_TYPE(kWasmI64, uint64_t)
77 CASE_ARG_TYPE(kWasmF32, float)
78 CASE_ARG_TYPE(kWasmF64, double)
79 #undef CASE_ARG_TYPE
80 default:
81 UNREACHABLE();
82 }
83 arg_buf_ptr += param_size;
84 }
85
86 WasmInterpreter::Thread *thread = interpreter_.GetThread(0);
87 // We do not support reentering an already running interpreter at the moment
88 // (like INTERPRETER -> JS -> WASM -> INTERPRETER).
89 DCHECK(thread->state() == WasmInterpreter::STOPPED ||
90 thread->state() == WasmInterpreter::FINISHED);
91 thread->Reset();
92 thread->PushFrame(&module()->functions[func_index], wasm_args.start());
93 WasmInterpreter::State state;
94 do {
95 state = thread->Run();
96 switch (state) {
97 case WasmInterpreter::State::PAUSED: {
98 // We hit a breakpoint.
99 // TODO(clemensh): Handle this.
100 } break;
101 case WasmInterpreter::State::FINISHED:
102 // Perfect, just break the switch and exit the loop.
103 break;
104 case WasmInterpreter::State::TRAPPED:
105 // TODO(clemensh): Generate appropriate JS exception.
106 UNIMPLEMENTED();
107 break;
108 // STOPPED and RUNNING should never occur here.
109 case WasmInterpreter::State::STOPPED:
110 case WasmInterpreter::State::RUNNING:
111 default:
112 UNREACHABLE();
113 }
114 } while (state != WasmInterpreter::State::FINISHED);
115
116 // Copy back the return value
117 DCHECK_GE(1, sig->return_count());
titzer 2017/01/12 15:32:05 I think you should check against kV8MaxWasmFunctio
Clemens Hammacher 2017/01/12 19:19:54 Done.
118 if (sig->return_count()) {
119 WasmVal ret_val = thread->GetReturnValue(0);
120 #define CASE_RET_TYPE(type, ctype) \
121 case type: \
122 DCHECK_EQ(1 << ElementSizeLog2Of(sig->GetReturn(0)), sizeof(ctype)); \
123 *reinterpret_cast<ctype *>(arg_buffer) = ret_val.to<ctype>(); \
124 break;
125 switch (sig->GetReturn(0)) {
126 CASE_RET_TYPE(kWasmI32, uint32_t)
127 CASE_RET_TYPE(kWasmI64, uint64_t)
128 CASE_RET_TYPE(kWasmF32, float)
129 CASE_RET_TYPE(kWasmF64, double)
130 #undef CASE_RET_TYPE
131 default:
132 UNREACHABLE();
133 }
134 }
135 }
136 };
137
138 InterpreterHandle *GetOrCreateInterpreterHandle(
139 Isolate *isolate, Handle<WasmDebugInfo> debug_info) {
140 Handle<Object> handle(debug_info->get(WasmDebugInfo::kInterpreterHandle),
141 isolate);
142 if (handle->IsUndefined(isolate)) {
143 InterpreterHandle *cpp_handle = new InterpreterHandle(isolate, *debug_info);
144 handle = Managed<InterpreterHandle>::New(isolate, cpp_handle);
145 debug_info->set(WasmDebugInfo::kInterpreterHandle, *handle);
146 }
147
148 return Handle<Managed<InterpreterHandle>>::cast(handle)->get();
149 }
150
151 int GetNumFunctions(WasmInstanceObject *instance) {
152 size_t num_functions =
153 instance->compiled_module()->module()->functions.size();
154 DCHECK_GE(kMaxInt, num_functions);
155 return static_cast<int>(num_functions);
156 }
157
158 Handle<FixedArray> GetOrCreateInterpretedFunctions(
159 Isolate *isolate, Handle<WasmDebugInfo> debug_info) {
160 Handle<Object> obj(debug_info->get(WasmDebugInfo::kInterpretedFunctions),
161 isolate);
162 if (!obj->IsUndefined(isolate)) return Handle<FixedArray>::cast(obj);
163
164 Handle<FixedArray> new_arr = isolate->factory()->NewFixedArray(
165 GetNumFunctions(debug_info->wasm_instance()));
166 debug_info->set(WasmDebugInfo::kInterpretedFunctions, *new_arr);
167 return new_arr;
168 }
169
170 void RedirectCallsitesInCode(Code *code, Code *old_target, Code *new_target) {
171 DisallowHeapAllocation no_gc;
172 for (RelocIterator it(code, RelocInfo::kCodeTargetMask); !it.done();
173 it.next()) {
174 DCHECK(RelocInfo::IsCodeTarget(it.rinfo()->rmode()));
175 Code *target = Code::GetCodeFromTargetAddress(it.rinfo()->target_address());
176 if (target != old_target) continue;
177 it.rinfo()->set_target_address(new_target->instruction_start());
178 }
179 }
180
181 void RedirectCallsitesInInstance(Isolate *isolate, WasmInstanceObject *instance,
182 Code *old_target, Code *new_target) {
183 DisallowHeapAllocation no_gc;
184 // Redirect in all wasm functions.
185 FixedArray *code_table = instance->compiled_module()->ptr_to_code_table();
186 for (int i = 0, e = GetNumFunctions(instance); i < e; ++i)
titzer 2017/01/12 15:32:05 Please add brackets.
Clemens Hammacher 2017/01/12 19:19:54 Done.
187 RedirectCallsitesInCode(Code::cast(code_table->get(i)), old_target,
188 new_target);
189
190 // Redirect in all exported functions.
titzer 2017/01/12 15:32:05 "Redirect all calls in exported functions"? and mo
Clemens Hammacher 2017/01/12 19:19:54 Done, and removed the DCHECK which does not really
191 DCHECK(!instance->compiled_module()->is_asm_js());
192
193 FixedArray *weak_exported_functions =
194 instance->compiled_module()->ptr_to_weak_exported_functions();
195 for (int i = 0, e = weak_exported_functions->length(); i != e; ++i) {
196 WeakCell *weak_function = WeakCell::cast(weak_exported_functions->get(i));
197 if (weak_function->cleared()) continue;
198 Code *code = JSFunction::cast(weak_function->value())->code();
199 RedirectCallsitesInCode(code, old_target, new_target);
200 }
201 }
202
203 void EnsureRedirectToInterpreter(Isolate *isolate,
204 Handle<WasmDebugInfo> debug_info,
205 int func_index) {
206 DCHECK_LE(0, func_index);
207 Handle<FixedArray> interpreted_functions =
208 GetOrCreateInterpretedFunctions(isolate, debug_info);
209 DCHECK_GT(interpreted_functions->length(), func_index);
titzer 2017/01/12 15:32:05 The FixedArray should do this bounds check for you
Clemens Hammacher 2017/01/12 19:19:54 Yeah, but it's only SLOW_DCHECK. I removed it for
210 if (!interpreted_functions->get(func_index)->IsUndefined(isolate)) return;
211
212 Handle<WasmInstanceObject> instance(debug_info->wasm_instance(), isolate);
213 Handle<Code> new_code = compiler::CompileWasmInterpreterEntry(
214 isolate, func_index,
215 instance->compiled_module()->module()->functions[func_index].sig,
216 instance);
217
218 Handle<FixedArray> code_table = instance->compiled_module()->code_table();
219 DCHECK_GT(code_table->length(), func_index);
titzer 2017/01/12 15:32:05 Same here. The FixedArray will bounds check for yo
Clemens Hammacher 2017/01/12 19:19:54 Done.
220 Handle<Code> old_code =
221 code_table->GetValueChecked<Code>(isolate, func_index);
222 interpreted_functions->set(func_index, *new_code);
223
224 RedirectCallsitesInInstance(isolate, *instance, *old_code, *new_code);
225 }
226
227 } // namespace
228
16 Handle<WasmDebugInfo> WasmDebugInfo::New(Handle<WasmInstanceObject> instance) { 229 Handle<WasmDebugInfo> WasmDebugInfo::New(Handle<WasmInstanceObject> instance) {
17 Isolate *isolate = instance->GetIsolate(); 230 Isolate *isolate = instance->GetIsolate();
18 Factory *factory = isolate->factory(); 231 Factory *factory = isolate->factory();
19 Handle<FixedArray> arr = factory->NewFixedArray(kFieldCount, TENURED); 232 Handle<FixedArray> arr = factory->NewFixedArray(kFieldCount, TENURED);
20 arr->set(kInstance, *instance); 233 arr->set(kInstance, *instance);
21
22 return Handle<WasmDebugInfo>::cast(arr); 234 return Handle<WasmDebugInfo>::cast(arr);
23 } 235 }
24 236
25 bool WasmDebugInfo::IsDebugInfo(Object *object) { 237 bool WasmDebugInfo::IsDebugInfo(Object *object) {
26 if (!object->IsFixedArray()) return false; 238 if (!object->IsFixedArray()) return false;
27 FixedArray *arr = FixedArray::cast(object); 239 FixedArray *arr = FixedArray::cast(object);
28 return arr->length() == kFieldCount && IsWasmInstance(arr->get(kInstance)); 240 if (arr->length() != kFieldCount) return false;
241 if (!IsWasmInstance(arr->get(kInstance))) return false;
242 Isolate *isolate = arr->GetIsolate();
243 if (!arr->get(kInterpreterHandle)->IsUndefined(isolate) &&
244 !arr->get(kInterpreterHandle)->IsForeign())
245 return false;
246 return true;
29 } 247 }
30 248
31 WasmDebugInfo *WasmDebugInfo::cast(Object *object) { 249 WasmDebugInfo *WasmDebugInfo::cast(Object *object) {
32 DCHECK(IsDebugInfo(object)); 250 DCHECK(IsDebugInfo(object));
33 return reinterpret_cast<WasmDebugInfo *>(object); 251 return reinterpret_cast<WasmDebugInfo *>(object);
34 } 252 }
35 253
36 WasmInstanceObject *WasmDebugInfo::wasm_instance() { 254 WasmInstanceObject *WasmDebugInfo::wasm_instance() {
37 return WasmInstanceObject::cast(get(kInstance)); 255 return WasmInstanceObject::cast(get(kInstance));
38 } 256 }
39 257
258 void WasmDebugInfo::SetBreakpoint(Handle<WasmDebugInfo> debug_info,
259 int func_index, int offset) {
260 Isolate *isolate = debug_info->GetIsolate();
261 InterpreterHandle *handle = GetOrCreateInterpreterHandle(isolate, debug_info);
262 WasmInterpreter *interpreter = handle->interpreter();
263 DCHECK_LE(0, func_index);
264 DCHECK_GT(handle->module()->functions.size(), func_index);
265 const WasmFunction *func = &handle->module()->functions[func_index];
266 interpreter->SetBreakpoint(func, offset, true);
267 EnsureRedirectToInterpreter(isolate, debug_info, func_index);
268 }
269
40 void WasmDebugInfo::RunInterpreter(Handle<WasmDebugInfo> debug_info, 270 void WasmDebugInfo::RunInterpreter(Handle<WasmDebugInfo> debug_info,
41 int func_index, uint8_t *arg_buffer) { 271 int func_index, uint8_t *arg_buffer) {
42 // TODO(clemensh): Implement this. 272 DCHECK_LE(0, func_index);
43 UNIMPLEMENTED(); 273 InterpreterHandle *interp_handle =
274 GetOrCreateInterpreterHandle(debug_info->GetIsolate(), debug_info);
275 interp_handle->Execute(static_cast<uint32_t>(func_index), arg_buffer);
44 } 276 }
OLDNEW
« no previous file with comments | « no previous file | src/wasm/wasm-module.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698