OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "src/asmjs/asm-js.h" |
| 6 |
| 7 #include "src/api-natives.h" |
| 8 #include "src/api.h" |
| 9 #include "src/asmjs/asm-wasm-builder.h" |
| 10 #include "src/asmjs/typing-asm.h" |
| 11 #include "src/assert-scope.h" |
| 12 #include "src/ast/ast.h" |
| 13 #include "src/ast/scopes.h" |
| 14 #include "src/execution.h" |
| 15 #include "src/factory.h" |
| 16 #include "src/handles.h" |
| 17 #include "src/isolate.h" |
| 18 #include "src/objects.h" |
| 19 #include "src/parsing/parser.h" |
| 20 |
| 21 #include "src/wasm/encoder.h" |
| 22 #include "src/wasm/module-decoder.h" |
| 23 #include "src/wasm/wasm-js.h" |
| 24 #include "src/wasm/wasm-module.h" |
| 25 #include "src/wasm/wasm-result.h" |
| 26 |
| 27 typedef uint8_t byte; |
| 28 |
| 29 using v8::internal::wasm::ErrorThrower; |
| 30 |
| 31 namespace v8 { |
| 32 namespace internal { |
| 33 |
| 34 namespace { |
| 35 i::MaybeHandle<i::FixedArray> CompileModule( |
| 36 i::Isolate* isolate, const byte* start, const byte* end, |
| 37 ErrorThrower* thrower, |
| 38 internal::wasm::ModuleOrigin origin = i::wasm::kWasmOrigin) { |
| 39 // Decode but avoid a redundant pass over function bodies for verification. |
| 40 // Verification will happen during compilation. |
| 41 i::Zone zone(isolate->allocator()); |
| 42 internal::wasm::ModuleResult result = internal::wasm::DecodeWasmModule( |
| 43 isolate, &zone, start, end, false, origin); |
| 44 |
| 45 i::MaybeHandle<i::FixedArray> compiled_module; |
| 46 if (result.failed() && origin == internal::wasm::kAsmJsOrigin) { |
| 47 thrower->Error("Asm.js converted module failed to decode"); |
| 48 } else if (result.failed()) { |
| 49 thrower->Failed("", result); |
| 50 } else { |
| 51 compiled_module = result.val->CompileFunctions(isolate); |
| 52 } |
| 53 |
| 54 if (result.val) delete result.val; |
| 55 return compiled_module; |
| 56 } |
| 57 |
| 58 } // namespace |
| 59 |
| 60 MaybeHandle<FixedArray> AsmJs::ConvertAsmToWasm(ParseInfo* info) { |
| 61 ErrorThrower thrower(info->isolate(), "Asm.js -> WebAssembly conversion"); |
| 62 AsmTyper typer(info->isolate(), info->zone(), *(info->script()), |
| 63 info->literal()); |
| 64 typer.set_fixed_signature(true); |
| 65 if (i::FLAG_enable_simd_asmjs) { |
| 66 typer.set_allow_simd(true); |
| 67 } |
| 68 if (!typer.Validate()) { |
| 69 DCHECK(!info->isolate()->has_pending_exception()); |
| 70 PrintF("Validation of asm.js module failed: %s", typer.error_message()); |
| 71 return MaybeHandle<FixedArray>(); |
| 72 } |
| 73 v8::internal::wasm::AsmWasmBuilder builder(info->isolate(), info->zone(), |
| 74 info->literal(), &typer); |
| 75 i::Handle<i::FixedArray> foreign_globals; |
| 76 auto module = builder.Run(&foreign_globals); |
| 77 size_t byte_length = module->end() - module->begin(); |
| 78 Handle<JSArrayBuffer> buffer = info->isolate()->factory()->NewJSArrayBuffer(); |
| 79 JSArrayBuffer::SetupAllocatingData(buffer, info->isolate(), byte_length, |
| 80 false, SharedFlag::kNotShared); |
| 81 uint8_t* module_bytes = reinterpret_cast<uint8_t*>(buffer->backing_store()); |
| 82 memcpy(module_bytes, module->begin(), byte_length); |
| 83 Handle<FixedArray> result = info->isolate()->factory()->NewFixedArray(2); |
| 84 result->set(0, *buffer); |
| 85 result->set(1, *foreign_globals); |
| 86 return result; |
| 87 } |
| 88 |
| 89 MaybeHandle<Object> AsmJs::InstantiateAsmWasm(i::Isolate* isolate, |
| 90 Handle<FixedArray> wasm_data, |
| 91 Handle<JSArrayBuffer> memory, |
| 92 Handle<JSObject> foreign) { |
| 93 i::Handle<i::JSArrayBuffer> module_bytes( |
| 94 i::JSArrayBuffer::cast(wasm_data->get(0))); |
| 95 i::Handle<i::FixedArray> foreign_globals( |
| 96 i::FixedArray::cast(wasm_data->get(1))); |
| 97 |
| 98 ErrorThrower thrower(isolate, "Asm.js -> WebAssembly instantiation"); |
| 99 |
| 100 const byte* module_start = |
| 101 reinterpret_cast<const byte*>(module_bytes->backing_store()); |
| 102 size_t module_length = |
| 103 static_cast<size_t>(module_bytes->byte_length()->Number()); |
| 104 const byte* module_end = module_start + module_length; |
| 105 i::MaybeHandle<i::FixedArray> compiled = |
| 106 CompileModule(isolate, module_start, module_end, &thrower, |
| 107 internal::wasm::kAsmJsOrigin); |
| 108 if (compiled.is_null()) { |
| 109 return MaybeHandle<Object>(); |
| 110 } |
| 111 i::MaybeHandle<i::JSObject> maybe_module_object = |
| 112 i::wasm::WasmModule::Instantiate(isolate, compiled.ToHandleChecked(), |
| 113 foreign, memory); |
| 114 if (maybe_module_object.is_null()) { |
| 115 return MaybeHandle<Object>(); |
| 116 } |
| 117 |
| 118 i::Handle<i::Name> name(isolate->factory()->InternalizeOneByteString( |
| 119 STATIC_CHAR_VECTOR("__foreign_init__"))); |
| 120 |
| 121 i::Handle<i::Object> module_object = maybe_module_object.ToHandleChecked(); |
| 122 i::MaybeHandle<i::Object> maybe_init = |
| 123 i::Object::GetProperty(module_object, name); |
| 124 DCHECK(!maybe_init.is_null()); |
| 125 |
| 126 i::Handle<i::Object> init = maybe_init.ToHandleChecked(); |
| 127 i::Handle<i::Object> undefined(isolate->heap()->undefined_value(), isolate); |
| 128 i::Handle<i::Object>* foreign_args_array = |
| 129 new i::Handle<i::Object>[foreign_globals->length()]; |
| 130 for (int j = 0; j < foreign_globals->length(); j++) { |
| 131 if (!foreign.is_null()) { |
| 132 i::MaybeHandle<i::Name> name = i::Object::ToName( |
| 133 isolate, i::Handle<i::Object>(foreign_globals->get(j), isolate)); |
| 134 if (!name.is_null()) { |
| 135 i::MaybeHandle<i::Object> val = |
| 136 i::Object::GetProperty(foreign, name.ToHandleChecked()); |
| 137 if (!val.is_null()) { |
| 138 foreign_args_array[j] = val.ToHandleChecked(); |
| 139 continue; |
| 140 } |
| 141 } |
| 142 } |
| 143 foreign_args_array[j] = undefined; |
| 144 } |
| 145 i::MaybeHandle<i::Object> retval = i::Execution::Call( |
| 146 isolate, init, undefined, foreign_globals->length(), foreign_args_array); |
| 147 delete[] foreign_args_array; |
| 148 |
| 149 if (retval.is_null()) { |
| 150 thrower.Error( |
| 151 "WASM.instantiateModuleFromAsm(): foreign init function failed"); |
| 152 return MaybeHandle<Object>(); |
| 153 } |
| 154 return maybe_module_object; |
| 155 } |
| 156 |
| 157 } // namespace internal |
| 158 } // namespace v8 |
OLD | NEW |