OLD | NEW |
---|---|
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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/api-natives.h" | 5 #include "src/api-natives.h" |
6 #include "src/api.h" | 6 #include "src/api.h" |
7 #include "src/assert-scope.h" | 7 #include "src/assert-scope.h" |
8 #include "src/ast/ast.h" | 8 #include "src/ast/ast.h" |
9 #include "src/ast/scopes.h" | 9 #include "src/ast/scopes.h" |
10 #include "src/execution.h" | 10 #include "src/execution.h" |
(...skipping 17 matching lines...) Expand all Loading... | |
28 | 28 |
29 namespace v8 { | 29 namespace v8 { |
30 | 30 |
31 namespace { | 31 namespace { |
32 struct RawBuffer { | 32 struct RawBuffer { |
33 const byte* start; | 33 const byte* start; |
34 const byte* end; | 34 const byte* end; |
35 size_t size() { return static_cast<size_t>(end - start); } | 35 size_t size() { return static_cast<size_t>(end - start); } |
36 }; | 36 }; |
37 | 37 |
38 RawBuffer GetRawBufferSource( | 38 RawBuffer GetRawBufferSource(v8::Local<v8::Value> source, |
39 v8::Local<v8::Value> source, ErrorThrower* thrower) { | 39 ErrorThrower* thrower) { |
40 const byte* start = nullptr; | 40 const byte* start = nullptr; |
41 const byte* end = nullptr; | 41 const byte* end = nullptr; |
42 | 42 |
43 if (source->IsArrayBuffer()) { | 43 if (source->IsArrayBuffer()) { |
44 // A raw array buffer was passed. | 44 // A raw array buffer was passed. |
45 Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(source); | 45 Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(source); |
46 ArrayBuffer::Contents contents = buffer->GetContents(); | 46 ArrayBuffer::Contents contents = buffer->GetContents(); |
47 | 47 |
48 start = reinterpret_cast<const byte*>(contents.Data()); | 48 start = reinterpret_cast<const byte*>(contents.Data()); |
49 end = start + contents.ByteLength(); | 49 end = start + contents.ByteLength(); |
50 | 50 |
51 if (start == nullptr || end == start) { | 51 if (start == nullptr || end == start) { |
52 thrower->Error("ArrayBuffer argument is empty"); | 52 thrower->Error("ArrayBuffer argument is empty"); |
53 } | 53 } |
54 } else if (source->IsTypedArray()) { | 54 } else if (source->IsTypedArray()) { |
55 // A TypedArray was passed. | 55 // A TypedArray was passed. |
56 Local<TypedArray> array = Local<TypedArray>::Cast(source); | 56 Local<TypedArray> array = Local<TypedArray>::Cast(source); |
57 Local<ArrayBuffer> buffer = array->Buffer(); | 57 Local<ArrayBuffer> buffer = array->Buffer(); |
58 | 58 |
59 ArrayBuffer::Contents contents = buffer->GetContents(); | 59 ArrayBuffer::Contents contents = buffer->GetContents(); |
60 | 60 |
61 start = | 61 start = |
62 reinterpret_cast<const byte*>(contents.Data()) + array->ByteOffset(); | 62 reinterpret_cast<const byte*>(contents.Data()) + array->ByteOffset(); |
63 end = start + array->ByteLength(); | 63 end = start + array->ByteLength(); |
64 | 64 |
65 if (start == nullptr || end == start) { | 65 if (start == nullptr || end == start) { |
66 thrower->Error("ArrayBuffer argument is empty"); | 66 thrower->Error("ArrayBuffer argument is empty"); |
67 } | 67 } |
68 } else { | 68 } else { |
69 thrower->Error("Argument 0 must be an ArrayBuffer or Uint8Array"); | 69 thrower->Error("Source must be an ArrayBuffer or Uint8Array"); |
Mircea Trofin
2016/06/30 23:23:29
Super-nit: would the caller (js programmer, I assu
bradn
2016/07/01 01:06:08
Reworded.
| |
70 } | 70 } |
71 | 71 |
72 return {start, end}; | 72 return {start, end}; |
73 } | 73 } |
74 | 74 |
75 i::Handle<i::JSArrayBuffer> GetMemoryArgument( | |
76 const v8::FunctionCallbackInfo<v8::Value>& args, int index) { | |
77 i::Handle<i::JSArrayBuffer> memory = i::Handle<i::JSArrayBuffer>::null(); | |
78 if (args.Length() > index && args[index]->IsArrayBuffer()) { | |
79 Local<Object> obj = Local<Object>::Cast(args[index]); | |
80 i::Handle<i::Object> mem_obj = v8::Utils::OpenHandle(*obj); | |
81 memory = i::Handle<i::JSArrayBuffer>(i::JSArrayBuffer::cast(*mem_obj)); | |
82 } | |
83 return memory; | |
84 } | |
85 | |
86 i::Handle<i::JSObject> GetForeignArgument( | |
87 const v8::FunctionCallbackInfo<v8::Value>& args, int index) { | |
88 i::Handle<i::JSObject> foreign; | |
89 if (args.Length() > index && args[index]->IsObject()) { | |
90 Local<Object> local_foreign = Local<Object>::Cast(args[index]); | |
91 i::Handle<i::Object> foreign_obj = v8::Utils::OpenHandle(*local_foreign); | |
92 foreign = i::Handle<i::JSObject>(i::JSObject::cast(*foreign_obj)); | |
93 } | |
94 return foreign; | |
95 } | |
96 | |
75 void VerifyModule(const v8::FunctionCallbackInfo<v8::Value>& args) { | 97 void VerifyModule(const v8::FunctionCallbackInfo<v8::Value>& args) { |
76 HandleScope scope(args.GetIsolate()); | 98 HandleScope scope(args.GetIsolate()); |
77 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); | 99 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); |
78 ErrorThrower thrower(isolate, "Wasm.verifyModule()"); | 100 ErrorThrower thrower(isolate, "Wasm.verifyModule()"); |
79 | 101 |
80 if (args.Length() < 1) { | 102 if (args.Length() < 1) { |
81 thrower.Error("Argument 0 must be a buffer source"); | 103 thrower.Error("Argument 0 must be a buffer source"); |
82 return; | 104 return; |
83 } | 105 } |
84 RawBuffer buffer = GetRawBufferSource(args[0], &thrower); | 106 RawBuffer buffer = GetRawBufferSource(args[0], &thrower); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
117 buffer.start, buffer.end); | 139 buffer.start, buffer.end); |
118 } | 140 } |
119 | 141 |
120 if (result.failed()) { | 142 if (result.failed()) { |
121 thrower.Failed("", result); | 143 thrower.Failed("", result); |
122 } | 144 } |
123 | 145 |
124 if (result.val) delete result.val; | 146 if (result.val) delete result.val; |
125 } | 147 } |
126 | 148 |
127 v8::internal::wasm::ZoneBuffer* TranslateAsmModule( | 149 static bool ParseAsmModule(i::ParseInfo* info, ErrorThrower* thrower) { |
128 i::ParseInfo* info, ErrorThrower* thrower, | |
129 i::Handle<i::FixedArray>* foreign_args) { | |
130 info->set_global(); | 150 info->set_global(); |
131 info->set_lazy(false); | 151 info->set_lazy(false); |
132 info->set_allow_lazy_parsing(false); | 152 info->set_allow_lazy_parsing(false); |
133 info->set_toplevel(true); | 153 info->set_toplevel(true); |
134 | 154 |
135 if (!i::Compiler::ParseAndAnalyze(info)) { | 155 if (!i::Compiler::ParseAndAnalyze(info)) { |
136 return nullptr; | 156 return false; |
137 } | 157 } |
138 | 158 |
139 if (info->scope()->declarations()->length() == 0) { | 159 if (info->scope()->declarations()->length() == 0) { |
140 thrower->Error("Asm.js validation failed: no declarations in scope"); | 160 thrower->Error("Asm.js validation failed: no declarations in scope"); |
141 return nullptr; | 161 return false; |
142 } | 162 } |
143 | 163 |
144 if (!info->scope()->declarations()->at(0)->IsFunctionDeclaration()) { | 164 if (!info->scope()->declarations()->at(0)->IsFunctionDeclaration()) { |
145 thrower->Error("Asm.js validation failed: non-function declaration"); | 165 thrower->Error("Asm.js validation failed: non-function declaration"); |
146 return nullptr; | 166 return false; |
147 } | 167 } |
148 | 168 |
149 info->set_literal( | 169 info->set_literal( |
150 info->scope()->declarations()->at(0)->AsFunctionDeclaration()->fun()); | 170 info->scope()->declarations()->at(0)->AsFunctionDeclaration()->fun()); |
151 | 171 return true; |
152 v8::internal::AsmTyper typer(info->isolate(), info->zone(), *(info->script()), | |
153 info->literal()); | |
154 if (i::FLAG_enable_simd_asmjs) { | |
155 typer.set_allow_simd(true); | |
156 } | |
157 if (!typer.Validate()) { | |
158 thrower->Error("Asm.js validation failed: %s", typer.error_message()); | |
159 return nullptr; | |
160 } | |
161 | |
162 v8::internal::wasm::AsmWasmBuilder builder(info->isolate(), info->zone(), | |
163 info->literal(), &typer); | |
164 | |
165 return builder.Run(foreign_args); | |
166 } | 172 } |
167 | 173 |
168 i::MaybeHandle<i::JSObject> InstantiateModuleCommon( | 174 i::MaybeHandle<i::FixedArray> CompileModuleCommon( |
169 const v8::FunctionCallbackInfo<v8::Value>& args, const byte* start, | 175 i::Isolate* isolate, const byte* start, const byte* end, |
170 const byte* end, ErrorThrower* thrower, | 176 ErrorThrower* thrower, |
171 internal::wasm::ModuleOrigin origin = i::wasm::kWasmOrigin) { | 177 internal::wasm::ModuleOrigin origin = i::wasm::kWasmOrigin) { |
172 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); | |
173 | |
174 // Decode but avoid a redundant pass over function bodies for verification. | 178 // Decode but avoid a redundant pass over function bodies for verification. |
175 // Verification will happen during compilation. | 179 // Verification will happen during compilation. |
176 i::Zone zone(isolate->allocator()); | 180 i::Zone zone(isolate->allocator()); |
177 internal::wasm::ModuleResult result = internal::wasm::DecodeWasmModule( | 181 internal::wasm::ModuleResult result = internal::wasm::DecodeWasmModule( |
178 isolate, &zone, start, end, false, origin); | 182 isolate, &zone, start, end, false, origin); |
179 | 183 |
180 i::MaybeHandle<i::JSObject> object; | 184 i::MaybeHandle<i::FixedArray> compiled_module; |
181 if (result.failed() && origin == internal::wasm::kAsmJsOrigin) { | 185 if (result.failed() && origin == internal::wasm::kAsmJsOrigin) { |
182 thrower->Error("Asm.js converted module failed to decode"); | 186 thrower->Error("Asm.js converted module failed to decode"); |
183 } else if (result.failed()) { | 187 } else if (result.failed()) { |
184 thrower->Failed("", result); | 188 thrower->Failed("", result); |
185 } else { | 189 } else { |
186 // Success. Instantiate the module and return the object. | 190 compiled_module = result.val->CompileFunctions(isolate); |
187 i::Handle<i::JSReceiver> ffi = i::Handle<i::JSObject>::null(); | |
188 if (args.Length() > 1 && args[1]->IsObject()) { | |
189 Local<Object> obj = Local<Object>::Cast(args[1]); | |
190 ffi = i::Handle<i::JSReceiver>::cast(v8::Utils::OpenHandle(*obj)); | |
191 } | |
192 | |
193 i::Handle<i::JSArrayBuffer> memory = i::Handle<i::JSArrayBuffer>::null(); | |
194 if (args.Length() > 2 && args[2]->IsArrayBuffer()) { | |
195 Local<Object> obj = Local<Object>::Cast(args[2]); | |
196 i::Handle<i::Object> mem_obj = v8::Utils::OpenHandle(*obj); | |
197 memory = i::Handle<i::JSArrayBuffer>(i::JSArrayBuffer::cast(*mem_obj)); | |
198 } | |
199 | |
200 i::MaybeHandle<i::FixedArray> compiled_module = | |
201 result.val->CompileFunctions(isolate); | |
202 if (!compiled_module.is_null()) { | |
203 object = i::wasm::WasmModule::Instantiate( | |
204 isolate, compiled_module.ToHandleChecked(), ffi, memory); | |
205 if (!object.is_null()) { | |
206 args.GetReturnValue().Set(v8::Utils::ToLocal(object.ToHandleChecked())); | |
207 } | |
208 } | |
209 } | 191 } |
210 | 192 |
211 if (result.val) delete result.val; | 193 if (result.val) delete result.val; |
212 return object; | 194 return compiled_module; |
213 } | 195 } |
214 | 196 |
215 void InstantiateModuleFromAsm(const v8::FunctionCallbackInfo<v8::Value>& args) { | 197 void InstantiateModuleFromAsm(const v8::FunctionCallbackInfo<v8::Value>& args) { |
216 HandleScope scope(args.GetIsolate()); | 198 HandleScope scope(args.GetIsolate()); |
217 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); | 199 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); |
218 ErrorThrower thrower(isolate, "Wasm.instantiateModuleFromAsm()"); | 200 ErrorThrower thrower(isolate, "Wasm.instantiateModuleFromAsm()"); |
219 | 201 |
220 if (!args[0]->IsString()) { | 202 if (!args[0]->IsString()) { |
221 thrower.Error("Asm module text should be a string"); | 203 thrower.Error("Asm module text should be a string"); |
222 return; | 204 return; |
223 } | 205 } |
224 | 206 |
225 i::Factory* factory = isolate->factory(); | 207 i::Factory* factory = isolate->factory(); |
226 i::Zone zone(isolate->allocator()); | 208 i::Zone zone(isolate->allocator()); |
227 Local<String> source = Local<String>::Cast(args[0]); | 209 Local<String> source = Local<String>::Cast(args[0]); |
228 i::Handle<i::Script> script = factory->NewScript(Utils::OpenHandle(*source)); | 210 i::Handle<i::Script> script = factory->NewScript(Utils::OpenHandle(*source)); |
229 i::ParseInfo info(&zone, script); | 211 i::ParseInfo info(&zone, script); |
230 | 212 |
231 i::Handle<i::Object> foreign; | 213 if (!ParseAsmModule(&info, &thrower)) { |
232 if (args.Length() > 1 && args[1]->IsObject()) { | |
233 Local<Object> local_foreign = Local<Object>::Cast(args[1]); | |
234 foreign = v8::Utils::OpenHandle(*local_foreign); | |
235 } | |
236 | |
237 i::Handle<i::FixedArray> foreign_args; | |
238 auto module = TranslateAsmModule(&info, &thrower, &foreign_args); | |
239 if (module == nullptr) { | |
240 return; | 214 return; |
241 } | 215 } |
242 | 216 |
243 i::MaybeHandle<i::Object> maybe_module_object = | 217 i::Handle<i::FixedArray> wasm_data; |
244 InstantiateModuleCommon(args, module->begin(), module->end(), &thrower, | 218 if (!i::WasmJs::ConvertAsmToWasm(&info, false, &wasm_data)) { |
245 internal::wasm::kAsmJsOrigin); | 219 thrower.Error("Asm.js failed to validate"); |
246 if (maybe_module_object.is_null()) { | |
247 return; | 220 return; |
248 } | 221 } |
249 | 222 |
250 i::Handle<i::Name> name = | 223 i::Handle<i::JSObject> foreign = GetForeignArgument(args, 1); |
251 factory->NewStringFromStaticChars("__foreign_init__"); | 224 i::Handle<i::JSArrayBuffer> memory = GetMemoryArgument(args, 2); |
252 | 225 |
253 i::Handle<i::Object> module_object = maybe_module_object.ToHandleChecked(); | 226 i::Handle<i::Object> result; |
254 i::MaybeHandle<i::Object> maybe_init = | 227 if (!i::WasmJs::InstantiateAsmWasm(isolate, wasm_data, memory, foreign, |
255 i::Object::GetProperty(module_object, name); | 228 &result)) { |
256 DCHECK(!maybe_init.is_null()); | 229 return; |
230 } | |
257 | 231 |
258 i::Handle<i::Object> init = maybe_init.ToHandleChecked(); | 232 if (!result.is_null()) { |
259 i::Handle<i::Object> undefined = isolate->factory()->undefined_value(); | 233 args.GetReturnValue().Set(v8::Utils::ToLocal(result)); |
260 i::Handle<i::Object>* foreign_args_array = | |
261 new i::Handle<i::Object>[foreign_args->length()]; | |
262 for (int j = 0; j < foreign_args->length(); j++) { | |
263 if (!foreign.is_null()) { | |
264 i::MaybeHandle<i::Name> name = i::Object::ToName( | |
265 isolate, i::Handle<i::Object>(foreign_args->get(j), isolate)); | |
266 if (!name.is_null()) { | |
267 i::MaybeHandle<i::Object> val = | |
268 i::Object::GetProperty(foreign, name.ToHandleChecked()); | |
269 if (!val.is_null()) { | |
270 foreign_args_array[j] = val.ToHandleChecked(); | |
271 continue; | |
272 } | |
273 } | |
274 } | |
275 foreign_args_array[j] = undefined; | |
276 } | |
277 i::MaybeHandle<i::Object> retval = i::Execution::Call( | |
278 isolate, init, undefined, foreign_args->length(), foreign_args_array); | |
279 delete[] foreign_args_array; | |
280 | |
281 if (retval.is_null()) { | |
282 thrower.Error( | |
283 "WASM.instantiateModuleFromAsm(): foreign init function failed"); | |
284 } | 234 } |
285 } | 235 } |
286 | 236 |
287 void InstantiateModule(const v8::FunctionCallbackInfo<v8::Value>& args) { | 237 void InstantiateModule(const v8::FunctionCallbackInfo<v8::Value>& args) { |
288 HandleScope scope(args.GetIsolate()); | 238 HandleScope scope(args.GetIsolate()); |
289 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); | 239 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); |
290 ErrorThrower thrower(isolate, "Wasm.instantiateModule()"); | 240 ErrorThrower thrower(isolate, "Wasm.instantiateModule()"); |
291 | 241 |
292 if (args.Length() < 1) { | 242 if (args.Length() < 1) { |
293 thrower.Error("Argument 0 must be a buffer source"); | 243 thrower.Error("Argument 0 must be a buffer source"); |
294 return; | 244 return; |
295 } | 245 } |
296 RawBuffer buffer = GetRawBufferSource(args[0], &thrower); | 246 RawBuffer buffer = GetRawBufferSource(args[0], &thrower); |
297 if (buffer.start == nullptr) return; | 247 if (buffer.start == nullptr) return; |
298 | 248 |
299 InstantiateModuleCommon(args, buffer.start, buffer.end, &thrower); | 249 i::Handle<i::JSObject> foreign = GetForeignArgument(args, 1); |
250 i::Handle<i::JSArrayBuffer> memory = GetMemoryArgument(args, 2); | |
251 | |
252 i::MaybeHandle<i::FixedArray> compiled = | |
253 CompileModuleCommon(isolate, buffer.start, buffer.end, &thrower); | |
254 if (compiled.is_null()) { | |
255 return; | |
256 } | |
257 i::MaybeHandle<i::JSObject> result = i::wasm::WasmModule::Instantiate( | |
258 isolate, compiled.ToHandleChecked(), foreign, memory); | |
259 | |
260 if (!result.is_null()) { | |
261 args.GetReturnValue().Set(v8::Utils::ToLocal(result.ToHandleChecked())); | |
262 } | |
300 } | 263 } |
301 | 264 |
302 | |
303 static i::MaybeHandle<i::JSObject> CreateModuleObject( | 265 static i::MaybeHandle<i::JSObject> CreateModuleObject( |
304 v8::Isolate* isolate, const v8::Local<v8::Value> source, | 266 v8::Isolate* isolate, const v8::Local<v8::Value> source, |
305 ErrorThrower* thrower) { | 267 ErrorThrower* thrower) { |
306 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 268 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
307 | 269 |
308 RawBuffer buffer = GetRawBufferSource(source, thrower); | 270 RawBuffer buffer = GetRawBufferSource(source, thrower); |
309 if (buffer.start == nullptr) return i::MaybeHandle<i::JSObject>(); | 271 if (buffer.start == nullptr) return i::MaybeHandle<i::JSObject>(); |
310 | 272 |
311 // TODO(rossberg): Once we can, do compilation here. | 273 // TODO(rossberg): Once we can, do compilation here. |
312 DCHECK(source->IsArrayBuffer() || source->IsTypedArray()); | 274 DCHECK(source->IsArrayBuffer() || source->IsTypedArray()); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
359 CreateModuleObject(isolate, args[0], &thrower); | 321 CreateModuleObject(isolate, args[0], &thrower); |
360 if (module_obj.is_null()) return; | 322 if (module_obj.is_null()) return; |
361 | 323 |
362 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); | 324 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); |
363 return_value.Set(Utils::ToLocal(module_obj.ToHandleChecked())); | 325 return_value.Set(Utils::ToLocal(module_obj.ToHandleChecked())); |
364 } | 326 } |
365 | 327 |
366 void WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) { | 328 void WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) { |
367 HandleScope scope(args.GetIsolate()); | 329 HandleScope scope(args.GetIsolate()); |
368 v8::Isolate* isolate = args.GetIsolate(); | 330 v8::Isolate* isolate = args.GetIsolate(); |
369 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), | 331 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
370 "WebAssembly.Instance()"); | 332 ErrorThrower thrower(i_isolate, "WebAssembly.Instance()"); |
371 | 333 |
372 if (args.Length() < 1) { | 334 if (args.Length() < 1) { |
373 thrower.Error("Argument 0 must be a WebAssembly.Module"); | 335 thrower.Error("Argument 0 must be a WebAssembly.Module"); |
374 return; | 336 return; |
375 } | 337 } |
376 Local<Context> context = isolate->GetCurrentContext(); | 338 Local<Context> context = isolate->GetCurrentContext(); |
377 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); | 339 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); |
378 i::Handle<i::Symbol> module_sym(i_context->wasm_module_sym()); | 340 i::Handle<i::Symbol> module_sym(i_context->wasm_module_sym()); |
379 i::MaybeHandle<i::Object> source = | 341 i::MaybeHandle<i::Object> source = |
380 i::Object::GetProperty(Utils::OpenHandle(*args[0]), module_sym); | 342 i::Object::GetProperty(Utils::OpenHandle(*args[0]), module_sym); |
381 if (source.is_null()) return; | 343 if (source.is_null()) return; |
382 | 344 |
383 RawBuffer buffer = | 345 RawBuffer buffer = |
384 GetRawBufferSource(Utils::ToLocal(source.ToHandleChecked()), &thrower); | 346 GetRawBufferSource(Utils::ToLocal(source.ToHandleChecked()), &thrower); |
385 if (buffer.start == nullptr) return; | 347 if (buffer.start == nullptr) return; |
386 | 348 |
387 InstantiateModuleCommon(args, buffer.start, buffer.end, &thrower); | 349 i::Handle<i::JSObject> foreign = GetForeignArgument(args, 1); |
350 i::Handle<i::JSArrayBuffer> memory = GetMemoryArgument(args, 2); | |
351 | |
352 i::MaybeHandle<i::FixedArray> compiled = | |
353 CompileModuleCommon(i_isolate, buffer.start, buffer.end, &thrower); | |
354 if (compiled.is_null()) { | |
355 return; | |
356 } | |
357 i::MaybeHandle<i::JSObject> result = i::wasm::WasmModule::Instantiate( | |
358 i_isolate, compiled.ToHandleChecked(), foreign, memory); | |
359 | |
360 if (!result.is_null()) { | |
361 args.GetReturnValue().Set(v8::Utils::ToLocal(result.ToHandleChecked())); | |
362 } | |
388 } | 363 } |
389 } // namespace | 364 } // namespace |
390 | 365 |
391 // TODO(titzer): we use the API to create the function template because the | 366 // TODO(titzer): we use the API to create the function template because the |
392 // internal guts are too ugly to replicate here. | 367 // internal guts are too ugly to replicate here. |
393 static i::Handle<i::FunctionTemplateInfo> NewTemplate(i::Isolate* i_isolate, | 368 static i::Handle<i::FunctionTemplateInfo> NewTemplate(i::Isolate* i_isolate, |
394 FunctionCallback func) { | 369 FunctionCallback func) { |
395 Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate); | 370 Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate); |
396 Local<FunctionTemplate> local = FunctionTemplate::New(isolate, func); | 371 Local<FunctionTemplate> local = FunctionTemplate::New(isolate, func); |
397 return v8::Utils::OpenHandle(*local); | 372 return v8::Utils::OpenHandle(*local); |
(...skipping 10 matching lines...) Expand all Loading... | |
408 Handle<FunctionTemplateInfo> temp = NewTemplate(isolate, func); | 383 Handle<FunctionTemplateInfo> temp = NewTemplate(isolate, func); |
409 Handle<JSFunction> function = | 384 Handle<JSFunction> function = |
410 ApiNatives::InstantiateFunction(temp).ToHandleChecked(); | 385 ApiNatives::InstantiateFunction(temp).ToHandleChecked(); |
411 PropertyAttributes attributes = | 386 PropertyAttributes attributes = |
412 static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY); | 387 static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY); |
413 JSObject::AddProperty(object, name, function, attributes); | 388 JSObject::AddProperty(object, name, function, attributes); |
414 return function; | 389 return function; |
415 } | 390 } |
416 | 391 |
417 void WasmJs::Install(Isolate* isolate, Handle<JSGlobalObject> global) { | 392 void WasmJs::Install(Isolate* isolate, Handle<JSGlobalObject> global) { |
393 if (!FLAG_expose_wasm && !FLAG_validate_asm) { | |
394 return; | |
395 } | |
titzer
2016/07/01 11:12:15
Why'd these flags go away? That accidentally shipp
Michael Starzinger
2016/07/01 11:41:27
+1. I also explicitly checked for these flags in m
bradn
2016/07/01 12:39:53
AAAH. Drat.
Sorry about that.
When I moved stuff o
| |
418 Factory* factory = isolate->factory(); | 396 Factory* factory = isolate->factory(); |
419 | 397 |
420 // Setup wasm function map. | 398 // Setup wasm function map. |
421 Handle<Context> context(global->native_context(), isolate); | 399 Handle<Context> context(global->native_context(), isolate); |
422 InstallWasmFunctionMap(isolate, context); | 400 InstallWasmFunctionMap(isolate, context); |
423 | 401 |
402 if (!FLAG_expose_wasm) { | |
403 return; | |
404 } | |
405 | |
424 // Bind the experimental WASM object. | 406 // Bind the experimental WASM object. |
425 // TODO(rossberg, titzer): remove once it's no longer needed. | 407 // TODO(rossberg, titzer): remove once it's no longer needed. |
426 { | 408 { |
427 Handle<String> name = v8_str(isolate, "Wasm"); | 409 Handle<String> name = v8_str(isolate, "Wasm"); |
428 Handle<JSFunction> cons = factory->NewFunction(name); | 410 Handle<JSFunction> cons = factory->NewFunction(name); |
429 JSFunction::SetInstancePrototype( | 411 JSFunction::SetInstancePrototype( |
430 cons, Handle<Object>(context->initial_object_prototype(), isolate)); | 412 cons, Handle<Object>(context->initial_object_prototype(), isolate)); |
431 cons->shared()->set_instance_class_name(*name); | 413 cons->shared()->set_instance_class_name(*name); |
432 Handle<JSObject> wasm_object = factory->NewJSObject(cons, TENURED); | 414 Handle<JSObject> wasm_object = factory->NewJSObject(cons, TENURED); |
433 PropertyAttributes attributes = static_cast<PropertyAttributes>(DONT_ENUM); | 415 PropertyAttributes attributes = static_cast<PropertyAttributes>(DONT_ENUM); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
495 &in_object_properties); | 477 &in_object_properties); |
496 | 478 |
497 int unused_property_fields = in_object_properties - pre_allocated; | 479 int unused_property_fields = in_object_properties - pre_allocated; |
498 Handle<Map> map = Map::CopyInitialMap( | 480 Handle<Map> map = Map::CopyInitialMap( |
499 prev_map, instance_size, in_object_properties, unused_property_fields); | 481 prev_map, instance_size, in_object_properties, unused_property_fields); |
500 | 482 |
501 context->set_wasm_function_map(*map); | 483 context->set_wasm_function_map(*map); |
502 } | 484 } |
503 } | 485 } |
504 | 486 |
487 bool WasmJs::ConvertAsmToWasm(ParseInfo* info, bool fixed_signature, | |
titzer
2016/06/30 09:56:03
The logic is basically OK here, but I think we sho
bradn
2016/07/01 01:06:09
Done.
| |
488 Handle<FixedArray>* wasm_data) { | |
489 ErrorThrower thrower(info->isolate(), "Asm.js -> WebAssembly conversion"); | |
490 AsmTyper typer(info->isolate(), info->zone(), *(info->script()), | |
491 info->literal()); | |
492 typer.set_fixed_signature(fixed_signature); | |
493 if (i::FLAG_enable_simd_asmjs) { | |
494 typer.set_allow_simd(true); | |
495 } | |
496 if (!typer.Validate()) { | |
497 DCHECK(!info->isolate()->has_pending_exception()); | |
498 PrintF("Validation of asm.js module failed: %s", typer.error_message()); | |
499 return false; | |
500 } | |
501 v8::internal::wasm::AsmWasmBuilder builder(info->isolate(), info->zone(), | |
502 info->literal(), &typer); | |
503 i::Handle<i::FixedArray> foreign_globals; | |
504 auto module = builder.Run(&foreign_globals); | |
505 size_t byte_length = module->end() - module->begin(); | |
506 Handle<JSArrayBuffer> buffer = info->isolate()->factory()->NewJSArrayBuffer(); | |
507 JSArrayBuffer::SetupAllocatingData(buffer, info->isolate(), byte_length, | |
508 false, SharedFlag::kNotShared); | |
509 uint8_t* module_bytes = reinterpret_cast<uint8_t*>(buffer->backing_store()); | |
510 memcpy(module_bytes, module->begin(), byte_length); | |
511 *wasm_data = info->isolate()->factory()->NewFixedArray(2); | |
512 (*wasm_data)->set(0, *buffer); | |
513 (*wasm_data)->set(1, *foreign_globals); | |
Mircea Trofin
2016/06/30 23:23:29
you could return MaybeHandle<FixedArray>, and then
bradn
2016/07/01 01:06:08
Done.
| |
514 return true; | |
515 } | |
516 | |
517 bool WasmJs::InstantiateAsmWasm(i::Isolate* isolate, | |
518 Handle<FixedArray> wasm_data, | |
519 Handle<JSArrayBuffer> memory, | |
520 Handle<JSObject> foreign, | |
521 Handle<Object>* result) { | |
522 i::Handle<i::JSArrayBuffer> module_bytes( | |
523 i::JSArrayBuffer::cast(wasm_data->get(0))); | |
524 i::Handle<i::FixedArray> foreign_globals( | |
525 i::FixedArray::cast(wasm_data->get(1))); | |
526 | |
527 ErrorThrower thrower(isolate, "Asm.js -> WebAssembly instantiation"); | |
528 i::Factory* factory = isolate->factory(); | |
529 | |
530 const byte* module_start = | |
531 reinterpret_cast<const byte*>(module_bytes->backing_store()); | |
532 size_t module_length = | |
533 static_cast<size_t>(module_bytes->byte_length()->Number()); | |
534 const byte* module_end = module_start + module_length; | |
535 i::MaybeHandle<i::FixedArray> compiled = | |
536 CompileModuleCommon(isolate, module_start, module_end, &thrower, | |
537 internal::wasm::kAsmJsOrigin); | |
538 if (compiled.is_null()) { | |
539 return false; | |
540 } | |
541 i::MaybeHandle<i::JSObject> maybe_module_object = | |
542 i::wasm::WasmModule::Instantiate(isolate, compiled.ToHandleChecked(), | |
543 foreign, memory); | |
544 if (maybe_module_object.is_null()) { | |
545 return false; | |
546 } | |
547 | |
548 i::Handle<i::Name> name = | |
549 factory->NewStringFromStaticChars("__foreign_init__"); | |
Mircea Trofin
2016/06/30 23:23:30
Should you use one of the Internalize APIs, e.g. I
bradn
2016/07/01 01:06:09
Done.
| |
550 | |
551 i::Handle<i::Object> module_object = maybe_module_object.ToHandleChecked(); | |
552 i::MaybeHandle<i::Object> maybe_init = | |
553 i::Object::GetProperty(module_object, name); | |
554 DCHECK(!maybe_init.is_null()); | |
555 | |
556 i::Handle<i::Object> init = maybe_init.ToHandleChecked(); | |
557 i::Handle<i::Object> undefined(isolate->heap()->undefined_value(), isolate); | |
558 i::Handle<i::Object>* foreign_args_array = | |
559 new i::Handle<i::Object>[foreign_globals->length()]; | |
560 for (int j = 0; j < foreign_globals->length(); j++) { | |
Mircea Trofin
2016/06/30 23:23:29
This is the asm.js initialization protocol? we cou
bradn
2016/07/01 01:06:08
Yes needs refactor.
| |
561 if (!foreign.is_null()) { | |
562 i::MaybeHandle<i::Name> name = i::Object::ToName( | |
563 isolate, i::Handle<i::Object>(foreign_globals->get(j), isolate)); | |
564 if (!name.is_null()) { | |
565 i::MaybeHandle<i::Object> val = | |
566 i::Object::GetProperty(foreign, name.ToHandleChecked()); | |
567 if (!val.is_null()) { | |
568 foreign_args_array[j] = val.ToHandleChecked(); | |
569 continue; | |
570 } | |
571 } | |
572 } | |
573 foreign_args_array[j] = undefined; | |
574 } | |
575 i::MaybeHandle<i::Object> retval = i::Execution::Call( | |
576 isolate, init, undefined, foreign_globals->length(), foreign_args_array); | |
577 delete[] foreign_args_array; | |
578 | |
579 if (retval.is_null()) { | |
580 thrower.Error( | |
581 "WASM.instantiateModuleFromAsm(): foreign init function failed"); | |
582 return false; | |
583 } else { | |
584 *result = maybe_module_object.ToHandleChecked(); | |
Mircea Trofin
2016/06/30 23:23:30
same comment as above, maybe return MaybeHandle<Ob
bradn
2016/07/01 01:06:08
Done.
| |
585 } | |
586 | |
587 return true; | |
588 } | |
589 | |
505 } // namespace internal | 590 } // namespace internal |
506 } // namespace v8 | 591 } // namespace v8 |
OLD | NEW |