wasm-js.cc revision 13e2dadd00298019ed862f2b2fc5068bba730bcf
1014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Copyright 2015 the V8 project authors. All rights reserved.
2014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// found in the LICENSE file.
4014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/api-natives.h"
613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include "src/api.h"
7014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/assert-scope.h"
8014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/ast/ast.h"
9014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/ast/scopes.h"
1013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include "src/execution.h"
11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/factory.h"
12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/handles.h"
13014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/isolate.h"
14014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/objects.h"
15014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/parsing/parser.h"
16014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/typing-asm.h"
17014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
18014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/wasm/asm-wasm-builder.h"
19014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/wasm/encoder.h"
20014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/wasm/module-decoder.h"
21014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/wasm/wasm-js.h"
22014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/wasm/wasm-module.h"
23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/wasm/wasm-result.h"
24014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
25014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochtypedef uint8_t byte;
26014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochusing v8::internal::wasm::ErrorThrower;
28014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
29014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace v8 {
30014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
31014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace {
32014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstruct RawBuffer {
33014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const byte* start;
34014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const byte* end;
35014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  size_t size() { return static_cast<size_t>(end - start); }
36014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch};
37014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3813e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochRawBuffer GetRawBufferSource(
3913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    v8::Local<v8::Value> source, ErrorThrower* thrower) {
403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  const byte* start = nullptr;
413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  const byte* end = nullptr;
42014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (source->IsArrayBuffer()) {
443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // A raw array buffer was passed.
4513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(source);
463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    ArrayBuffer::Contents contents = buffer->GetContents();
473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    start = reinterpret_cast<const byte*>(contents.Data());
493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    end = start + contents.ByteLength();
503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (start == nullptr || end == start) {
5213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      thrower->Error("ArrayBuffer argument is empty");
533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
5413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else if (source->IsTypedArray()) {
553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // A TypedArray was passed.
5613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    Local<TypedArray> array = Local<TypedArray>::Cast(source);
573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Local<ArrayBuffer> buffer = array->Buffer();
583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    ArrayBuffer::Contents contents = buffer->GetContents();
603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    start =
623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        reinterpret_cast<const byte*>(contents.Data()) + array->ByteOffset();
633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    end = start + array->ByteLength();
643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (start == nullptr || end == start) {
6613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      thrower->Error("ArrayBuffer argument is empty");
673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
6913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    thrower->Error("Argument 0 must be an ArrayBuffer or Uint8Array");
70014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
72014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return {start, end};
73014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
74014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
75014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid VerifyModule(const v8::FunctionCallbackInfo<v8::Value>& args) {
76014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  HandleScope scope(args.GetIsolate());
77014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate());
7813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  ErrorThrower thrower(isolate, "Wasm.verifyModule()");
79014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
8013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (args.Length() < 1) {
8113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    thrower.Error("Argument 0 must be a buffer source");
8213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return;
8313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
8413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  RawBuffer buffer = GetRawBufferSource(args[0], &thrower);
85014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (thrower.error()) return;
86014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  i::Zone zone(isolate->allocator());
883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  internal::wasm::ModuleResult result =
893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      internal::wasm::DecodeWasmModule(isolate, &zone, buffer.start, buffer.end,
903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                       true, internal::wasm::kWasmOrigin);
91014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
92014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (result.failed()) {
93014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    thrower.Failed("", result);
94014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
95014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
96014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (result.val) delete result.val;
97014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
98014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
99014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid VerifyFunction(const v8::FunctionCallbackInfo<v8::Value>& args) {
100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  HandleScope scope(args.GetIsolate());
101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate());
10213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  ErrorThrower thrower(isolate, "Wasm.verifyFunction()");
103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
10413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (args.Length() < 1) {
10513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    thrower.Error("Argument 0 must be a buffer source");
10613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return;
10713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
10813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  RawBuffer buffer = GetRawBufferSource(args[0], &thrower);
109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (thrower.error()) return;
110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  internal::wasm::FunctionResult result;
112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  {
113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Verification of a single function shouldn't allocate.
114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    i::DisallowHeapAllocation no_allocation;
1153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    i::Zone zone(isolate->allocator());
116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    result = internal::wasm::DecodeWasmFunction(isolate, &zone, nullptr,
117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                buffer.start, buffer.end);
118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (result.failed()) {
121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    thrower.Failed("", result);
122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (result.val) delete result.val;
125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
12713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochv8::internal::wasm::ZoneBuffer* TranslateAsmModule(
12813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    i::ParseInfo* info, ErrorThrower* thrower,
12913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    i::Handle<i::FixedArray>* foreign_args) {
130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  info->set_global();
131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  info->set_lazy(false);
132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  info->set_allow_lazy_parsing(false);
133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  info->set_toplevel(true);
134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!i::Compiler::ParseAndAnalyze(info)) {
136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return nullptr;
137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
139bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (info->scope()->declarations()->length() == 0) {
140bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    thrower->Error("Asm.js validation failed: no declarations in scope");
141bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    return nullptr;
142bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
143bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  info->set_literal(
145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      info->scope()->declarations()->at(0)->AsFunctionDeclaration()->fun());
146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  v8::internal::AsmTyper typer(info->isolate(), info->zone(), *(info->script()),
148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                               info->literal());
149109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (i::FLAG_enable_simd_asmjs) {
150109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    typer.set_allow_simd(true);
151109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!typer.Validate()) {
153109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    thrower->Error("Asm.js validation failed: %s", typer.error_message());
154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return nullptr;
155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
15713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  v8::internal::wasm::AsmWasmBuilder builder(info->isolate(), info->zone(),
15813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                             info->literal(), &typer);
159109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
16013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return builder.Run(foreign_args);
161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
16313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochi::MaybeHandle<i::JSObject> InstantiateModuleCommon(
16413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& args, const byte* start,
16513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    const byte* end, ErrorThrower* thrower,
16613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    internal::wasm::ModuleOrigin origin = i::wasm::kWasmOrigin) {
167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate());
168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
169109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Decode but avoid a redundant pass over function bodies for verification.
170109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Verification will happen during compilation.
1713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  i::Zone zone(isolate->allocator());
172109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  internal::wasm::ModuleResult result = internal::wasm::DecodeWasmModule(
1733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      isolate, &zone, start, end, false, origin);
1748389745919cae02139ddc085a63c00d024269cf2Ben Murdoch
17513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  i::MaybeHandle<i::JSObject> object;
1763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (result.failed() && origin == internal::wasm::kAsmJsOrigin) {
177109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    thrower->Error("Asm.js converted module failed to decode");
178109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  } else if (result.failed()) {
179109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    thrower->Failed("", result);
180109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  } else {
181109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // Success. Instantiate the module and return the object.
182bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    i::Handle<i::JSReceiver> ffi = i::Handle<i::JSObject>::null();
183109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    if (args.Length() > 1 && args[1]->IsObject()) {
184109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      Local<Object> obj = Local<Object>::Cast(args[1]);
185bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      ffi = i::Handle<i::JSReceiver>::cast(v8::Utils::OpenHandle(*obj));
186109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
187109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
18813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    i::Handle<i::JSArrayBuffer> memory = i::Handle<i::JSArrayBuffer>::null();
18913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (args.Length() > 2 && args[2]->IsArrayBuffer()) {
19013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      Local<Object> obj = Local<Object>::Cast(args[2]);
19113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      i::Handle<i::Object> mem_obj = v8::Utils::OpenHandle(*obj);
19213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      memory = i::Handle<i::JSArrayBuffer>(i::JSArrayBuffer::cast(*mem_obj));
19313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
194109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
19513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    object = result.val->Instantiate(isolate, ffi, memory);
196109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    if (!object.is_null()) {
197109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      args.GetReturnValue().Set(v8::Utils::ToLocal(object.ToHandleChecked()));
198109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
201109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (result.val) delete result.val;
20213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return object;
203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid InstantiateModuleFromAsm(const v8::FunctionCallbackInfo<v8::Value>& args) {
206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  HandleScope scope(args.GetIsolate());
207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate());
20813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  ErrorThrower thrower(isolate, "Wasm.instantiateModuleFromAsm()");
209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!args[0]->IsString()) {
211109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    thrower.Error("Asm module text should be a string");
212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return;
213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  i::Factory* factory = isolate->factory();
2163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  i::Zone zone(isolate->allocator());
217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Local<String> source = Local<String>::Cast(args[0]);
218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  i::Handle<i::Script> script = factory->NewScript(Utils::OpenHandle(*source));
219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  i::ParseInfo info(&zone, script);
220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
221109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  i::Handle<i::Object> foreign;
222109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (args.Length() > 1 && args[1]->IsObject()) {
223109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Local<Object> local_foreign = Local<Object>::Cast(args[1]);
224109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    foreign = v8::Utils::OpenHandle(*local_foreign);
225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
22713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  i::Handle<i::FixedArray> foreign_args;
22813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  auto module = TranslateAsmModule(&info, &thrower, &foreign_args);
229109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (module == nullptr) {
230109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    return;
231f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch  }
232f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch
23313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  i::MaybeHandle<i::Object> maybe_module_object =
23413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      InstantiateModuleCommon(args, module->begin(), module->end(), &thrower,
23513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                              internal::wasm::kAsmJsOrigin);
23613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (maybe_module_object.is_null()) {
23713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return;
23813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
23913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
24013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  i::Handle<i::Name> name =
24113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      factory->NewStringFromStaticChars("__foreign_init__");
24213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
24313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  i::Handle<i::Object> module_object = maybe_module_object.ToHandleChecked();
24413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  i::MaybeHandle<i::Object> maybe_init =
24513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      i::Object::GetProperty(module_object, name);
24613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK(!maybe_init.is_null());
24713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
24813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  i::Handle<i::Object> init = maybe_init.ToHandleChecked();
24913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  i::Handle<i::Object> undefined = isolate->factory()->undefined_value();
25013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  i::Handle<i::Object>* foreign_args_array =
25113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      new i::Handle<i::Object>[foreign_args->length()];
25213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  for (int j = 0; j < foreign_args->length(); j++) {
25313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (!foreign.is_null()) {
25413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      i::MaybeHandle<i::Name> name = i::Object::ToName(
25513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          isolate, i::Handle<i::Object>(foreign_args->get(j), isolate));
25613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      if (!name.is_null()) {
25713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        i::MaybeHandle<i::Object> val =
25813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch            i::Object::GetProperty(foreign, name.ToHandleChecked());
25913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        if (!val.is_null()) {
26013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          foreign_args_array[j] = val.ToHandleChecked();
26113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          continue;
26213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        }
26313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      }
26413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
26513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    foreign_args_array[j] = undefined;
26613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
26713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  i::MaybeHandle<i::Object> retval = i::Execution::Call(
26813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      isolate, init, undefined, foreign_args->length(), foreign_args_array);
26913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  delete[] foreign_args_array;
27013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
27113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (retval.is_null()) {
27213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    thrower.Error(
27313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        "WASM.instantiateModuleFromAsm(): foreign init function failed");
27413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
277014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid InstantiateModule(const v8::FunctionCallbackInfo<v8::Value>& args) {
278014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  HandleScope scope(args.GetIsolate());
279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate());
28013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  ErrorThrower thrower(isolate, "Wasm.instantiateModule()");
281014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
28213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (args.Length() < 1) {
28313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    thrower.Error("Argument 0 must be a buffer source");
28413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return;
28513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
28613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  RawBuffer buffer = GetRawBufferSource(args[0], &thrower);
287014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (buffer.start == nullptr) return;
288014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
28913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  InstantiateModuleCommon(args, buffer.start, buffer.end, &thrower);
29013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
29113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
29213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
29313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochstatic i::MaybeHandle<i::JSObject> CreateModuleObject(
29413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    v8::Isolate* isolate, const v8::Local<v8::Value> source,
29513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    ErrorThrower* thrower) {
29613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
29713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
29813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  RawBuffer buffer = GetRawBufferSource(source, thrower);
29913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (buffer.start == nullptr) return i::MaybeHandle<i::JSObject>();
30013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
30113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // TODO(rossberg): Once we can, do compilation here.
30213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK(source->IsArrayBuffer() || source->IsTypedArray());
30313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Local<Context> context = isolate->GetCurrentContext();
30413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  i::Handle<i::Context> i_context = Utils::OpenHandle(*context);
30513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  i::Handle<i::JSFunction> module_cons(i_context->wasm_module_constructor());
30613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  i::Handle<i::JSObject> module_obj =
30713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      i_isolate->factory()->NewJSObject(module_cons);
30813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  i::Handle<i::Object> module_ref = Utils::OpenHandle(*source);
30913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  i::Handle<i::Symbol> module_sym(i_context->wasm_module_sym());
31013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  i::Object::SetProperty(module_obj, module_sym, module_ref, i::STRICT).Check();
31113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
31213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return module_obj;
31313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
31413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
31513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid WebAssemblyCompile(const v8::FunctionCallbackInfo<v8::Value>& args) {
31613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  v8::Isolate* isolate = args.GetIsolate();
31713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  HandleScope scope(isolate);
31813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate),
31913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                       "WebAssembly.compile()");
32013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
32113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (args.Length() < 1) {
32213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    thrower.Error("Argument 0 must be a buffer source");
32313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return;
32413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
32513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  i::MaybeHandle<i::JSObject> module_obj =
32613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      CreateModuleObject(isolate, args[0], &thrower);
32713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (module_obj.is_null()) return;
32813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
32913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Local<Context> context = isolate->GetCurrentContext();
33013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  v8::Local<v8::Promise::Resolver> resolver;
33113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (!v8::Promise::Resolver::New(context).ToLocal(&resolver)) return;
33213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  resolver->Resolve(context, Utils::ToLocal(module_obj.ToHandleChecked()));
33313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
33413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
33513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return_value.Set(resolver->GetPromise());
33613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
33713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
33813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid WebAssemblyModule(const v8::FunctionCallbackInfo<v8::Value>& args) {
33913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  v8::Isolate* isolate = args.GetIsolate();
34013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  HandleScope scope(isolate);
34113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate),
34213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                       "WebAssembly.Module()");
34313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
34413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (args.Length() < 1) {
34513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    thrower.Error("Argument 0 must be a buffer source");
34613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return;
34713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
34813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  i::MaybeHandle<i::JSObject> module_obj =
34913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      CreateModuleObject(isolate, args[0], &thrower);
35013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (module_obj.is_null()) return;
35113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
35213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
35313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return_value.Set(Utils::ToLocal(module_obj.ToHandleChecked()));
35413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
35513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
35613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) {
35713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  HandleScope scope(args.GetIsolate());
35813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  v8::Isolate* isolate = args.GetIsolate();
35913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate),
36013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                       "WebAssembly.Instance()");
36113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
36213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (args.Length() < 1) {
36313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    thrower.Error("Argument 0 must be a WebAssembly.Module");
36413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return;
36513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
36613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Local<Context> context = isolate->GetCurrentContext();
36713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  i::Handle<i::Context> i_context = Utils::OpenHandle(*context);
36813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  i::Handle<i::Symbol> module_sym(i_context->wasm_module_sym());
36913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  i::MaybeHandle<i::Object> source =
37013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      i::Object::GetProperty(Utils::OpenHandle(*args[0]), module_sym);
37113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (source.is_null()) return;
37213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
37313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  RawBuffer buffer =
37413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      GetRawBufferSource(Utils::ToLocal(source.ToHandleChecked()), &thrower);
37513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (buffer.start == nullptr) return;
37613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
37713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  InstantiateModuleCommon(args, buffer.start, buffer.end, &thrower);
378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
379014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace
380014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
381014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// TODO(titzer): we use the API to create the function template because the
382014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// internal guts are too ugly to replicate here.
383014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic i::Handle<i::FunctionTemplateInfo> NewTemplate(i::Isolate* i_isolate,
384014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                      FunctionCallback func) {
385014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate);
386014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Local<FunctionTemplate> local = FunctionTemplate::New(isolate, func);
387014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return v8::Utils::OpenHandle(*local);
388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
389014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
390014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace internal {
391014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic Handle<String> v8_str(Isolate* isolate, const char* str) {
392014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return isolate->factory()->NewStringFromAsciiChecked(str);
393014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
394014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
39513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochstatic Handle<JSFunction> InstallFunc(Isolate* isolate, Handle<JSObject> object,
39613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                      const char* str, FunctionCallback func) {
397014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Handle<String> name = v8_str(isolate, str);
398014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Handle<FunctionTemplateInfo> temp = NewTemplate(isolate, func);
399014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Handle<JSFunction> function =
400014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ApiNatives::InstantiateFunction(temp).ToHandleChecked();
401014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  PropertyAttributes attributes =
402014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
403014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  JSObject::AddProperty(object, name, function, attributes);
40413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return function;
405014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
406014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
407014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid WasmJs::Install(Isolate* isolate, Handle<JSGlobalObject> global) {
40813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Factory* factory = isolate->factory();
40913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
410014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Setup wasm function map.
411014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Handle<Context> context(global->native_context(), isolate);
412014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InstallWasmFunctionMap(isolate, context);
413014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
41413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Bind the experimental WASM object.
41513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // TODO(rossberg, titzer): remove once it's no longer needed.
41613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  {
41713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    Handle<String> name = v8_str(isolate, "Wasm");
41813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    Handle<JSFunction> cons = factory->NewFunction(name);
41913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    JSFunction::SetInstancePrototype(
42013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        cons, Handle<Object>(context->initial_object_prototype(), isolate));
42113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    cons->shared()->set_instance_class_name(*name);
42213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    Handle<JSObject> wasm_object = factory->NewJSObject(cons, TENURED);
42313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    PropertyAttributes attributes = static_cast<PropertyAttributes>(DONT_ENUM);
42413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    JSObject::AddProperty(global, name, wasm_object, attributes);
42513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
42613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // Install functions on the WASM object.
42713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    InstallFunc(isolate, wasm_object, "verifyModule", VerifyModule);
42813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    InstallFunc(isolate, wasm_object, "verifyFunction", VerifyFunction);
42913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    InstallFunc(isolate, wasm_object, "instantiateModule", InstantiateModule);
43013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    InstallFunc(isolate, wasm_object, "instantiateModuleFromAsm",
43113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                InstantiateModuleFromAsm);
43213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
43313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    {
43413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      // Add the Wasm.experimentalVersion property.
43513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      Handle<String> name = v8_str(isolate, "experimentalVersion");
43613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      PropertyAttributes attributes =
43713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
43813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      Handle<Smi> value =
43913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          Handle<Smi>(Smi::FromInt(wasm::kWasmVersion), isolate);
44013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      JSObject::AddProperty(wasm_object, name, value, attributes);
44113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
44213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
44313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
44413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Create private symbols.
44513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Handle<Symbol> module_sym = isolate->factory()->NewPrivateSymbol();
44613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Handle<Symbol> instance_sym = isolate->factory()->NewPrivateSymbol();
44713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  context->set_wasm_module_sym(*module_sym);
44813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  context->set_wasm_instance_sym(*instance_sym);
44913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
45013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Bind the WebAssembly object.
45113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Handle<String> name = v8_str(isolate, "WebAssembly");
452014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Handle<JSFunction> cons = factory->NewFunction(name);
453014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  JSFunction::SetInstancePrototype(
454014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      cons, Handle<Object>(context->initial_object_prototype(), isolate));
455014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  cons->shared()->set_instance_class_name(*name);
456014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Handle<JSObject> wasm_object = factory->NewJSObject(cons, TENURED);
457014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  PropertyAttributes attributes = static_cast<PropertyAttributes>(DONT_ENUM);
458014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  JSObject::AddProperty(global, name, wasm_object, attributes);
459014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
46013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Install static methods on WebAssembly object.
46113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  InstallFunc(isolate, wasm_object, "compile", WebAssemblyCompile);
46213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Handle<JSFunction> module_constructor =
46313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      InstallFunc(isolate, wasm_object, "Module", WebAssemblyModule);
46413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Handle<JSFunction> instance_constructor =
46513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      InstallFunc(isolate, wasm_object, "Instance", WebAssemblyInstance);
46613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  context->set_wasm_module_constructor(*module_constructor);
46713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  context->set_wasm_instance_constructor(*instance_constructor);
468bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
469014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
470014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid WasmJs::InstallWasmFunctionMap(Isolate* isolate, Handle<Context> context) {
471014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!context->get(Context::WASM_FUNCTION_MAP_INDEX)->IsMap()) {
4723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // TODO(titzer): Move this to bootstrapper.cc??
4733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // TODO(titzer): Also make one for strict mode functions?
4743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Handle<Map> prev_map = Handle<Map>(context->sloppy_function_map(), isolate);
4753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
4763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    InstanceType instance_type = prev_map->instance_type();
4773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    int internal_fields = JSObject::GetInternalFieldCount(*prev_map);
4783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    CHECK_EQ(0, internal_fields);
4793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    int pre_allocated =
4803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        prev_map->GetInObjectProperties() - prev_map->unused_property_fields();
4813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    int instance_size;
4823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    int in_object_properties;
4833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    JSFunction::CalculateInstanceSizeHelper(instance_type, internal_fields + 1,
4843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                            0, &instance_size,
4853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                            &in_object_properties);
4863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
4873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    int unused_property_fields = in_object_properties - pre_allocated;
4883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    Handle<Map> map = Map::CopyInitialMap(
4893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        prev_map, instance_size, in_object_properties, unused_property_fields);
4903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
4913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    context->set_wasm_function_map(*map);
492014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
493014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
494014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
495014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
496014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
497