Revert "Revert "Upgrade to 5.0.71.48"" DO NOT MERGE
This reverts commit f2e3994fa5148cc3d9946666f0b0596290192b0e,
and updates the x64 makefile properly so it doesn't break that
build.
FPIIM-449
Change-Id: Ib83e35bfbae6af627451c926a9650ec57c045605
(cherry picked from commit 109988c7ccb6f3fd1a58574fa3dfb88beaef6632)
diff --git a/src/compiler/wasm-compiler.cc b/src/compiler/wasm-compiler.cc
index 17065d6..9c3858d 100644
--- a/src/compiler/wasm-compiler.cc
+++ b/src/compiler/wasm-compiler.cc
@@ -15,6 +15,7 @@
#include "src/compiler/graph.h"
#include "src/compiler/graph-visualizer.h"
#include "src/compiler/instruction-selector.h"
+#include "src/compiler/int64-lowering.h"
#include "src/compiler/js-generic-lowering.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/js-operator.h"
@@ -29,6 +30,9 @@
#include "src/code-factory.h"
#include "src/code-stubs.h"
+#include "src/factory.h"
+#include "src/log-inl.h"
+#include "src/profiler/cpu-profiler.h"
#include "src/wasm/ast-decoder.h"
#include "src/wasm/wasm-module.h"
@@ -105,6 +109,9 @@
// Make the current control path trap to unreachable.
void Unreachable() { ConnectTrap(kTrapUnreachable); }
+ // Always trap with the given reason.
+ void TrapAlways(TrapReason reason) { ConnectTrap(reason); }
+
// Add a check that traps if {node} is equal to {val}.
Node* TrapIfEq32(TrapReason reason, Node* node, int32_t val) {
Int32Matcher m(node);
@@ -165,6 +172,28 @@
*effect_ptr = before;
}
+ Node* GetTrapValue(wasm::FunctionSig* sig) {
+ if (sig->return_count() > 0) {
+ switch (sig->GetReturn()) {
+ case wasm::kAstI32:
+ return jsgraph()->Int32Constant(0xdeadbeef);
+ case wasm::kAstI64:
+ return jsgraph()->Int64Constant(0xdeadbeefdeadbeef);
+ case wasm::kAstF32:
+ return jsgraph()->Float32Constant(bit_cast<float>(0xdeadbeef));
+ case wasm::kAstF64:
+ return jsgraph()->Float64Constant(
+ bit_cast<double>(0xdeadbeefdeadbeef));
+ break;
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
+ } else {
+ return jsgraph()->Int32Constant(0xdeadbeef);
+ }
+ }
+
private:
WasmGraphBuilder* builder_;
JSGraph* jsgraph_;
@@ -197,7 +226,7 @@
*effect_ptr = effects_[reason] =
graph()->NewNode(common()->EffectPhi(1), *effect_ptr, *control_ptr);
- if (module && !module->context.is_null()) {
+ if (module && !module->instance->context.is_null()) {
// Use the module context to call the runtime to throw an exception.
Runtime::FunctionId f = Runtime::kThrow;
const Runtime::Function* fun = Runtime::FunctionForId(f);
@@ -210,7 +239,7 @@
jsgraph()->ExternalConstant(
ExternalReference(f, jsgraph()->isolate())), // ref
jsgraph()->Int32Constant(fun->nargs), // arity
- jsgraph()->Constant(module->context), // context
+ jsgraph()->Constant(module->instance->context), // context
*effect_ptr,
*control_ptr};
@@ -227,29 +256,7 @@
end = thrw;
} else {
// End the control flow with returning 0xdeadbeef
- Node* ret_value;
- if (builder_->GetFunctionSignature()->return_count() > 0) {
- switch (builder_->GetFunctionSignature()->GetReturn()) {
- case wasm::kAstI32:
- ret_value = jsgraph()->Int32Constant(0xdeadbeef);
- break;
- case wasm::kAstI64:
- ret_value = jsgraph()->Int64Constant(0xdeadbeefdeadbeef);
- break;
- case wasm::kAstF32:
- ret_value = jsgraph()->Float32Constant(bit_cast<float>(0xdeadbeef));
- break;
- case wasm::kAstF64:
- ret_value = jsgraph()->Float64Constant(
- bit_cast<double>(0xdeadbeefdeadbeef));
- break;
- default:
- UNREACHABLE();
- ret_value = nullptr;
- }
- } else {
- ret_value = jsgraph()->Int32Constant(0xdeadbeef);
- }
+ Node* ret_value = GetTrapValue(builder_->GetFunctionSignature());
end = graph()->NewNode(jsgraph()->common()->Return(), ret_value,
*effect_ptr, *control_ptr);
}
@@ -475,6 +482,9 @@
op = m->Uint32LessThanOrEqual();
std::swap(left, right);
break;
+ case wasm::kExprI64And:
+ op = m->Word64And();
+ break;
#if WASM_64
// Opcodes only supported on 64-bit platforms.
// TODO(titzer): query the machine operator builder here instead of #ifdef.
@@ -525,9 +535,6 @@
op = m->Uint64Mod();
return graph()->NewNode(op, left, right,
trap_->ZeroCheck64(kTrapRemByZero, right));
- case wasm::kExprI64And:
- op = m->Word64And();
- break;
case wasm::kExprI64Ior:
op = m->Word64Or();
break;
@@ -696,14 +703,10 @@
op = m->ChangeUint32ToFloat64();
break;
case wasm::kExprF32SConvertI32:
- op = m->ChangeInt32ToFloat64(); // TODO(titzer): two conversions
- input = graph()->NewNode(op, input);
- op = m->TruncateFloat64ToFloat32();
+ op = m->RoundInt32ToFloat32();
break;
case wasm::kExprF32UConvertI32:
- op = m->ChangeUint32ToFloat64();
- input = graph()->NewNode(op, input);
- op = m->TruncateFloat64ToFloat32();
+ op = m->RoundUint32ToFloat32();
break;
case wasm::kExprI32SConvertF32:
return BuildI32SConvertF32(input);
@@ -725,6 +728,10 @@
if (m->Word32Ctz().IsSupported()) {
op = m->Word32Ctz().op();
break;
+ } else if (m->Word32ReverseBits().IsSupported()) {
+ Node* reversed = graph()->NewNode(m->Word32ReverseBits().op(), input);
+ Node* result = graph()->NewNode(m->Word32Clz(), reversed);
+ return result;
} else {
return BuildI32Ctz(input);
}
@@ -738,84 +745,53 @@
}
}
case wasm::kExprF32Floor: {
- if (m->Float32RoundDown().IsSupported()) {
- op = m->Float32RoundDown().op();
- break;
- } else {
- op = UnsupportedOpcode(opcode);
- break;
- }
+ if (!m->Float32RoundDown().IsSupported()) return BuildF32Floor(input);
+ op = m->Float32RoundDown().op();
+ break;
}
case wasm::kExprF32Ceil: {
- if (m->Float32RoundUp().IsSupported()) {
- op = m->Float32RoundUp().op();
- break;
- } else {
- op = UnsupportedOpcode(opcode);
- break;
- }
+ if (!m->Float32RoundUp().IsSupported()) return BuildF32Ceil(input);
+ op = m->Float32RoundUp().op();
+ break;
}
case wasm::kExprF32Trunc: {
- if (m->Float32RoundTruncate().IsSupported()) {
- op = m->Float32RoundTruncate().op();
- break;
- } else {
- op = UnsupportedOpcode(opcode);
- break;
- }
+ if (!m->Float32RoundTruncate().IsSupported()) return BuildF32Trunc(input);
+ op = m->Float32RoundTruncate().op();
+ break;
}
case wasm::kExprF32NearestInt: {
- if (m->Float32RoundTiesEven().IsSupported()) {
- op = m->Float32RoundTiesEven().op();
- break;
- } else {
- op = UnsupportedOpcode(opcode);
- break;
- }
+ if (!m->Float32RoundTiesEven().IsSupported())
+ return BuildF32NearestInt(input);
+ op = m->Float32RoundTiesEven().op();
+ break;
}
case wasm::kExprF64Floor: {
- if (m->Float64RoundDown().IsSupported()) {
- op = m->Float64RoundDown().op();
- break;
- } else {
- op = UnsupportedOpcode(opcode);
- break;
- }
+ if (!m->Float64RoundDown().IsSupported()) return BuildF64Floor(input);
+ op = m->Float64RoundDown().op();
+ break;
}
case wasm::kExprF64Ceil: {
- if (m->Float64RoundUp().IsSupported()) {
- op = m->Float64RoundUp().op();
- break;
- } else {
- op = UnsupportedOpcode(opcode);
- break;
- }
+ if (!m->Float64RoundUp().IsSupported()) return BuildF64Ceil(input);
+ op = m->Float64RoundUp().op();
+ break;
}
case wasm::kExprF64Trunc: {
- if (m->Float64RoundTruncate().IsSupported()) {
- op = m->Float64RoundTruncate().op();
- break;
- } else {
- op = UnsupportedOpcode(opcode);
- break;
- }
+ if (!m->Float64RoundTruncate().IsSupported()) return BuildF64Trunc(input);
+ op = m->Float64RoundTruncate().op();
+ break;
}
case wasm::kExprF64NearestInt: {
- if (m->Float64RoundTiesEven().IsSupported()) {
- op = m->Float64RoundTiesEven().op();
- break;
- } else {
- op = UnsupportedOpcode(opcode);
- break;
- }
+ if (!m->Float64RoundTiesEven().IsSupported())
+ return BuildF64NearestInt(input);
+ op = m->Float64RoundTiesEven().op();
+ break;
}
-
-#if WASM_64
- // Opcodes only supported on 64-bit platforms.
- // TODO(titzer): query the machine operator builder here instead of #ifdef.
case wasm::kExprI32ConvertI64:
op = m->TruncateInt64ToInt32();
break;
+#if WASM_64
+ // Opcodes only supported on 64-bit platforms.
+ // TODO(titzer): query the machine operator builder here instead of #ifdef.
case wasm::kExprI64SConvertI32:
op = m->ChangeInt32ToInt64();
break;
@@ -883,6 +859,10 @@
if (m->Word64Ctz().IsSupported()) {
op = m->Word64Ctz().op();
break;
+ } else if (m->Word64ReverseBits().IsSupported()) {
+ Node* reversed = graph()->NewNode(m->Word64ReverseBits().op(), input);
+ Node* result = graph()->NewNode(m->Word64Clz(), reversed);
+ return result;
} else {
return BuildI64Ctz(input);
}
@@ -1061,8 +1041,12 @@
return left_le_right.Phi(
wasm::kAstF32, left,
- right_lt_left.Phi(wasm::kAstF32, right,
- left_is_not_nan.Phi(wasm::kAstF32, right, left)));
+ right_lt_left.Phi(
+ wasm::kAstF32, right,
+ left_is_not_nan.Phi(
+ wasm::kAstF32,
+ Binop(wasm::kExprF32Mul, right, Float32Constant(1.0)),
+ Binop(wasm::kExprF32Mul, left, Float32Constant(1.0)))));
}
@@ -1078,8 +1062,12 @@
return left_ge_right.Phi(
wasm::kAstF32, left,
- right_gt_left.Phi(wasm::kAstF32, right,
- left_is_not_nan.Phi(wasm::kAstF32, right, left)));
+ right_gt_left.Phi(
+ wasm::kAstF32, right,
+ left_is_not_nan.Phi(
+ wasm::kAstF32,
+ Binop(wasm::kExprF32Mul, right, Float32Constant(1.0)),
+ Binop(wasm::kExprF32Mul, left, Float32Constant(1.0)))));
}
@@ -1095,8 +1083,12 @@
return left_le_right.Phi(
wasm::kAstF64, left,
- right_lt_left.Phi(wasm::kAstF64, right,
- left_is_not_nan.Phi(wasm::kAstF64, right, left)));
+ right_lt_left.Phi(
+ wasm::kAstF64, right,
+ left_is_not_nan.Phi(
+ wasm::kAstF64,
+ Binop(wasm::kExprF64Mul, right, Float64Constant(1.0)),
+ Binop(wasm::kExprF64Mul, left, Float64Constant(1.0)))));
}
@@ -1112,8 +1104,12 @@
return left_ge_right.Phi(
wasm::kAstF64, left,
- right_gt_left.Phi(wasm::kAstF64, right,
- left_is_not_nan.Phi(wasm::kAstF64, right, left)));
+ right_gt_left.Phi(
+ wasm::kAstF64, right,
+ left_is_not_nan.Phi(
+ wasm::kAstF64,
+ Binop(wasm::kExprF64Mul, right, Float64Constant(1.0)),
+ Binop(wasm::kExprF64Mul, left, Float64Constant(1.0)))));
}
@@ -1121,14 +1117,12 @@
MachineOperatorBuilder* m = jsgraph()->machine();
// Truncation of the input value is needed for the overflow check later.
Node* trunc = Unop(wasm::kExprF32Trunc, input);
- // TODO(titzer): two conversions
- Node* f64_trunc = graph()->NewNode(m->ChangeFloat32ToFloat64(), trunc);
- Node* result = graph()->NewNode(m->ChangeFloat64ToInt32(), f64_trunc);
+ Node* result = graph()->NewNode(m->TruncateFloat32ToInt32(), trunc);
// Convert the result back to f64. If we end up at a different value than the
// truncated input value, then there has been an overflow and we trap.
- Node* check = Unop(wasm::kExprF64SConvertI32, result);
- Node* overflow = Binop(wasm::kExprF64Ne, f64_trunc, check);
+ Node* check = Unop(wasm::kExprF32SConvertI32, result);
+ Node* overflow = Binop(wasm::kExprF32Ne, trunc, check);
trap_->AddTrapIfTrue(kTrapFloatUnrepresentable, overflow);
return result;
@@ -1137,6 +1131,10 @@
Node* WasmGraphBuilder::BuildI32SConvertF64(Node* input) {
MachineOperatorBuilder* m = jsgraph()->machine();
+ if (module_ && module_->asm_js) {
+ return graph()->NewNode(
+ m->TruncateFloat64ToInt32(TruncationMode::kJavaScript), input);
+ }
// Truncation of the input value is needed for the overflow check later.
Node* trunc = Unop(wasm::kExprF64Trunc, input);
Node* result = graph()->NewNode(m->ChangeFloat64ToInt32(), trunc);
@@ -1155,14 +1153,12 @@
MachineOperatorBuilder* m = jsgraph()->machine();
// Truncation of the input value is needed for the overflow check later.
Node* trunc = Unop(wasm::kExprF32Trunc, input);
- // TODO(titzer): two conversions
- Node* f64_trunc = graph()->NewNode(m->ChangeFloat32ToFloat64(), trunc);
- Node* result = graph()->NewNode(m->ChangeFloat64ToUint32(), f64_trunc);
+ Node* result = graph()->NewNode(m->TruncateFloat32ToUint32(), trunc);
- // Convert the result back to f64. If we end up at a different value than the
+ // Convert the result back to f32. If we end up at a different value than the
// truncated input value, then there has been an overflow and we trap.
- Node* check = Unop(wasm::kExprF64UConvertI32, result);
- Node* overflow = Binop(wasm::kExprF64Ne, f64_trunc, check);
+ Node* check = Unop(wasm::kExprF32UConvertI32, result);
+ Node* overflow = Binop(wasm::kExprF32Ne, trunc, check);
trap_->AddTrapIfTrue(kTrapFloatUnrepresentable, overflow);
return result;
@@ -1171,6 +1167,10 @@
Node* WasmGraphBuilder::BuildI32UConvertF64(Node* input) {
MachineOperatorBuilder* m = jsgraph()->machine();
+ if (module_ && module_->asm_js) {
+ return graph()->NewNode(
+ m->TruncateFloat64ToInt32(TruncationMode::kJavaScript), input);
+ }
// Truncation of the input value is needed for the overflow check later.
Node* trunc = Unop(wasm::kExprF64Trunc, input);
Node* result = graph()->NewNode(m->ChangeFloat64ToUint32(), trunc);
@@ -1360,6 +1360,117 @@
return result;
}
+Node* WasmGraphBuilder::BuildF32Trunc(Node* input) {
+ MachineType type = MachineType::Float32();
+ ExternalReference ref =
+ ExternalReference::f32_trunc_wrapper_function(jsgraph()->isolate());
+ return BuildRoundingInstruction(input, ref, type);
+}
+
+Node* WasmGraphBuilder::BuildF32Floor(Node* input) {
+ MachineType type = MachineType::Float32();
+ ExternalReference ref =
+ ExternalReference::f32_floor_wrapper_function(jsgraph()->isolate());
+ return BuildRoundingInstruction(input, ref, type);
+}
+
+Node* WasmGraphBuilder::BuildF32Ceil(Node* input) {
+ MachineType type = MachineType::Float32();
+ ExternalReference ref =
+ ExternalReference::f32_ceil_wrapper_function(jsgraph()->isolate());
+ return BuildRoundingInstruction(input, ref, type);
+}
+
+Node* WasmGraphBuilder::BuildF32NearestInt(Node* input) {
+ MachineType type = MachineType::Float32();
+ ExternalReference ref =
+ ExternalReference::f32_nearest_int_wrapper_function(jsgraph()->isolate());
+ return BuildRoundingInstruction(input, ref, type);
+}
+
+Node* WasmGraphBuilder::BuildF64Trunc(Node* input) {
+ MachineType type = MachineType::Float64();
+ ExternalReference ref =
+ ExternalReference::f64_trunc_wrapper_function(jsgraph()->isolate());
+ return BuildRoundingInstruction(input, ref, type);
+}
+
+Node* WasmGraphBuilder::BuildF64Floor(Node* input) {
+ MachineType type = MachineType::Float64();
+ ExternalReference ref =
+ ExternalReference::f64_floor_wrapper_function(jsgraph()->isolate());
+ return BuildRoundingInstruction(input, ref, type);
+}
+
+Node* WasmGraphBuilder::BuildF64Ceil(Node* input) {
+ MachineType type = MachineType::Float64();
+ ExternalReference ref =
+ ExternalReference::f64_ceil_wrapper_function(jsgraph()->isolate());
+ return BuildRoundingInstruction(input, ref, type);
+}
+
+Node* WasmGraphBuilder::BuildF64NearestInt(Node* input) {
+ MachineType type = MachineType::Float64();
+ ExternalReference ref =
+ ExternalReference::f64_nearest_int_wrapper_function(jsgraph()->isolate());
+ return BuildRoundingInstruction(input, ref, type);
+}
+
+Node* WasmGraphBuilder::BuildRoundingInstruction(Node* input,
+ ExternalReference ref,
+ MachineType type) {
+ // We do truncation by calling a C function which calculates the truncation
+ // for us. The input is passed to the C function as a double* to avoid double
+ // parameters. For this we reserve a slot on the stack, store the parameter in
+ // that slot, pass a pointer to the slot to the C function, and after calling
+ // the C function we collect the return value from the stack slot.
+
+ Node* stack_slot_param =
+ graph()->NewNode(jsgraph()->machine()->StackSlot(type.representation()));
+
+ const Operator* store_op = jsgraph()->machine()->Store(
+ StoreRepresentation(type.representation(), kNoWriteBarrier));
+ *effect_ =
+ graph()->NewNode(store_op, stack_slot_param, jsgraph()->Int32Constant(0),
+ input, *effect_, *control_);
+
+ Signature<MachineType>::Builder sig_builder(jsgraph()->zone(), 0, 1);
+ sig_builder.AddParam(MachineType::Pointer());
+ Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(ref));
+
+ Node* args[] = {function, stack_slot_param};
+
+ BuildCCall(sig_builder.Build(), args);
+
+ const Operator* load_op = jsgraph()->machine()->Load(type);
+
+ Node* load =
+ graph()->NewNode(load_op, stack_slot_param, jsgraph()->Int32Constant(0),
+ *effect_, *control_);
+ *effect_ = load;
+ return load;
+}
+
+Node* WasmGraphBuilder::BuildCCall(MachineSignature* sig, Node** args) {
+ const size_t params = sig->parameter_count();
+ const size_t extra = 2; // effect and control inputs.
+ const size_t count = 1 + params + extra;
+
+ // Reallocate the buffer to make space for extra inputs.
+ args = Realloc(args, count);
+
+ // Add effect and control inputs.
+ args[params + 1] = *effect_;
+ args[params + 2] = *control_;
+
+ CallDescriptor* desc =
+ Linkage::GetSimplifiedCDescriptor(jsgraph()->zone(), sig);
+
+ const Operator* op = jsgraph()->common()->Call(desc);
+ Node* call = graph()->NewNode(op, static_cast<int>(count), args);
+ *effect_ = call;
+ return call;
+}
Node* WasmGraphBuilder::BuildWasmCall(wasm::FunctionSig* sig, Node** args) {
const size_t params = sig->parameter_count();
@@ -1373,8 +1484,9 @@
args[params + 1] = *effect_;
args[params + 2] = *control_;
- const Operator* op = jsgraph()->common()->Call(
- module_->GetWasmCallDescriptor(jsgraph()->zone(), sig));
+ CallDescriptor* descriptor =
+ wasm::ModuleEnv::GetWasmCallDescriptor(jsgraph()->zone(), sig);
+ const Operator* op = jsgraph()->common()->Call(descriptor);
Node* call = graph()->NewNode(op, static_cast<int>(count), args);
*effect_ = call;
@@ -1392,23 +1504,38 @@
return BuildWasmCall(sig, args);
}
+Node* WasmGraphBuilder::CallImport(uint32_t index, Node** args) {
+ DCHECK_NULL(args[0]);
+
+ // Add code object as constant.
+ args[0] = Constant(module_->GetImportCode(index));
+ wasm::FunctionSig* sig = module_->GetImportSignature(index);
+
+ return BuildWasmCall(sig, args);
+}
Node* WasmGraphBuilder::CallIndirect(uint32_t index, Node** args) {
DCHECK_NOT_NULL(args[0]);
+ DCHECK(module_ && module_->instance);
MachineOperatorBuilder* machine = jsgraph()->machine();
// Compute the code object by loading it from the function table.
Node* key = args[0];
- Node* table = FunctionTable();
// Bounds check the index.
int table_size = static_cast<int>(module_->FunctionTableSize());
- {
+ if (table_size > 0) {
+ // Bounds check against the table size.
Node* size = Int32Constant(static_cast<int>(table_size));
Node* in_bounds = graph()->NewNode(machine->Uint32LessThan(), key, size);
trap_->AddTrapIfFalse(kTrapFuncInvalid, in_bounds);
+ } else {
+ // No function table. Generate a trap and return a constant.
+ trap_->AddTrapIfFalse(kTrapFuncInvalid, Int32Constant(0));
+ return trap_->GetTrapValue(module_->GetSignature(index));
}
+ Node* table = FunctionTable();
// Load signature from the table and check.
// The table is a FixedArray; signatures are encoded as SMIs.
@@ -1546,7 +1673,8 @@
args[pos++] = *control_;
// Call the WASM code.
- CallDescriptor* desc = module_->GetWasmCallDescriptor(jsgraph()->zone(), sig);
+ CallDescriptor* desc =
+ wasm::ModuleEnv::GetWasmCallDescriptor(jsgraph()->zone(), sig);
Node* call = graph()->NewNode(jsgraph()->common()->Call(desc), count, args);
Node* jsval =
ToJS(call, context,
@@ -1631,18 +1759,23 @@
Node* WasmGraphBuilder::MemBuffer(uint32_t offset) {
+ DCHECK(module_ && module_->instance);
if (offset == 0) {
- if (!mem_buffer_)
- mem_buffer_ = jsgraph()->IntPtrConstant(module_->mem_start);
+ if (!mem_buffer_) {
+ mem_buffer_ = jsgraph()->IntPtrConstant(
+ reinterpret_cast<uintptr_t>(module_->instance->mem_start));
+ }
return mem_buffer_;
} else {
- return jsgraph()->IntPtrConstant(module_->mem_start + offset);
+ return jsgraph()->IntPtrConstant(
+ reinterpret_cast<uintptr_t>(module_->instance->mem_start + offset));
}
}
Node* WasmGraphBuilder::MemSize(uint32_t offset) {
- int32_t size = static_cast<int>(module_->mem_end - module_->mem_start);
+ DCHECK(module_ && module_->instance);
+ uint32_t size = static_cast<uint32_t>(module_->instance->mem_size);
if (offset == 0) {
if (!mem_size_) mem_size_ = jsgraph()->Int32Constant(size);
return mem_size_;
@@ -1653,18 +1786,21 @@
Node* WasmGraphBuilder::FunctionTable() {
+ DCHECK(module_ && module_->instance &&
+ !module_->instance->function_table.is_null());
if (!function_table_) {
- DCHECK(!module_->function_table.is_null());
- function_table_ = jsgraph()->Constant(module_->function_table);
+ function_table_ = jsgraph()->Constant(module_->instance->function_table);
}
return function_table_;
}
Node* WasmGraphBuilder::LoadGlobal(uint32_t index) {
+ DCHECK(module_ && module_->instance && module_->instance->globals_start);
MachineType mem_type = module_->GetGlobalType(index);
Node* addr = jsgraph()->IntPtrConstant(
- module_->globals_area + module_->module->globals->at(index).offset);
+ reinterpret_cast<uintptr_t>(module_->instance->globals_start +
+ module_->module->globals->at(index).offset));
const Operator* op = jsgraph()->machine()->Load(mem_type);
Node* node = graph()->NewNode(op, addr, jsgraph()->Int32Constant(0), *effect_,
*control_);
@@ -1674,9 +1810,11 @@
Node* WasmGraphBuilder::StoreGlobal(uint32_t index, Node* val) {
+ DCHECK(module_ && module_->instance && module_->instance->globals_start);
MachineType mem_type = module_->GetGlobalType(index);
Node* addr = jsgraph()->IntPtrConstant(
- module_->globals_area + module_->module->globals->at(index).offset);
+ reinterpret_cast<uintptr_t>(module_->instance->globals_start +
+ module_->module->globals->at(index).offset));
const Operator* op = jsgraph()->machine()->Store(
StoreRepresentation(mem_type.representation(), kNoWriteBarrier));
Node* node = graph()->NewNode(op, addr, jsgraph()->Int32Constant(0), val,
@@ -1689,12 +1827,11 @@
void WasmGraphBuilder::BoundsCheckMem(MachineType memtype, Node* index,
uint32_t offset) {
// TODO(turbofan): fold bounds checks for constant indexes.
- CHECK_GE(module_->mem_end, module_->mem_start);
- ptrdiff_t size = module_->mem_end - module_->mem_start;
+ DCHECK(module_ && module_->instance);
+ size_t size = module_->instance->mem_size;
byte memsize = wasm::WasmOpcodes::MemSize(memtype);
Node* cond;
- if (static_cast<ptrdiff_t>(offset) >= size ||
- static_cast<ptrdiff_t>(offset + memsize) > size) {
+ if (offset >= size || (static_cast<uint64_t>(offset) + memsize) > size) {
// The access will always throw.
cond = jsgraph()->Int32Constant(0);
} else {
@@ -1782,6 +1919,35 @@
Graph* WasmGraphBuilder::graph() { return jsgraph()->graph(); }
+void WasmGraphBuilder::Int64LoweringForTesting() {
+ if (kPointerSize == 4) {
+ Int64Lowering r(jsgraph()->graph(), jsgraph()->machine(),
+ jsgraph()->common(), jsgraph()->zone(),
+ function_signature_);
+ r.LowerGraph();
+ }
+}
+
+static void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
+ CompilationInfo* info,
+ const char* message, uint32_t index,
+ const char* func_name) {
+ Isolate* isolate = info->isolate();
+ if (isolate->logger()->is_logging_code_events() ||
+ isolate->cpu_profiler()->is_profiling()) {
+ ScopedVector<char> buffer(128);
+ SNPrintF(buffer, "%s#%d:%s", message, index, func_name);
+ Handle<String> name_str =
+ isolate->factory()->NewStringFromAsciiChecked(buffer.start());
+ Handle<String> script_str =
+ isolate->factory()->NewStringFromAsciiChecked("(WASM)");
+ Handle<Code> code = info->code();
+ Handle<SharedFunctionInfo> shared =
+ isolate->factory()->NewSharedFunctionInfo(name_str, code, false);
+ PROFILE(isolate,
+ CodeCreateEvent(tag, *code, *shared, info, *script_str, 0, 0));
+ }
+}
Handle<JSFunction> CompileJSToWasmWrapper(
Isolate* isolate, wasm::ModuleEnv* module, Handle<String> name,
@@ -1849,38 +2015,42 @@
module->GetFunctionSignature(index)->parameter_count());
CallDescriptor* incoming = Linkage::GetJSCallDescriptor(
&zone, false, params + 1, CallDescriptor::kNoFlags);
- CompilationInfo info("js-to-wasm", isolate, &zone);
// TODO(titzer): this is technically a WASM wrapper, not a wasm function.
- info.set_output_code_kind(Code::WASM_FUNCTION);
+ Code::Flags flags = Code::ComputeFlags(Code::WASM_FUNCTION);
+ bool debugging =
+#if DEBUG
+ true;
+#else
+ FLAG_print_opt_code || FLAG_trace_turbo || FLAG_trace_turbo_graph;
+#endif
+ const char* func_name = "js-to-wasm";
+
+ static unsigned id = 0;
+ Vector<char> buffer;
+ if (debugging) {
+ buffer = Vector<char>::New(128);
+ SNPrintF(buffer, "js-to-wasm#%d", id);
+ func_name = buffer.start();
+ }
+
+ CompilationInfo info(func_name, isolate, &zone, flags);
Handle<Code> code =
Pipeline::GenerateCodeForTesting(&info, incoming, &graph, nullptr);
-
-#ifdef ENABLE_DISASSEMBLER
- // Disassemble the wrapper code for debugging.
- if (!code.is_null() && FLAG_print_opt_code) {
- Vector<char> buffer;
- const char* name = "";
- if (func->name_offset > 0) {
- const byte* ptr = module->module->module_start + func->name_offset;
- name = reinterpret_cast<const char*>(ptr);
- }
- SNPrintF(buffer, "JS->WASM function wrapper #%d:%s", index, name);
- OFStream os(stdout);
- code->Disassemble(buffer.start(), os);
+ if (debugging) {
+ buffer.Dispose();
}
-#endif
+
+ RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, "js-to-wasm", index,
+ module->module->GetName(func->name_offset));
// Set the JSFunction's machine code.
function->set_code(*code);
}
return function;
}
-
Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, wasm::ModuleEnv* module,
Handle<JSFunction> function,
- uint32_t index) {
- wasm::WasmFunction* func = &module->module->functions->at(index);
-
+ wasm::FunctionSig* sig, const char* name) {
//----------------------------------------------------------------------------
// Create the Graph
//----------------------------------------------------------------------------
@@ -1894,11 +2064,11 @@
Node* control = nullptr;
Node* effect = nullptr;
- WasmGraphBuilder builder(&zone, &jsgraph, func->sig);
+ WasmGraphBuilder builder(&zone, &jsgraph, sig);
builder.set_control_ptr(&control);
builder.set_effect_ptr(&effect);
builder.set_module(module);
- builder.BuildWasmToJSWrapper(function, func->sig);
+ builder.BuildWasmToJSWrapper(function, sig);
Handle<Code> code = Handle<Code>::null();
{
@@ -1923,26 +2093,33 @@
}
// Schedule and compile to machine code.
- CallDescriptor* incoming = module->GetWasmCallDescriptor(&zone, func->sig);
- CompilationInfo info("wasm-to-js", isolate, &zone);
+ CallDescriptor* incoming =
+ wasm::ModuleEnv::GetWasmCallDescriptor(&zone, sig);
// TODO(titzer): this is technically a WASM wrapper, not a wasm function.
- info.set_output_code_kind(Code::WASM_FUNCTION);
- code = Pipeline::GenerateCodeForTesting(&info, incoming, &graph, nullptr);
-
-#ifdef ENABLE_DISASSEMBLER
- // Disassemble the wrapper code for debugging.
- if (!code.is_null() && FLAG_print_opt_code) {
- Vector<char> buffer;
- const char* name = "";
- if (func->name_offset > 0) {
- const byte* ptr = module->module->module_start + func->name_offset;
- name = reinterpret_cast<const char*>(ptr);
- }
- SNPrintF(buffer, "WASM->JS function wrapper #%d:%s", index, name);
- OFStream os(stdout);
- code->Disassemble(buffer.start(), os);
- }
+ Code::Flags flags = Code::ComputeFlags(Code::WASM_FUNCTION);
+ bool debugging =
+#if DEBUG
+ true;
+#else
+ FLAG_print_opt_code || FLAG_trace_turbo || FLAG_trace_turbo_graph;
#endif
+ const char* func_name = "wasm-to-js";
+ static unsigned id = 0;
+ Vector<char> buffer;
+ if (debugging) {
+ buffer = Vector<char>::New(128);
+ SNPrintF(buffer, "wasm-to-js#%d", id);
+ func_name = buffer.start();
+ }
+
+ CompilationInfo info(func_name, isolate, &zone, flags);
+ code = Pipeline::GenerateCodeForTesting(&info, incoming, &graph, nullptr);
+ if (debugging) {
+ buffer.Dispose();
+ }
+
+ RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, "wasm-to-js", 0,
+ name);
}
return code;
}
@@ -1951,25 +2128,21 @@
// Helper function to compile a single function.
Handle<Code> CompileWasmFunction(wasm::ErrorThrower& thrower, Isolate* isolate,
wasm::ModuleEnv* module_env,
- const wasm::WasmFunction& function,
- int index) {
+ const wasm::WasmFunction& function) {
if (FLAG_trace_wasm_compiler || FLAG_trace_wasm_decode_time) {
- // TODO(titzer): clean me up a bit.
OFStream os(stdout);
- os << "Compiling WASM function #" << index << ":";
- if (function.name_offset > 0) {
- os << module_env->module->GetName(function.name_offset);
- }
+ os << "Compiling WASM function "
+ << wasm::WasmFunctionName(&function, module_env) << std::endl;
os << std::endl;
}
// Initialize the function environment for decoding.
wasm::FunctionEnv env;
env.module = module_env;
env.sig = function.sig;
- env.local_int32_count = function.local_int32_count;
- env.local_int64_count = function.local_int64_count;
- env.local_float32_count = function.local_float32_count;
- env.local_float64_count = function.local_float64_count;
+ env.local_i32_count = function.local_i32_count;
+ env.local_i64_count = function.local_i64_count;
+ env.local_f32_count = function.local_f32_count;
+ env.local_f64_count = function.local_f64_count;
env.SumLocals();
// Create a TF graph during decoding.
@@ -1993,35 +2166,49 @@
os << "Compilation failed: " << result << std::endl;
}
// Add the function as another context for the exception
- Vector<char> buffer;
- SNPrintF(buffer, "Compiling WASM function #%d:%s failed:", index,
+ ScopedVector<char> buffer(128);
+ SNPrintF(buffer, "Compiling WASM function #%d:%s failed:",
+ function.func_index,
module_env->module->GetName(function.name_offset));
thrower.Failed(buffer.start(), result);
return Handle<Code>::null();
}
// Run the compiler pipeline to generate machine code.
- CallDescriptor* descriptor = const_cast<CallDescriptor*>(
- module_env->GetWasmCallDescriptor(&zone, function.sig));
- CompilationInfo info("wasm", isolate, &zone);
- info.set_output_code_kind(Code::WASM_FUNCTION);
+ CallDescriptor* descriptor =
+ wasm::ModuleEnv::GetWasmCallDescriptor(&zone, function.sig);
+ if (kPointerSize == 4) {
+ descriptor = module_env->GetI32WasmCallDescriptor(&zone, descriptor);
+ }
+ Code::Flags flags = Code::ComputeFlags(Code::WASM_FUNCTION);
+ // add flags here if a meaningful name is helpful for debugging.
+ bool debugging =
+#if DEBUG
+ true;
+#else
+ FLAG_print_opt_code || FLAG_trace_turbo || FLAG_trace_turbo_graph;
+#endif
+ const char* func_name = "wasm";
+ Vector<char> buffer;
+ if (debugging) {
+ buffer = Vector<char>::New(128);
+ SNPrintF(buffer, "WASM_function_#%d:%s", function.func_index,
+ module_env->module->GetName(function.name_offset));
+ func_name = buffer.start();
+ }
+ CompilationInfo info(func_name, isolate, &zone, flags);
+
Handle<Code> code =
Pipeline::GenerateCodeForTesting(&info, descriptor, &graph);
-
-#ifdef ENABLE_DISASSEMBLER
- // Disassemble the code for debugging.
- if (!code.is_null() && FLAG_print_opt_code) {
- Vector<char> buffer;
- const char* name = "";
- if (function.name_offset > 0) {
- const byte* ptr = module_env->module->module_start + function.name_offset;
- name = reinterpret_cast<const char*>(ptr);
- }
- SNPrintF(buffer, "WASM function #%d:%s", index, name);
- OFStream os(stdout);
- code->Disassemble(buffer.start(), os);
+ if (debugging) {
+ buffer.Dispose();
}
-#endif
+ if (!code.is_null()) {
+ RecordFunctionCompilation(
+ Logger::FUNCTION_TAG, &info, "WASM_function", function.func_index,
+ module_env->module->GetName(function.name_offset));
+ }
+
return code;
}