1f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// Copyright 2015 the V8 project authors. All rights reserved.
2f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// found in the LICENSE file.
4f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
5f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/asmjs/asm-js.h"
6f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
7f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/api-natives.h"
8f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/api.h"
9f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/asmjs/asm-typer.h"
10f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/asmjs/asm-wasm-builder.h"
11f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/assert-scope.h"
12f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/execution.h"
13f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/factory.h"
14f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/handles.h"
15f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/isolate.h"
16f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/objects.h"
17f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/parsing/parse-info.h"
18f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
19f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/wasm/module-decoder.h"
20f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/wasm/wasm-js.h"
21f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include "src/wasm/wasm-module-builder.h"
22f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/wasm/wasm-module.h"
23c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch#include "src/wasm/wasm-objects.h"
24f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/wasm/wasm-result.h"
25f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
26f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochtypedef uint8_t byte;
27f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
28f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochusing v8::internal::wasm::ErrorThrower;
29f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
30f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochnamespace v8 {
31f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochnamespace internal {
32f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
33f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochnamespace {
34f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochHandle<i::Object> StdlibMathMember(i::Isolate* isolate,
35f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                   Handle<JSReceiver> stdlib,
36f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                   Handle<Name> name) {
37f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (stdlib.is_null()) {
38f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return Handle<i::Object>();
39f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
40f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Handle<i::Name> math_name(
41f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("Math")));
42f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  MaybeHandle<i::Object> maybe_math = i::Object::GetProperty(stdlib, math_name);
43f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (maybe_math.is_null()) {
44f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return Handle<i::Object>();
45f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
46f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Handle<i::Object> math = maybe_math.ToHandleChecked();
47f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (!math->IsJSReceiver()) {
48f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return Handle<i::Object>();
49f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
50f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  MaybeHandle<i::Object> maybe_value = i::Object::GetProperty(math, name);
51f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (maybe_value.is_null()) {
52f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return Handle<i::Object>();
53f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
54f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return maybe_value.ToHandleChecked();
55f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
56f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
57f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochbool IsStdlibMemberValid(i::Isolate* isolate, Handle<JSReceiver> stdlib,
58f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                         Handle<i::Object> member_id) {
59f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  int32_t member_kind;
60f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (!member_id->ToInt32(&member_kind)) {
61f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    UNREACHABLE();
62f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
63f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  switch (member_kind) {
64f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case wasm::AsmTyper::StandardMember::kNone:
65f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case wasm::AsmTyper::StandardMember::kModule:
66f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case wasm::AsmTyper::StandardMember::kStdlib:
67f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case wasm::AsmTyper::StandardMember::kHeap:
68f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case wasm::AsmTyper::StandardMember::kFFI: {
69f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // Nothing to check for these.
70f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return true;
71f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
72f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case wasm::AsmTyper::StandardMember::kInfinity: {
73f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      if (stdlib.is_null()) {
74f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        return false;
75f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      }
76f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Handle<i::Name> name(isolate->factory()->InternalizeOneByteString(
77f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          STATIC_CHAR_VECTOR("Infinity")));
78f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      MaybeHandle<i::Object> maybe_value = i::Object::GetProperty(stdlib, name);
79f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      if (maybe_value.is_null()) {
80f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        return false;
81f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      }
82f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Handle<i::Object> value = maybe_value.ToHandleChecked();
83f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return value->IsNumber() && std::isinf(value->Number());
84f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
85f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case wasm::AsmTyper::StandardMember::kNaN: {
86f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      if (stdlib.is_null()) {
87f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        return false;
88f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      }
89f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Handle<i::Name> name(isolate->factory()->InternalizeOneByteString(
90f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          STATIC_CHAR_VECTOR("NaN")));
91f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      MaybeHandle<i::Object> maybe_value = i::Object::GetProperty(stdlib, name);
92f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      if (maybe_value.is_null()) {
93f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        return false;
94f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      }
95f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Handle<i::Object> value = maybe_value.ToHandleChecked();
96f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return value->IsNaN();
97f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
98f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#define STDLIB_MATH_FUNC(CamelName, fname)                             \
99f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  case wasm::AsmTyper::StandardMember::k##CamelName: {                 \
100f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Handle<i::Name> name(isolate->factory()->InternalizeOneByteString( \
101f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        STATIC_CHAR_VECTOR(#fname)));                                  \
102f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Handle<i::Object> value = StdlibMathMember(isolate, stdlib, name); \
103f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (value.is_null() || !value->IsJSFunction()) {                   \
104f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return false;                                                    \
105f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }                                                                  \
106f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Handle<i::JSFunction> func(i::JSFunction::cast(*value));           \
107f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return func->shared()->code() ==                                   \
108f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch           isolate->builtins()->builtin(Builtins::k##CamelName);       \
109f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
110f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      STDLIB_MATH_FUNC(MathAcos, acos)
111f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      STDLIB_MATH_FUNC(MathAsin, asin)
112f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      STDLIB_MATH_FUNC(MathAtan, atan)
113f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      STDLIB_MATH_FUNC(MathCos, cos)
114f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      STDLIB_MATH_FUNC(MathSin, sin)
115f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      STDLIB_MATH_FUNC(MathTan, tan)
116f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      STDLIB_MATH_FUNC(MathExp, exp)
117f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      STDLIB_MATH_FUNC(MathLog, log)
118f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      STDLIB_MATH_FUNC(MathCeil, ceil)
119f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      STDLIB_MATH_FUNC(MathFloor, floor)
120f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      STDLIB_MATH_FUNC(MathSqrt, sqrt)
121f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      STDLIB_MATH_FUNC(MathAbs, abs)
122f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      STDLIB_MATH_FUNC(MathClz32, clz32)
123f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      STDLIB_MATH_FUNC(MathMin, min)
124f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      STDLIB_MATH_FUNC(MathMax, max)
125f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      STDLIB_MATH_FUNC(MathAtan2, atan2)
126f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      STDLIB_MATH_FUNC(MathPow, pow)
127f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      STDLIB_MATH_FUNC(MathImul, imul)
128f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      STDLIB_MATH_FUNC(MathFround, fround)
129f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#undef STDLIB_MATH_FUNC
130f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#define STDLIB_MATH_CONST(cname, const_value)                             \
131f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  case wasm::AsmTyper::StandardMember::kMath##cname: {                    \
132f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    i::Handle<i::Name> name(isolate->factory()->InternalizeOneByteString( \
133f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        STATIC_CHAR_VECTOR(#cname)));                                     \
134f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    i::Handle<i::Object> value = StdlibMathMember(isolate, stdlib, name); \
135f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return !value.is_null() && value->IsNumber() &&                       \
136f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch           value->Number() == const_value;                                \
137f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
138f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      STDLIB_MATH_CONST(E, 2.718281828459045)
139f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      STDLIB_MATH_CONST(LN10, 2.302585092994046)
140f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      STDLIB_MATH_CONST(LN2, 0.6931471805599453)
141f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      STDLIB_MATH_CONST(LOG2E, 1.4426950408889634)
142f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      STDLIB_MATH_CONST(LOG10E, 0.4342944819032518)
143f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      STDLIB_MATH_CONST(PI, 3.141592653589793)
144f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      STDLIB_MATH_CONST(SQRT1_2, 0.7071067811865476)
145f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      STDLIB_MATH_CONST(SQRT2, 1.4142135623730951)
146f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#undef STDLIB_MATH_CONST
147f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    default: { UNREACHABLE(); }
148f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
149f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return false;
150f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
151f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
152f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}  // namespace
153f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
154f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochMaybeHandle<FixedArray> AsmJs::ConvertAsmToWasm(ParseInfo* info) {
155f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  ErrorThrower thrower(info->isolate(), "Asm.js -> WebAssembly conversion");
156f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  wasm::AsmTyper typer(info->isolate(), info->zone(), *(info->script()),
157f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                       info->literal());
158f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (!typer.Validate()) {
159f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DCHECK(!info->isolate()->has_pending_exception());
160f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    PrintF("Validation of asm.js module failed: %s", typer.error_message());
161f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return MaybeHandle<FixedArray>();
162f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
163f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  v8::internal::wasm::AsmWasmBuilder builder(info->isolate(), info->zone(),
164f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                             info->literal(), &typer);
165f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  i::Handle<i::FixedArray> foreign_globals;
166c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  auto asm_wasm_result = builder.Run(&foreign_globals);
167c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  wasm::ZoneBuffer* module = asm_wasm_result.module_bytes;
168c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  wasm::ZoneBuffer* asm_offsets = asm_wasm_result.asm_offset_table;
169f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
170f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  i::MaybeHandle<i::JSObject> compiled = wasm::CreateModuleObjectFromBytes(
171f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      info->isolate(), module->begin(), module->end(), &thrower,
172c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      internal::wasm::kAsmJsOrigin, info->script(), asm_offsets->begin(),
173c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      asm_offsets->end());
174f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(!compiled.is_null());
175f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
176f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  wasm::AsmTyper::StdlibSet uses = typer.StdlibUses();
177f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Handle<FixedArray> uses_array =
178f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      info->isolate()->factory()->NewFixedArray(static_cast<int>(uses.size()));
179f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  int count = 0;
180f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  for (auto i : uses) {
181f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    uses_array->set(count++, Smi::FromInt(i));
182f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
183f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
184f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Handle<FixedArray> result = info->isolate()->factory()->NewFixedArray(3);
185f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  result->set(0, *compiled.ToHandleChecked());
186f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  result->set(1, *foreign_globals);
187f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  result->set(2, *uses_array);
188f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return result;
189f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
190f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
191f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochbool AsmJs::IsStdlibValid(i::Isolate* isolate, Handle<FixedArray> wasm_data,
192f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                          Handle<JSReceiver> stdlib) {
193f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  i::Handle<i::FixedArray> uses(i::FixedArray::cast(wasm_data->get(2)));
194f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  for (int i = 0; i < uses->length(); ++i) {
195f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (!IsStdlibMemberValid(isolate, stdlib,
196f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                             uses->GetValueChecked<i::Object>(isolate, i))) {
197f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return false;
198f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
199f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
200f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return true;
201f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
202f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
203f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochMaybeHandle<Object> AsmJs::InstantiateAsmWasm(i::Isolate* isolate,
204f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                              Handle<FixedArray> wasm_data,
205f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                              Handle<JSArrayBuffer> memory,
206f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                              Handle<JSReceiver> foreign) {
207f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  i::Handle<i::JSObject> module(i::JSObject::cast(wasm_data->get(0)));
208f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  i::Handle<i::FixedArray> foreign_globals(
209f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      i::FixedArray::cast(wasm_data->get(1)));
210f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
211f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  ErrorThrower thrower(isolate, "Asm.js -> WebAssembly instantiation");
212f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
213f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  i::MaybeHandle<i::JSObject> maybe_module_object =
214f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      i::wasm::WasmModule::Instantiate(isolate, &thrower, module, foreign,
215f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                                       memory);
216f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (maybe_module_object.is_null()) {
217f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return MaybeHandle<Object>();
218f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
219f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
220f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  i::Handle<i::Name> init_name(isolate->factory()->InternalizeUtf8String(
221f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      wasm::AsmWasmBuilder::foreign_init_name));
222f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
223f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  i::Handle<i::Object> module_object = maybe_module_object.ToHandleChecked();
224f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  i::MaybeHandle<i::Object> maybe_init =
225f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      i::Object::GetProperty(module_object, init_name);
226f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(!maybe_init.is_null());
227f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
228f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  i::Handle<i::Object> init = maybe_init.ToHandleChecked();
229f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  i::Handle<i::Object> undefined(isolate->heap()->undefined_value(), isolate);
230f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  i::Handle<i::Object>* foreign_args_array =
231f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      new i::Handle<i::Object>[foreign_globals->length()];
232f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  for (int j = 0; j < foreign_globals->length(); j++) {
233f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (!foreign.is_null()) {
234f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      i::MaybeHandle<i::Name> name = i::Object::ToName(
235f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          isolate, i::Handle<i::Object>(foreign_globals->get(j), isolate));
236f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      if (!name.is_null()) {
237f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        i::MaybeHandle<i::Object> val =
238f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            i::Object::GetProperty(foreign, name.ToHandleChecked());
239f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        if (!val.is_null()) {
240f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          foreign_args_array[j] = val.ToHandleChecked();
241f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          continue;
242f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        }
243f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      }
244f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
245f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    foreign_args_array[j] = undefined;
246f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
247f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  i::MaybeHandle<i::Object> retval = i::Execution::Call(
248f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      isolate, init, undefined, foreign_globals->length(), foreign_args_array);
249f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  delete[] foreign_args_array;
250f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(!retval.is_null());
251f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
252f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  i::Handle<i::Name> single_function_name(
253f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      isolate->factory()->InternalizeUtf8String(
254f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          wasm::AsmWasmBuilder::single_function_name));
255f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  i::MaybeHandle<i::Object> single_function =
256f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      i::Object::GetProperty(module_object, single_function_name);
257f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if (!single_function.is_null() &&
258f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      !single_function.ToHandleChecked()->IsUndefined(isolate)) {
259f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    return single_function;
260f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
261f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  return module_object;
262f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
263f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
264f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}  // namespace internal
265f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}  // namespace v8
266