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.h" | 5 #include "src/api.h" |
6 #include "src/api-natives.h" | 6 #include "src/api-natives.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/factory.h" | 10 #include "src/factory.h" |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
119 } else { | 119 } else { |
120 // Success. Compile and run! | 120 // Success. Compile and run! |
121 int32_t retval = i::wasm::CompileAndRunWasmModule(isolate, result.val); | 121 int32_t retval = i::wasm::CompileAndRunWasmModule(isolate, result.val); |
122 args.GetReturnValue().Set(retval); | 122 args.GetReturnValue().Set(retval); |
123 } | 123 } |
124 | 124 |
125 if (result.val) delete result.val; | 125 if (result.val) delete result.val; |
126 } | 126 } |
127 | 127 |
128 | 128 |
129 v8::internal::wasm::WasmModuleIndex* TranslateAsmModule(i::ParseInfo* info) { | 129 v8::internal::wasm::WasmModuleIndex* TranslateAsmModule(i::ParseInfo* info, |
| 130 ErrorThrower* thrower) { |
130 info->set_global(); | 131 info->set_global(); |
131 info->set_lazy(false); | 132 info->set_lazy(false); |
132 info->set_allow_lazy_parsing(false); | 133 info->set_allow_lazy_parsing(false); |
133 info->set_toplevel(true); | 134 info->set_toplevel(true); |
134 | 135 |
135 if (!i::Compiler::ParseAndAnalyze(info)) { | 136 if (!i::Compiler::ParseAndAnalyze(info)) { |
136 return nullptr; | 137 return nullptr; |
137 } | 138 } |
138 | 139 |
139 info->set_literal( | 140 info->set_literal( |
140 info->scope()->declarations()->at(0)->AsFunctionDeclaration()->fun()); | 141 info->scope()->declarations()->at(0)->AsFunctionDeclaration()->fun()); |
141 | 142 |
142 v8::internal::AsmTyper typer(info->isolate(), info->zone(), *(info->script()), | 143 v8::internal::AsmTyper typer(info->isolate(), info->zone(), *(info->script()), |
143 info->literal()); | 144 info->literal()); |
144 if (!typer.Validate()) { | 145 if (!typer.Validate()) { |
| 146 thrower->Error("Asm.js validation failed: %s", typer.error_message()); |
145 return nullptr; | 147 return nullptr; |
146 } | 148 } |
147 | 149 |
148 auto module = v8::internal::wasm::AsmWasmBuilder( | 150 auto module = v8::internal::wasm::AsmWasmBuilder( |
149 info->isolate(), info->zone(), info->literal()) | 151 info->isolate(), info->zone(), info->literal()) |
150 .Run(); | 152 .Run(); |
151 return module; | 153 return module; |
152 } | 154 } |
153 | 155 |
154 | 156 |
155 void AsmCompileRun(const v8::FunctionCallbackInfo<v8::Value>& args) { | 157 void AsmCompileRun(const v8::FunctionCallbackInfo<v8::Value>& args) { |
156 HandleScope scope(args.GetIsolate()); | 158 HandleScope scope(args.GetIsolate()); |
157 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); | 159 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); |
158 ErrorThrower thrower(isolate, "WASM.asmCompileRun()"); | 160 ErrorThrower thrower(isolate, "WASM.asmCompileRun()"); |
159 | 161 |
160 if (args.Length() != 1) { | 162 if (args.Length() != 1) { |
161 thrower.Error("Invalid argument count"); | 163 thrower.Error("Invalid argument count"); |
162 return; | 164 return; |
163 } | 165 } |
164 if (!args[0]->IsString()) { | 166 if (!args[0]->IsString()) { |
165 thrower.Error("Invalid argument count"); | 167 thrower.Error("Asm module text should be a string"); |
166 return; | 168 return; |
167 } | 169 } |
168 | 170 |
169 i::Factory* factory = isolate->factory(); | 171 i::Factory* factory = isolate->factory(); |
170 i::Zone zone; | 172 i::Zone zone; |
171 Local<String> source = Local<String>::Cast(args[0]); | 173 Local<String> source = Local<String>::Cast(args[0]); |
172 i::Handle<i::Script> script = factory->NewScript(Utils::OpenHandle(*source)); | 174 i::Handle<i::Script> script = factory->NewScript(Utils::OpenHandle(*source)); |
173 i::ParseInfo info(&zone, script); | 175 i::ParseInfo info(&zone, script); |
174 | 176 |
175 auto module = TranslateAsmModule(&info); | 177 auto module = TranslateAsmModule(&info, &thrower); |
176 if (module == nullptr) { | 178 if (module == nullptr) { |
177 thrower.Error("Asm.js validation failed"); | |
178 return; | 179 return; |
179 } | 180 } |
180 | 181 |
181 int32_t result = v8::internal::wasm::CompileAndRunWasmModule( | 182 int32_t result = v8::internal::wasm::CompileAndRunWasmModule( |
182 isolate, module->Begin(), module->End(), true); | 183 isolate, module->Begin(), module->End(), true); |
183 args.GetReturnValue().Set(result); | 184 args.GetReturnValue().Set(result); |
184 } | 185 } |
185 | 186 |
186 | 187 |
187 // TODO(aseemgarg): deal with arraybuffer and foreign functions | 188 void InstantiateModuleCommon(const v8::FunctionCallbackInfo<v8::Value>& args, |
188 void InstantiateModuleFromAsm(const v8::FunctionCallbackInfo<v8::Value>& args) { | 189 const byte* start, const byte* end, |
189 HandleScope scope(args.GetIsolate()); | 190 ErrorThrower* thrower, bool must_decode) { |
190 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); | 191 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); |
191 ErrorThrower thrower(isolate, "WASM.instantiateModuleFromAsm()"); | |
192 | 192 |
193 if (args.Length() != 1) { | 193 i::Handle<i::JSArrayBuffer> memory = i::Handle<i::JSArrayBuffer>::null(); |
194 thrower.Error("Invalid argument count"); | 194 if (args.Length() > 2 && args[2]->IsArrayBuffer()) { |
195 return; | 195 Local<Object> obj = Local<Object>::Cast(args[2]); |
196 } | 196 i::Handle<i::Object> mem_obj = v8::Utils::OpenHandle(*obj); |
197 if (!args[0]->IsString()) { | 197 memory = i::Handle<i::JSArrayBuffer>(i::JSArrayBuffer::cast(*mem_obj)); |
198 thrower.Error("Invalid argument count"); | |
199 return; | |
200 } | 198 } |
201 | 199 |
202 i::Factory* factory = isolate->factory(); | 200 // Decode but avoid a redundant pass over function bodies for verification. |
| 201 // Verification will happen during compilation. |
203 i::Zone zone; | 202 i::Zone zone; |
204 Local<String> source = Local<String>::Cast(args[0]); | 203 internal::wasm::ModuleResult result = internal::wasm::DecodeWasmModule( |
205 i::Handle<i::Script> script = factory->NewScript(Utils::OpenHandle(*source)); | 204 isolate, &zone, start, end, false, false); |
206 i::ParseInfo info(&zone, script); | |
207 | 205 |
208 auto module = TranslateAsmModule(&info); | 206 if (result.failed() && must_decode) { |
209 if (module == nullptr) { | 207 thrower->Error("Asm.js converted module failed to decode"); |
210 thrower.Error("Asm.js validation failed"); | 208 } else if (result.failed()) { |
211 return; | 209 thrower->Failed("", result); |
212 } | |
213 | |
214 i::Handle<i::JSArrayBuffer> memory = i::Handle<i::JSArrayBuffer>::null(); | |
215 internal::wasm::ModuleResult result = internal::wasm::DecodeWasmModule( | |
216 isolate, &zone, module->Begin(), module->End(), false, false); | |
217 | |
218 if (result.failed()) { | |
219 thrower.Failed("", result); | |
220 } else { | 210 } else { |
221 // Success. Instantiate the module and return the object. | 211 // Success. Instantiate the module and return the object. |
222 i::Handle<i::JSObject> ffi = i::Handle<i::JSObject>::null(); | 212 i::Handle<i::JSObject> ffi = i::Handle<i::JSObject>::null(); |
| 213 if (args.Length() > 1 && args[1]->IsObject()) { |
| 214 Local<Object> obj = Local<Object>::Cast(args[1]); |
| 215 ffi = i::Handle<i::JSObject>::cast(v8::Utils::OpenHandle(*obj)); |
| 216 } |
223 | 217 |
224 i::MaybeHandle<i::JSObject> object = | 218 i::MaybeHandle<i::JSObject> object = |
225 result.val->Instantiate(isolate, ffi, memory); | 219 result.val->Instantiate(isolate, ffi, memory); |
226 | 220 |
227 if (!object.is_null()) { | 221 if (!object.is_null()) { |
228 args.GetReturnValue().Set(v8::Utils::ToLocal(object.ToHandleChecked())); | 222 args.GetReturnValue().Set(v8::Utils::ToLocal(object.ToHandleChecked())); |
229 } | 223 } |
230 } | 224 } |
231 | 225 |
232 if (result.val) delete result.val; | 226 if (result.val) delete result.val; |
233 } | 227 } |
234 | 228 |
235 | 229 |
| 230 void InstantiateModuleFromAsm(const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 231 HandleScope scope(args.GetIsolate()); |
| 232 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); |
| 233 ErrorThrower thrower(isolate, "WASM.instantiateModuleFromAsm()"); |
| 234 |
| 235 if (!args[0]->IsString()) { |
| 236 thrower.Error("Asm module text should be a string"); |
| 237 return; |
| 238 } |
| 239 |
| 240 i::Factory* factory = isolate->factory(); |
| 241 i::Zone zone; |
| 242 Local<String> source = Local<String>::Cast(args[0]); |
| 243 i::Handle<i::Script> script = factory->NewScript(Utils::OpenHandle(*source)); |
| 244 i::ParseInfo info(&zone, script); |
| 245 |
| 246 auto module = TranslateAsmModule(&info, &thrower); |
| 247 if (module == nullptr) { |
| 248 return; |
| 249 } |
| 250 |
| 251 InstantiateModuleCommon(args, module->Begin(), module->End(), &thrower, true); |
| 252 } |
| 253 |
| 254 |
236 void InstantiateModule(const v8::FunctionCallbackInfo<v8::Value>& args) { | 255 void InstantiateModule(const v8::FunctionCallbackInfo<v8::Value>& args) { |
237 HandleScope scope(args.GetIsolate()); | 256 HandleScope scope(args.GetIsolate()); |
238 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); | 257 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); |
239 ErrorThrower thrower(isolate, "WASM.instantiateModule()"); | 258 ErrorThrower thrower(isolate, "WASM.instantiateModule()"); |
240 | 259 |
241 RawBuffer buffer = GetRawBufferArgument(thrower, args); | 260 RawBuffer buffer = GetRawBufferArgument(thrower, args); |
242 if (buffer.start == nullptr) return; | 261 if (buffer.start == nullptr) return; |
243 | 262 |
244 i::Handle<i::JSArrayBuffer> memory = i::Handle<i::JSArrayBuffer>::null(); | 263 InstantiateModuleCommon(args, buffer.start, buffer.end, &thrower, false); |
245 if (args.Length() > 2 && args[2]->IsArrayBuffer()) { | |
246 Local<Object> obj = Local<Object>::Cast(args[2]); | |
247 i::Handle<i::Object> mem_obj = v8::Utils::OpenHandle(*obj); | |
248 memory = i::Handle<i::JSArrayBuffer>(i::JSArrayBuffer::cast(*mem_obj)); | |
249 } | |
250 | |
251 // Decode but avoid a redundant pass over function bodies for verification. | |
252 // Verification will happen during compilation. | |
253 i::Zone zone; | |
254 internal::wasm::ModuleResult result = internal::wasm::DecodeWasmModule( | |
255 isolate, &zone, buffer.start, buffer.end, false, false); | |
256 | |
257 if (result.failed()) { | |
258 thrower.Failed("", result); | |
259 } else { | |
260 // Success. Instantiate the module and return the object. | |
261 i::Handle<i::JSObject> ffi = i::Handle<i::JSObject>::null(); | |
262 if (args.Length() > 1 && args[1]->IsObject()) { | |
263 Local<Object> obj = Local<Object>::Cast(args[1]); | |
264 ffi = i::Handle<i::JSObject>::cast(v8::Utils::OpenHandle(*obj)); | |
265 } | |
266 | |
267 i::MaybeHandle<i::JSObject> object = | |
268 result.val->Instantiate(isolate, ffi, memory); | |
269 | |
270 if (!object.is_null()) { | |
271 args.GetReturnValue().Set(v8::Utils::ToLocal(object.ToHandleChecked())); | |
272 } | |
273 } | |
274 | |
275 if (result.val) delete result.val; | |
276 } | 264 } |
277 } // namespace | 265 } // namespace |
278 | 266 |
279 | 267 |
280 // TODO(titzer): we use the API to create the function template because the | 268 // TODO(titzer): we use the API to create the function template because the |
281 // internal guts are too ugly to replicate here. | 269 // internal guts are too ugly to replicate here. |
282 static i::Handle<i::FunctionTemplateInfo> NewTemplate(i::Isolate* i_isolate, | 270 static i::Handle<i::FunctionTemplateInfo> NewTemplate(i::Isolate* i_isolate, |
283 FunctionCallback func) { | 271 FunctionCallback func) { |
284 Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate); | 272 Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate); |
285 Local<FunctionTemplate> local = FunctionTemplate::New(isolate, func); | 273 Local<FunctionTemplate> local = FunctionTemplate::New(isolate, func); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
336 if (!context->get(Context::WASM_FUNCTION_MAP_INDEX)->IsMap()) { | 324 if (!context->get(Context::WASM_FUNCTION_MAP_INDEX)->IsMap()) { |
337 Handle<Map> wasm_function_map = isolate->factory()->NewMap( | 325 Handle<Map> wasm_function_map = isolate->factory()->NewMap( |
338 JS_FUNCTION_TYPE, JSFunction::kSize + kPointerSize); | 326 JS_FUNCTION_TYPE, JSFunction::kSize + kPointerSize); |
339 wasm_function_map->set_is_callable(); | 327 wasm_function_map->set_is_callable(); |
340 context->set_wasm_function_map(*wasm_function_map); | 328 context->set_wasm_function_map(*wasm_function_map); |
341 } | 329 } |
342 } | 330 } |
343 | 331 |
344 } // namespace internal | 332 } // namespace internal |
345 } // namespace v8 | 333 } // namespace v8 |
OLD | NEW |