Commit 4c5b3609 authored by titzer's avatar titzer Committed by Commit bot

Initial import of v8-native WASM.

As discussed in person, this adds the code from v8-native-prototype into
V8 proper, guarded by GYP flags that do not build the code by default.
Passing wasm=on to 'make' or setting v8_wasm as a GYP flag activates
building of this code.

An additional header file is added to and exported from the compiler
directory, src/compiler/wasm-compiler.h. This exposes a limited interface
with opaque Node and Graph types to the decoder to build TF graphs, as
well as functions to compile WASM graphs.

The mjsunit tests added are blacklisted because they fail without the
WASM object exposed to JS, which is also disabled by the build config
option.

This corresponds closely to https://github.com/WebAssembly/v8-native-prototype/commit/5981e06ebc9b1e578831d03100f17ebb77970ee0, with some formatting fixes and moving some files into src/compiler.

R=mstarzinger@chromium.org, bradnelson@chromium.org
BUG=

Review URL: https://codereview.chromium.org/1504713014

Cr-Commit-Position: refs/heads/master@{#32794}
parent 38d889ec
......@@ -3,6 +3,7 @@ include_rules = [
"-src/compiler",
"+src/compiler/pipeline.h",
"+src/compiler/code-stub-assembler.h",
"+src/compiler/wasm-compiler.h",
"-src/heap",
"+src/heap/heap.h",
"+src/heap/heap-inl.h",
......
This diff is collapsed.
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_COMPILER_WASM_COMPILER_H_
#define V8_COMPILER_WASM_COMPILER_H_
// Clients of this interface shouldn't depend on lots of compiler internals.
// Do not include anything from src/compiler here!
#include "src/wasm/wasm-opcodes.h"
#include "src/zone.h"
namespace v8 {
namespace internal {
namespace compiler {
// Forward declarations for some compiler data structures.
class Node;
class JSGraph;
class Graph;
}
namespace wasm {
// Forward declarations for some WASM data structures.
struct ModuleEnv;
struct WasmFunction;
class ErrorThrower;
// Expose {Node} and {Graph} opaquely as {wasm::TFNode} and {wasm::TFGraph}.
typedef compiler::Node TFNode;
typedef compiler::JSGraph TFGraph;
}
namespace compiler {
// Compiles a single function, producing a code object.
Handle<Code> CompileWasmFunction(wasm::ErrorThrower& thrower, Isolate* isolate,
wasm::ModuleEnv* module_env,
const wasm::WasmFunction& function, int index);
// Wraps a JS function, producing a code object that can be called from WASM.
Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, wasm::ModuleEnv* module,
Handle<JSFunction> function,
uint32_t index);
// Wraps a given wasm code object, producing a JSFunction that can be called
// from JavaScript.
Handle<JSFunction> CompileJSToWasmWrapper(Isolate* isolate,
wasm::ModuleEnv* module,
Handle<String> name,
Handle<Code> wasm_code,
uint32_t index);
// Abstracts details of building TurboFan graph nodes for WASM to separate
// the WASM decoder from the internal details of TurboFan.
class WasmTrapHelper;
class WasmGraphBuilder {
public:
WasmGraphBuilder(Zone* z, JSGraph* g);
Node** Buffer(size_t count) {
if (count > cur_bufsize_) {
size_t new_size = count + cur_bufsize_ + 5;
cur_buffer_ =
reinterpret_cast<Node**>(zone_->New(new_size * sizeof(Node*)));
cur_bufsize_ = new_size;
}
return cur_buffer_;
}
//-----------------------------------------------------------------------
// Operations independent of {control} or {effect}.
//-----------------------------------------------------------------------
Node* Error();
Node* Start(unsigned params);
Node* Param(unsigned index, wasm::LocalType type);
Node* Loop(Node* entry);
Node* Terminate(Node* effect, Node* control);
Node* Merge(unsigned count, Node** controls);
Node* Phi(wasm::LocalType type, unsigned count, Node** vals, Node* control);
Node* EffectPhi(unsigned count, Node** effects, Node* control);
Node* Int32Constant(int32_t value);
Node* Int64Constant(int64_t value);
Node* Float32Constant(float value);
Node* Float64Constant(double value);
Node* Constant(Handle<Object> value);
Node* Binop(wasm::WasmOpcode opcode, Node* left, Node* right);
Node* Unop(wasm::WasmOpcode opcode, Node* input);
unsigned InputCount(Node* node);
bool IsPhiWithMerge(Node* phi, Node* merge);
void AppendToMerge(Node* merge, Node* from);
void AppendToPhi(Node* merge, Node* phi, Node* from);
//-----------------------------------------------------------------------
// Operations that read and/or write {control} and {effect}.
//-----------------------------------------------------------------------
Node* Branch(Node* cond, Node** true_node, Node** false_node);
Node* Switch(unsigned count, Node* key);
Node* IfValue(int32_t value, Node* sw);
Node* IfDefault(Node* sw);
Node* Return(unsigned count, Node** vals);
Node* ReturnVoid();
Node* Unreachable();
Node* CallDirect(uint32_t index, Node** args);
Node* CallIndirect(uint32_t index, Node** args);
void BuildJSToWasmWrapper(Handle<Code> wasm_code, wasm::FunctionSig* sig);
void BuildWasmToJSWrapper(Handle<JSFunction> function,
wasm::FunctionSig* sig);
Node* ToJS(Node* node, Node* context, wasm::LocalType type);
Node* FromJS(Node* node, Node* context, wasm::LocalType type);
Node* Invert(Node* node);
Node* FunctionTable();
//-----------------------------------------------------------------------
// Operations that concern the linear memory.
//-----------------------------------------------------------------------
Node* MemSize(uint32_t offset);
Node* LoadGlobal(uint32_t index);
Node* StoreGlobal(uint32_t index, Node* val);
Node* LoadMem(wasm::LocalType type, MachineType memtype, Node* index,
uint32_t offset);
Node* StoreMem(MachineType type, Node* index, uint32_t offset, Node* val);
static void PrintDebugName(Node* node);
Node* Control() { return *control_; }
Node* Effect() { return *effect_; }
void set_module(wasm::ModuleEnv* module) { this->module_ = module; }
void set_control_ptr(Node** control) { this->control_ = control; }
void set_effect_ptr(Node** effect) { this->effect_ = effect; }
private:
static const int kDefaultBufferSize = 16;
friend class WasmTrapHelper;
Zone* zone_;
JSGraph* jsgraph_;
wasm::ModuleEnv* module_;
Node* mem_buffer_;
Node* mem_size_;
Node* function_table_;
Node** control_;
Node** effect_;
Node** cur_buffer_;
size_t cur_bufsize_;
Node* def_buffer_[kDefaultBufferSize];
WasmTrapHelper* trap_;
// Internal helper methods.
JSGraph* jsgraph() { return jsgraph_; }
Graph* graph();
Node* String(const char* string);
Node* MemBuffer(uint32_t offset);
void BoundsCheckMem(MachineType memtype, Node* index, uint32_t offset);
Node* BuildWasmCall(wasm::FunctionSig* sig, Node** args);
Node* BuildF32CopySign(Node* left, Node* right);
Node* BuildF64CopySign(Node* left, Node* right);
Node* BuildI32Ctz(Node* input);
Node* BuildI32Popcnt(Node* input);
Node* BuildI64Ctz(Node* input);
Node* BuildI64Popcnt(Node* input);
Node** Realloc(Node** buffer, size_t count) {
Node** buf = Buffer(count);
if (buf != buffer) memcpy(buf, buffer, count * sizeof(Node*));
return buf;
}
};
} // namespace compiler
} // namespace internal
} // namespace v8
#endif // V8_COMPILER_WASM_COMPILER_H_
This diff is collapsed.
set noparent
titzer@chromium.org
bradnelson@chromium.org
ahaas@chromium.org
This diff is collapsed.
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_WASM_ASM_WASM_BUILDER_H_
#define V8_WASM_ASM_WASM_BUILDER_H_
#include "src/allocation.h"
#include "src/wasm/encoder.h"
#include "src/zone.h"
namespace v8 {
namespace internal {
class FunctionLiteral;
namespace wasm {
class AsmWasmBuilder {
public:
explicit AsmWasmBuilder(Isolate* isolate, Zone* zone, FunctionLiteral* root);
WasmModuleIndex* Run();
private:
Isolate* isolate_;
Zone* zone_;
FunctionLiteral* literal_;
};
} // namespace wasm
} // namespace internal
} // namespace v8
#endif // V8_WASM_ASM_WASM_BUILDER_H_
This diff is collapsed.
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_WASM_AST_DECODER_H_
#define V8_WASM_AST_DECODER_H_
#include "src/signature.h"
#include "src/wasm/wasm-opcodes.h"
#include "src/wasm/wasm-result.h"
namespace v8 {
namespace internal {
namespace compiler { // external declarations from compiler.
class WasmGraphBuilder;
}
namespace wasm {
typedef compiler::WasmGraphBuilder TFBuilder;
struct ModuleEnv; // forward declaration of module interface.
// Interface the function environment during decoding, include the signature
// and number of locals.
struct FunctionEnv {
ModuleEnv* module; // module environment
FunctionSig* sig; // signature of this function
uint32_t local_int32_count; // number of int32 locals
uint32_t local_int64_count; // number of int64 locals
uint32_t local_float32_count; // number of float32 locals
uint32_t local_float64_count; // number of float64 locals
uint32_t total_locals; // sum of parameters and all locals
bool IsValidLocal(uint32_t index) { return index < total_locals; }
uint32_t GetLocalCount() { return total_locals; }
LocalType GetLocalType(uint32_t index) {
if (index < sig->parameter_count()) return sig->GetParam(index);
index -= sig->parameter_count();
if (index < local_int32_count) return kAstI32;
index -= local_int32_count;
if (index < local_int64_count) return kAstI64;
index -= local_int64_count;
if (index < local_float32_count) return kAstF32;
index -= local_float32_count;
if (index < local_float64_count) return kAstF64;
return kAstStmt;
}
void AddLocals(LocalType type, uint32_t count) {
switch (type) {
case kAstI32:
local_int32_count += count;
break;
case kAstI64:
local_int64_count += count;
break;
case kAstF32:
local_float32_count += count;
break;
case kAstF64:
local_float64_count += count;
break;
default:
UNREACHABLE();
}
total_locals += count;
DCHECK(total_locals ==
(sig->parameter_count() + local_int32_count + local_int64_count +
local_float32_count + local_float64_count));
}
void SumLocals() {
total_locals = static_cast<uint32_t>(sig->parameter_count()) +
local_int32_count + local_int64_count + local_float32_count +
local_float64_count;
}
};
struct Tree;
typedef Result<Tree*> TreeResult;
std::ostream& operator<<(std::ostream& os, const Tree& tree);
TreeResult VerifyWasmCode(FunctionEnv* env, const byte* base, const byte* start,
const byte* end);
TreeResult BuildTFGraph(TFBuilder* builder, FunctionEnv* env, const byte* base,
const byte* start, const byte* end);
inline TreeResult VerifyWasmCode(FunctionEnv* env, const byte* start,
const byte* end) {
return VerifyWasmCode(env, nullptr, start, end);
}
inline TreeResult BuildTFGraph(TFBuilder* builder, FunctionEnv* env,
const byte* start, const byte* end) {
return BuildTFGraph(builder, env, nullptr, start, end);
}
enum ReadUnsignedLEB128ErrorCode { kNoError, kInvalidLEB128, kMissingLEB128 };
ReadUnsignedLEB128ErrorCode ReadUnsignedLEB128Operand(const byte*, const byte*,
int*, uint32_t*);
// Computes the length of the opcode at the given address.
int OpcodeLength(const byte* pc);
// Computes the arity (number of sub-nodes) of the opcode at the given address.
int OpcodeArity(FunctionEnv* env, const byte* pc);
} // namespace wasm
} // namespace internal
} // namespace v8
#endif // V8_WASM_AST_DECODER_H_
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_WASM_JS_H_
#define V8_WASM_JS_H_
#ifndef V8_SHARED
#include "src/allocation.h"
#include "src/hashmap.h"
#else
#include "include/v8.h"
#include "src/base/compiler-specific.h"
#endif // !V8_SHARED
namespace v8 {
namespace internal {
// Exposes a WASM API to JavaScript through the V8 API.
class WasmJs {
public:
static void Install(Isolate* isolate, Handle<JSGlobalObject> global_object);
};
} // namespace internal
} // namespace v8
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment