Chromium Code Reviews| 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 thrower.Error("!!!!BBBBBB Asm module text should be a string"); | |
|
aseemgarg
2016/01/14 22:08:04
Don't know what !!!!BBBBBB means..
bradn
2016/01/14 22:39:18
Oops, leftover, dropping.
| |
| 249 return; | |
| 250 } | |
| 251 | |
| 252 InstantiateModuleCommon(args, module->Begin(), module->End(), &thrower, true); | |
| 253 } | |
| 254 | |
| 255 | |
| 236 void InstantiateModule(const v8::FunctionCallbackInfo<v8::Value>& args) { | 256 void InstantiateModule(const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 237 HandleScope scope(args.GetIsolate()); | 257 HandleScope scope(args.GetIsolate()); |
| 238 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); | 258 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); |
| 239 ErrorThrower thrower(isolate, "WASM.instantiateModule()"); | 259 ErrorThrower thrower(isolate, "WASM.instantiateModule()"); |
| 240 | 260 |
| 241 RawBuffer buffer = GetRawBufferArgument(thrower, args); | 261 RawBuffer buffer = GetRawBufferArgument(thrower, args); |
| 242 if (buffer.start == nullptr) return; | 262 if (buffer.start == nullptr) return; |
| 243 | 263 |
| 244 i::Handle<i::JSArrayBuffer> memory = i::Handle<i::JSArrayBuffer>::null(); | 264 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 } | 265 } |
| 277 } // namespace | 266 } // namespace |
| 278 | 267 |
| 279 | 268 |
| 280 // TODO(titzer): we use the API to create the function template because the | 269 // TODO(titzer): we use the API to create the function template because the |
| 281 // internal guts are too ugly to replicate here. | 270 // internal guts are too ugly to replicate here. |
| 282 static i::Handle<i::FunctionTemplateInfo> NewTemplate(i::Isolate* i_isolate, | 271 static i::Handle<i::FunctionTemplateInfo> NewTemplate(i::Isolate* i_isolate, |
| 283 FunctionCallback func) { | 272 FunctionCallback func) { |
| 284 Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate); | 273 Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate); |
| 285 Local<FunctionTemplate> local = FunctionTemplate::New(isolate, func); | 274 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()) { | 325 if (!context->get(Context::WASM_FUNCTION_MAP_INDEX)->IsMap()) { |
| 337 Handle<Map> wasm_function_map = isolate->factory()->NewMap( | 326 Handle<Map> wasm_function_map = isolate->factory()->NewMap( |
| 338 JS_FUNCTION_TYPE, JSFunction::kSize + kPointerSize); | 327 JS_FUNCTION_TYPE, JSFunction::kSize + kPointerSize); |
| 339 wasm_function_map->set_is_callable(); | 328 wasm_function_map->set_is_callable(); |
| 340 context->set_wasm_function_map(*wasm_function_map); | 329 context->set_wasm_function_map(*wasm_function_map); |
| 341 } | 330 } |
| 342 } | 331 } |
| 343 | 332 |
| 344 } // namespace internal | 333 } // namespace internal |
| 345 } // namespace v8 | 334 } // namespace v8 |
| OLD | NEW |