summaryrefslogtreecommitdiff
path: root/deps/v8/src/asmjs/asm-js.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/asmjs/asm-js.cc')
-rw-r--r--deps/v8/src/asmjs/asm-js.cc523
1 files changed, 232 insertions, 291 deletions
diff --git a/deps/v8/src/asmjs/asm-js.cc b/deps/v8/src/asmjs/asm-js.cc
index fb46026a98..516bce2543 100644
--- a/deps/v8/src/asmjs/asm-js.cc
+++ b/deps/v8/src/asmjs/asm-js.cc
@@ -6,10 +6,10 @@
#include "src/api-natives.h"
#include "src/api.h"
+#include "src/asmjs/asm-names.h"
#include "src/asmjs/asm-parser.h"
-#include "src/asmjs/asm-typer.h"
-#include "src/asmjs/asm-wasm-builder.h"
#include "src/assert-scope.h"
+#include "src/ast/ast.h"
#include "src/base/platform/elapsed-timer.h"
#include "src/compilation-info.h"
#include "src/execution.h"
@@ -18,7 +18,6 @@
#include "src/isolate.h"
#include "src/objects-inl.h"
#include "src/objects.h"
-#include "src/parsing/parse-info.h"
#include "src/wasm/module-decoder.h"
#include "src/wasm/wasm-js.h"
@@ -27,286 +26,266 @@
#include "src/wasm/wasm-objects.h"
#include "src/wasm/wasm-result.h"
-typedef uint8_t byte;
-
-using v8::internal::wasm::ErrorThrower;
-
namespace v8 {
namespace internal {
+const char* const AsmJs::kSingleFunctionName = "__single_function__";
+
namespace {
enum WasmDataEntries {
kWasmDataCompiledModule,
- kWasmDataForeignGlobals,
kWasmDataUsesArray,
- kWasmDataScript,
- kWasmDataScriptPosition,
kWasmDataEntryCount,
};
-Handle<i::Object> StdlibMathMember(i::Isolate* isolate,
- Handle<JSReceiver> stdlib,
- Handle<Name> name) {
- if (stdlib.is_null()) {
- return Handle<i::Object>();
- }
- Handle<i::Name> math_name(
+Handle<Object> StdlibMathMember(Isolate* isolate, Handle<JSReceiver> stdlib,
+ Handle<Name> name) {
+ Handle<Name> math_name(
isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("Math")));
- MaybeHandle<i::Object> maybe_math = i::Object::GetProperty(stdlib, math_name);
- if (maybe_math.is_null()) {
- return Handle<i::Object>();
- }
- Handle<i::Object> math = maybe_math.ToHandleChecked();
- if (!math->IsJSReceiver()) {
- return Handle<i::Object>();
- }
- MaybeHandle<i::Object> maybe_value = i::Object::GetProperty(math, name);
- if (maybe_value.is_null()) {
- return Handle<i::Object>();
- }
- return maybe_value.ToHandleChecked();
+ Handle<Object> math = JSReceiver::GetDataProperty(stdlib, math_name);
+ if (!math->IsJSReceiver()) return isolate->factory()->undefined_value();
+ Handle<JSReceiver> math_receiver = Handle<JSReceiver>::cast(math);
+ Handle<Object> value = JSReceiver::GetDataProperty(math_receiver, name);
+ return value;
}
-bool IsStdlibMemberValid(i::Isolate* isolate, Handle<JSReceiver> stdlib,
- Handle<i::Object> member_id) {
- int32_t member_kind;
- if (!member_id->ToInt32(&member_kind)) {
- UNREACHABLE();
- }
- switch (member_kind) {
- case wasm::AsmTyper::StandardMember::kNone:
- case wasm::AsmTyper::StandardMember::kModule:
- case wasm::AsmTyper::StandardMember::kStdlib:
- case wasm::AsmTyper::StandardMember::kHeap:
- case wasm::AsmTyper::StandardMember::kFFI: {
- // Nothing to check for these.
- return true;
- }
- case wasm::AsmTyper::StandardMember::kInfinity: {
- if (stdlib.is_null()) {
- return false;
- }
- Handle<i::Name> name(isolate->factory()->InternalizeOneByteString(
- STATIC_CHAR_VECTOR("Infinity")));
- MaybeHandle<i::Object> maybe_value = i::Object::GetProperty(stdlib, name);
- if (maybe_value.is_null()) {
- return false;
- }
- Handle<i::Object> value = maybe_value.ToHandleChecked();
+bool IsStdlibMemberValid(Isolate* isolate, Handle<JSReceiver> stdlib,
+ wasm::AsmJsParser::StandardMember member,
+ bool* is_typed_array) {
+ switch (member) {
+ case wasm::AsmJsParser::StandardMember::kInfinity: {
+ Handle<Name> name = isolate->factory()->infinity_string();
+ Handle<Object> value = JSReceiver::GetDataProperty(stdlib, name);
return value->IsNumber() && std::isinf(value->Number());
}
- case wasm::AsmTyper::StandardMember::kNaN: {
- if (stdlib.is_null()) {
- return false;
- }
- Handle<i::Name> name(isolate->factory()->InternalizeOneByteString(
- STATIC_CHAR_VECTOR("NaN")));
- MaybeHandle<i::Object> maybe_value = i::Object::GetProperty(stdlib, name);
- if (maybe_value.is_null()) {
- return false;
- }
- Handle<i::Object> value = maybe_value.ToHandleChecked();
+ case wasm::AsmJsParser::StandardMember::kNaN: {
+ Handle<Name> name = isolate->factory()->nan_string();
+ Handle<Object> value = JSReceiver::GetDataProperty(stdlib, name);
return value->IsNaN();
}
-#define STDLIB_MATH_FUNC(CamelName, fname) \
- case wasm::AsmTyper::StandardMember::k##CamelName: { \
- Handle<i::Name> name(isolate->factory()->InternalizeOneByteString( \
- STATIC_CHAR_VECTOR(#fname))); \
- Handle<i::Object> value = StdlibMathMember(isolate, stdlib, name); \
- if (value.is_null() || !value->IsJSFunction()) { \
- return false; \
- } \
- Handle<i::JSFunction> func(i::JSFunction::cast(*value)); \
- return func->shared()->code() == \
- isolate->builtins()->builtin(Builtins::k##CamelName); \
+#define STDLIB_MATH_FUNC(fname, FName, ignore1, ignore2) \
+ case wasm::AsmJsParser::StandardMember::kMath##FName: { \
+ Handle<Name> name(isolate->factory()->InternalizeOneByteString( \
+ STATIC_CHAR_VECTOR(#fname))); \
+ Handle<Object> value = StdlibMathMember(isolate, stdlib, name); \
+ if (!value->IsJSFunction()) return false; \
+ Handle<JSFunction> func = Handle<JSFunction>::cast(value); \
+ return func->shared()->code() == \
+ isolate->builtins()->builtin(Builtins::kMath##FName); \
}
- STDLIB_MATH_FUNC(MathAcos, acos)
- STDLIB_MATH_FUNC(MathAsin, asin)
- STDLIB_MATH_FUNC(MathAtan, atan)
- STDLIB_MATH_FUNC(MathCos, cos)
- STDLIB_MATH_FUNC(MathSin, sin)
- STDLIB_MATH_FUNC(MathTan, tan)
- STDLIB_MATH_FUNC(MathExp, exp)
- STDLIB_MATH_FUNC(MathLog, log)
- STDLIB_MATH_FUNC(MathCeil, ceil)
- STDLIB_MATH_FUNC(MathFloor, floor)
- STDLIB_MATH_FUNC(MathSqrt, sqrt)
- STDLIB_MATH_FUNC(MathAbs, abs)
- STDLIB_MATH_FUNC(MathClz32, clz32)
- STDLIB_MATH_FUNC(MathMin, min)
- STDLIB_MATH_FUNC(MathMax, max)
- STDLIB_MATH_FUNC(MathAtan2, atan2)
- STDLIB_MATH_FUNC(MathPow, pow)
- STDLIB_MATH_FUNC(MathImul, imul)
- STDLIB_MATH_FUNC(MathFround, fround)
+ STDLIB_MATH_FUNCTION_LIST(STDLIB_MATH_FUNC)
#undef STDLIB_MATH_FUNC
-#define STDLIB_MATH_CONST(cname, const_value) \
- case wasm::AsmTyper::StandardMember::kMath##cname: { \
- i::Handle<i::Name> name(isolate->factory()->InternalizeOneByteString( \
- STATIC_CHAR_VECTOR(#cname))); \
- i::Handle<i::Object> value = StdlibMathMember(isolate, stdlib, name); \
- return !value.is_null() && value->IsNumber() && \
- value->Number() == const_value; \
+#define STDLIB_MATH_CONST(cname, const_value) \
+ case wasm::AsmJsParser::StandardMember::kMath##cname: { \
+ Handle<Name> name(isolate->factory()->InternalizeOneByteString( \
+ STATIC_CHAR_VECTOR(#cname))); \
+ Handle<Object> value = StdlibMathMember(isolate, stdlib, name); \
+ return value->IsNumber() && value->Number() == const_value; \
}
- STDLIB_MATH_CONST(E, 2.718281828459045)
- STDLIB_MATH_CONST(LN10, 2.302585092994046)
- STDLIB_MATH_CONST(LN2, 0.6931471805599453)
- STDLIB_MATH_CONST(LOG2E, 1.4426950408889634)
- STDLIB_MATH_CONST(LOG10E, 0.4342944819032518)
- STDLIB_MATH_CONST(PI, 3.141592653589793)
- STDLIB_MATH_CONST(SQRT1_2, 0.7071067811865476)
- STDLIB_MATH_CONST(SQRT2, 1.4142135623730951)
+ STDLIB_MATH_VALUE_LIST(STDLIB_MATH_CONST)
#undef STDLIB_MATH_CONST
- default: { UNREACHABLE(); }
+#define STDLIB_ARRAY_TYPE(fname, FName) \
+ case wasm::AsmJsParser::StandardMember::k##FName: { \
+ *is_typed_array = true; \
+ Handle<Name> name(isolate->factory()->InternalizeOneByteString( \
+ STATIC_CHAR_VECTOR(#FName))); \
+ Handle<Object> value = JSReceiver::GetDataProperty(stdlib, name); \
+ if (!value->IsJSFunction()) return false; \
+ Handle<JSFunction> func = Handle<JSFunction>::cast(value); \
+ return func.is_identical_to(isolate->fname()); \
+ }
+ STDLIB_ARRAY_TYPE(int8_array_fun, Int8Array)
+ STDLIB_ARRAY_TYPE(uint8_array_fun, Uint8Array)
+ STDLIB_ARRAY_TYPE(int16_array_fun, Int16Array)
+ STDLIB_ARRAY_TYPE(uint16_array_fun, Uint16Array)
+ STDLIB_ARRAY_TYPE(int32_array_fun, Int32Array)
+ STDLIB_ARRAY_TYPE(uint32_array_fun, Uint32Array)
+ STDLIB_ARRAY_TYPE(float32_array_fun, Float32Array)
+ STDLIB_ARRAY_TYPE(float64_array_fun, Float64Array)
+#undef STDLIB_ARRAY_TYPE
}
+ UNREACHABLE();
return false;
}
+void Report(Handle<Script> script, int position, Vector<const char> text,
+ MessageTemplate::Template message_template,
+ v8::Isolate::MessageErrorLevel level) {
+ Isolate* isolate = script->GetIsolate();
+ MessageLocation location(script, position, position);
+ Handle<String> text_object = isolate->factory()->InternalizeUtf8String(text);
+ Handle<JSMessageObject> message = MessageHandler::MakeMessageObject(
+ isolate, message_template, &location, text_object,
+ Handle<FixedArray>::null());
+ message->set_error_level(level);
+ MessageHandler::ReportMessage(isolate, &location, message);
+}
+
+// Hook to report successful execution of {AsmJs::CompileAsmViaWasm} phase.
+void ReportCompilationSuccess(Handle<Script> script, int position,
+ double translate_time, double compile_time,
+ size_t module_size) {
+ if (FLAG_suppress_asm_messages || !FLAG_trace_asm_time) return;
+ EmbeddedVector<char, 100> text;
+ int length = SNPrintF(
+ text, "success, asm->wasm: %0.3f ms, compile: %0.3f ms, %" PRIuS " bytes",
+ translate_time, compile_time, module_size);
+ CHECK_NE(-1, length);
+ text.Truncate(length);
+ Report(script, position, text, MessageTemplate::kAsmJsCompiled,
+ v8::Isolate::kMessageInfo);
+}
+
+// Hook to report failed execution of {AsmJs::CompileAsmViaWasm} phase.
+void ReportCompilationFailure(Handle<Script> script, int position,
+ const char* reason) {
+ if (FLAG_suppress_asm_messages) return;
+ Vector<const char> text = CStrVector(reason);
+ Report(script, position, text, MessageTemplate::kAsmJsInvalid,
+ v8::Isolate::kMessageWarning);
+}
+
+// Hook to report successful execution of {AsmJs::InstantiateAsmWasm} phase.
+void ReportInstantiationSuccess(Handle<Script> script, int position,
+ double instantiate_time) {
+ if (FLAG_suppress_asm_messages || !FLAG_trace_asm_time) return;
+ EmbeddedVector<char, 50> text;
+ int length = SNPrintF(text, "success, %0.3f ms", instantiate_time);
+ CHECK_NE(-1, length);
+ text.Truncate(length);
+ Report(script, position, text, MessageTemplate::kAsmJsInstantiated,
+ v8::Isolate::kMessageInfo);
+}
+
+// Hook to report failed execution of {AsmJs::InstantiateAsmWasm} phase.
+void ReportInstantiationFailure(Handle<Script> script, int position,
+ const char* reason) {
+ if (FLAG_suppress_asm_messages) return;
+ Vector<const char> text = CStrVector(reason);
+ Report(script, position, text, MessageTemplate::kAsmJsLinkingFailed,
+ v8::Isolate::kMessageWarning);
+}
+
} // namespace
MaybeHandle<FixedArray> AsmJs::CompileAsmViaWasm(CompilationInfo* info) {
wasm::ZoneBuffer* module = nullptr;
wasm::ZoneBuffer* asm_offsets = nullptr;
Handle<FixedArray> uses_array;
- Handle<FixedArray> foreign_globals;
- base::ElapsedTimer asm_wasm_timer;
- asm_wasm_timer.Start();
- wasm::AsmWasmBuilder builder(info);
- if (FLAG_fast_validate_asm) {
- wasm::AsmJsParser parser(info->isolate(), info->zone(), info->script(),
+ Handle<WasmModuleObject> compiled;
+
+ // The compilation of asm.js modules is split into two distinct steps:
+ // [1] The asm.js module source is parsed, validated, and translated to a
+ // valid WebAssembly module. The result are two vectors representing the
+ // encoded module as well as encoded source position information.
+ // [2] The module is handed to WebAssembly which decodes it into an internal
+ // representation and eventually compiles it to machine code.
+ double translate_time; // Time (milliseconds) taken to execute step [1].
+ double compile_time; // Time (milliseconds) taken to execute step [2].
+
+ // Step 1: Translate asm.js module to WebAssembly module.
+ {
+ HistogramTimerScope translate_time_scope(
+ info->isolate()->counters()->asm_wasm_translation_time());
+ size_t compile_zone_start = info->zone()->allocation_size();
+ base::ElapsedTimer translate_timer;
+ translate_timer.Start();
+
+ Zone* compile_zone = info->zone();
+ Zone translate_zone(info->isolate()->allocator(), ZONE_NAME);
+ wasm::AsmJsParser parser(info->isolate(), &translate_zone, info->script(),
info->literal()->start_position(),
info->literal()->end_position());
if (!parser.Run()) {
DCHECK(!info->isolate()->has_pending_exception());
- if (!FLAG_suppress_asm_messages) {
- MessageLocation location(info->script(), parser.failure_location(),
- parser.failure_location());
- Handle<String> message =
- info->isolate()
- ->factory()
- ->NewStringFromUtf8(CStrVector(parser.failure_message()))
- .ToHandleChecked();
- Handle<JSMessageObject> error_message =
- MessageHandler::MakeMessageObject(
- info->isolate(), MessageTemplate::kAsmJsInvalid, &location,
- message, Handle<JSArray>::null());
- error_message->set_error_level(v8::Isolate::kMessageWarning);
- MessageHandler::ReportMessage(info->isolate(), &location,
- error_message);
- }
+ ReportCompilationFailure(info->script(), parser.failure_location(),
+ parser.failure_message());
return MaybeHandle<FixedArray>();
}
- Zone* zone = info->zone();
- module = new (zone) wasm::ZoneBuffer(zone);
+ module = new (compile_zone) wasm::ZoneBuffer(compile_zone);
parser.module_builder()->WriteTo(*module);
- asm_offsets = new (zone) wasm::ZoneBuffer(zone);
+ asm_offsets = new (compile_zone) wasm::ZoneBuffer(compile_zone);
parser.module_builder()->WriteAsmJsOffsetTable(*asm_offsets);
- // TODO(bradnelson): Remove foreign_globals plumbing (as we don't need it
- // for the new parser).
- foreign_globals = info->isolate()->factory()->NewFixedArray(0);
uses_array = info->isolate()->factory()->NewFixedArray(
static_cast<int>(parser.stdlib_uses()->size()));
int count = 0;
for (auto i : *parser.stdlib_uses()) {
uses_array->set(count++, Smi::FromInt(i));
}
- } else {
- auto asm_wasm_result = builder.Run(&foreign_globals);
- if (!asm_wasm_result.success) {
- DCHECK(!info->isolate()->has_pending_exception());
- if (!FLAG_suppress_asm_messages) {
- MessageHandler::ReportMessage(info->isolate(),
- builder.typer()->message_location(),
- builder.typer()->error_message());
- }
- return MaybeHandle<FixedArray>();
- }
- module = asm_wasm_result.module_bytes;
- asm_offsets = asm_wasm_result.asm_offset_table;
- wasm::AsmTyper::StdlibSet uses = builder.typer()->StdlibUses();
- uses_array = info->isolate()->factory()->NewFixedArray(
- static_cast<int>(uses.size()));
- int count = 0;
- for (auto i : uses) {
- uses_array->set(count++, Smi::FromInt(i));
+ size_t compile_zone_size =
+ info->zone()->allocation_size() - compile_zone_start;
+ size_t translate_zone_size = translate_zone.allocation_size();
+ info->isolate()
+ ->counters()
+ ->asm_wasm_translation_peak_memory_bytes()
+ ->AddSample(static_cast<int>(translate_zone_size));
+ translate_time = translate_timer.Elapsed().InMillisecondsF();
+ if (FLAG_trace_asm_parser) {
+ PrintF(
+ "[asm.js translation successful: time=%0.3fms, "
+ "translate_zone=%" PRIuS "KB, compile_zone+=%" PRIuS "KB]\n",
+ translate_time, translate_zone_size / KB, compile_zone_size / KB);
}
}
- double asm_wasm_time = asm_wasm_timer.Elapsed().InMillisecondsF();
- Vector<const byte> asm_offsets_vec(asm_offsets->begin(),
- static_cast<int>(asm_offsets->size()));
-
- base::ElapsedTimer compile_timer;
- compile_timer.Start();
- ErrorThrower thrower(info->isolate(), "Asm.js -> WebAssembly conversion");
- MaybeHandle<JSObject> compiled = SyncCompileTranslatedAsmJs(
- info->isolate(), &thrower,
- wasm::ModuleWireBytes(module->begin(), module->end()), info->script(),
- asm_offsets_vec);
- DCHECK(!compiled.is_null());
- DCHECK(!thrower.error());
- double compile_time = compile_timer.Elapsed().InMillisecondsF();
- DCHECK_GE(module->end(), module->begin());
- uintptr_t wasm_size = module->end() - module->begin();
+ // Step 2: Compile and decode the WebAssembly module.
+ {
+ base::ElapsedTimer compile_timer;
+ compile_timer.Start();
+ wasm::ErrorThrower thrower(info->isolate(), "AsmJs::Compile");
+ MaybeHandle<WasmModuleObject> maybe_compiled = SyncCompileTranslatedAsmJs(
+ info->isolate(), &thrower,
+ wasm::ModuleWireBytes(module->begin(), module->end()), info->script(),
+ Vector<const byte>(asm_offsets->begin(), asm_offsets->size()));
+ DCHECK(!maybe_compiled.is_null());
+ DCHECK(!thrower.error());
+ compile_time = compile_timer.Elapsed().InMillisecondsF();
+ compiled = maybe_compiled.ToHandleChecked();
+ }
+ // The result is a compiled module and serialized standard library uses.
Handle<FixedArray> result =
info->isolate()->factory()->NewFixedArray(kWasmDataEntryCount);
- result->set(kWasmDataCompiledModule, *compiled.ToHandleChecked());
- result->set(kWasmDataForeignGlobals, *foreign_globals);
+ result->set(kWasmDataCompiledModule, *compiled);
result->set(kWasmDataUsesArray, *uses_array);
- result->set(kWasmDataScript, *info->script());
- result->set(kWasmDataScriptPosition,
- Smi::FromInt(info->literal()->position()));
-
- MessageLocation location(info->script(), info->literal()->position(),
- info->literal()->position());
- char text[100];
- int length;
- if (FLAG_predictable) {
- length = base::OS::SNPrintF(text, arraysize(text), "success");
- } else {
- length = base::OS::SNPrintF(
- text, arraysize(text),
- "success, asm->wasm: %0.3f ms, compile: %0.3f ms, %" PRIuPTR " bytes",
- asm_wasm_time, compile_time, wasm_size);
- }
- DCHECK_NE(-1, length);
- USE(length);
- Handle<String> stext(info->isolate()->factory()->InternalizeUtf8String(text));
- Handle<JSMessageObject> message = MessageHandler::MakeMessageObject(
- info->isolate(), MessageTemplate::kAsmJsCompiled, &location, stext,
- Handle<JSArray>::null());
- message->set_error_level(v8::Isolate::kMessageInfo);
- if (!FLAG_suppress_asm_messages && FLAG_trace_asm_time) {
- MessageHandler::ReportMessage(info->isolate(), &location, message);
- }
-
+ ReportCompilationSuccess(info->script(), info->literal()->position(),
+ translate_time, compile_time, module->size());
return result;
}
-bool AsmJs::IsStdlibValid(i::Isolate* isolate, Handle<FixedArray> wasm_data,
- Handle<JSReceiver> stdlib) {
- i::Handle<i::FixedArray> uses(
- i::FixedArray::cast(wasm_data->get(kWasmDataUsesArray)));
- for (int i = 0; i < uses->length(); ++i) {
- if (!IsStdlibMemberValid(isolate, stdlib,
- uses->GetValueChecked<i::Object>(isolate, i))) {
- return false;
- }
- }
- return true;
-}
-
-MaybeHandle<Object> AsmJs::InstantiateAsmWasm(i::Isolate* isolate,
+MaybeHandle<Object> AsmJs::InstantiateAsmWasm(Isolate* isolate,
+ Handle<SharedFunctionInfo> shared,
Handle<FixedArray> wasm_data,
- Handle<JSArrayBuffer> memory,
- Handle<JSReceiver> foreign) {
+ Handle<JSReceiver> stdlib,
+ Handle<JSReceiver> foreign,
+ Handle<JSArrayBuffer> memory) {
base::ElapsedTimer instantiate_timer;
instantiate_timer.Start();
- i::Handle<i::WasmModuleObject> module(
- i::WasmModuleObject::cast(wasm_data->get(kWasmDataCompiledModule)));
- i::Handle<i::FixedArray> foreign_globals(
- i::FixedArray::cast(wasm_data->get(kWasmDataForeignGlobals)));
+ Handle<FixedArray> stdlib_uses(
+ FixedArray::cast(wasm_data->get(kWasmDataUsesArray)));
+ Handle<WasmModuleObject> module(
+ WasmModuleObject::cast(wasm_data->get(kWasmDataCompiledModule)));
+ Handle<Script> script(Script::cast(shared->script()));
+ // TODO(mstarzinger): The position currently points to the module definition
+ // but should instead point to the instantiation site (more intuitive).
+ int position = shared->start_position();
+
+ // Check that all used stdlib members are valid.
+ bool stdlib_use_of_typed_array_present = false;
+ for (int i = 0; i < stdlib_uses->length(); ++i) {
+ if (stdlib.is_null()) {
+ ReportInstantiationFailure(script, position, "Requires standard library");
+ return MaybeHandle<Object>();
+ }
+ int member_id = Smi::cast(stdlib_uses->get(i))->value();
+ wasm::AsmJsParser::StandardMember member =
+ static_cast<wasm::AsmJsParser::StandardMember>(member_id);
+ if (!IsStdlibMemberValid(isolate, stdlib, member,
+ &stdlib_use_of_typed_array_present)) {
+ ReportInstantiationFailure(script, position, "Unexpected stdlib member");
+ return MaybeHandle<Object>();
+ }
+ }
// Create the ffi object for foreign functions {"": foreign}.
Handle<JSObject> ffi_object;
@@ -318,85 +297,47 @@ MaybeHandle<Object> AsmJs::InstantiateAsmWasm(i::Isolate* isolate,
foreign, NONE);
}
- ErrorThrower thrower(isolate, "Asm.js -> WebAssembly instantiation");
- i::MaybeHandle<i::Object> maybe_module_object =
- i::wasm::SyncInstantiate(isolate, &thrower, module, ffi_object, memory);
+ // Check that a valid heap buffer is provided if required.
+ if (stdlib_use_of_typed_array_present) {
+ if (memory.is_null()) {
+ ReportInstantiationFailure(script, position, "Requires heap buffer");
+ return MaybeHandle<Object>();
+ }
+ size_t size = NumberToSize(memory->byte_length());
+ // TODO(mstarzinger): We currently only limit byte length of the buffer to
+ // be a multiple of 8, we should enforce the stricter spec limits here.
+ if (size % FixedTypedArrayBase::kMaxElementSize != 0) {
+ ReportInstantiationFailure(script, position, "Unexpected heap size");
+ return MaybeHandle<Object>();
+ }
+ }
+
+ wasm::ErrorThrower thrower(isolate, "AsmJs::Instantiate");
+ MaybeHandle<Object> maybe_module_object =
+ wasm::SyncInstantiate(isolate, &thrower, module, ffi_object, memory);
if (maybe_module_object.is_null()) {
- thrower.Reify(); // Ensure exceptions do not propagate.
+ thrower.Reset(); // Ensure exceptions do not propagate.
+ ReportInstantiationFailure(script, position, "Internal wasm failure");
return MaybeHandle<Object>();
}
DCHECK(!thrower.error());
- i::Handle<i::Object> module_object = maybe_module_object.ToHandleChecked();
+ Handle<Object> module_object = maybe_module_object.ToHandleChecked();
- if (!FLAG_fast_validate_asm) {
- i::Handle<i::Name> init_name(isolate->factory()->InternalizeUtf8String(
- wasm::AsmWasmBuilder::foreign_init_name));
- i::Handle<i::Object> init =
- i::Object::GetProperty(module_object, init_name).ToHandleChecked();
+ ReportInstantiationSuccess(script, position,
+ instantiate_timer.Elapsed().InMillisecondsF());
- i::Handle<i::Object> undefined(isolate->heap()->undefined_value(), isolate);
- i::Handle<i::Object>* foreign_args_array =
- new i::Handle<i::Object>[foreign_globals->length()];
- for (int j = 0; j < foreign_globals->length(); j++) {
- if (!foreign.is_null()) {
- i::MaybeHandle<i::Name> name = i::Object::ToName(
- isolate, i::Handle<i::Object>(foreign_globals->get(j), isolate));
- if (!name.is_null()) {
- i::MaybeHandle<i::Object> val =
- i::Object::GetProperty(foreign, name.ToHandleChecked());
- if (!val.is_null()) {
- foreign_args_array[j] = val.ToHandleChecked();
- continue;
- }
- }
- }
- foreign_args_array[j] = undefined;
- }
- i::MaybeHandle<i::Object> retval =
- i::Execution::Call(isolate, init, undefined, foreign_globals->length(),
- foreign_args_array);
- delete[] foreign_args_array;
- DCHECK(!retval.is_null());
- }
-
- i::Handle<i::Name> single_function_name(
- isolate->factory()->InternalizeUtf8String(
- wasm::AsmWasmBuilder::single_function_name));
- i::MaybeHandle<i::Object> single_function =
- i::Object::GetProperty(module_object, single_function_name);
+ Handle<Name> single_function_name(
+ isolate->factory()->InternalizeUtf8String(AsmJs::kSingleFunctionName));
+ MaybeHandle<Object> single_function =
+ Object::GetProperty(module_object, single_function_name);
if (!single_function.is_null() &&
!single_function.ToHandleChecked()->IsUndefined(isolate)) {
return single_function;
}
- i::Handle<i::Script> script(i::Script::cast(wasm_data->get(kWasmDataScript)));
- int32_t position = 0;
- if (!wasm_data->get(kWasmDataScriptPosition)->ToInt32(&position)) {
- UNREACHABLE();
- }
- MessageLocation location(script, position, position);
- char text[50];
- int length;
- if (FLAG_predictable) {
- length = base::OS::SNPrintF(text, arraysize(text), "success");
- } else {
- length = base::OS::SNPrintF(text, arraysize(text), "success, %0.3f ms",
- instantiate_timer.Elapsed().InMillisecondsF());
- }
- DCHECK_NE(-1, length);
- USE(length);
- Handle<String> stext(isolate->factory()->InternalizeUtf8String(text));
- Handle<JSMessageObject> message = MessageHandler::MakeMessageObject(
- isolate, MessageTemplate::kAsmJsInstantiated, &location, stext,
- Handle<JSArray>::null());
- message->set_error_level(v8::Isolate::kMessageInfo);
- if (!FLAG_suppress_asm_messages && FLAG_trace_asm_time) {
- MessageHandler::ReportMessage(isolate, &location, message);
- }
-
Handle<String> exports_name =
isolate->factory()->InternalizeUtf8String("exports");
- return i::Object::GetProperty(module_object, exports_name);
+ return Object::GetProperty(module_object, exports_name);
}
} // namespace internal