summaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler/wasm-compiler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/compiler/wasm-compiler.cc')
-rw-r--r--deps/v8/src/compiler/wasm-compiler.cc386
1 files changed, 231 insertions, 155 deletions
diff --git a/deps/v8/src/compiler/wasm-compiler.cc b/deps/v8/src/compiler/wasm-compiler.cc
index 28f9943e59..ddc97ce503 100644
--- a/deps/v8/src/compiler/wasm-compiler.cc
+++ b/deps/v8/src/compiler/wasm-compiler.cc
@@ -176,8 +176,6 @@ WasmGraphBuilder::WasmGraphBuilder(
: zone_(zone),
mcgraph_(mcgraph),
env_(env),
- cur_buffer_(def_buffer_),
- cur_bufsize_(kDefaultBufferSize),
has_simd_(ContainsSimd(sig)),
untrusted_code_mitigations_(FLAG_untrusted_code_mitigations),
sig_(sig),
@@ -255,24 +253,19 @@ Node* WasmGraphBuilder::Merge(unsigned count, Node** controls) {
return graph()->NewNode(mcgraph()->common()->Merge(count), count, controls);
}
-Node* WasmGraphBuilder::Phi(wasm::ValueType type, unsigned count, Node** vals,
- Node* control) {
- DCHECK(IrOpcode::IsMergeOpcode(control->opcode()));
- Vector<Node*> buf = Realloc(vals, count, count + 1);
- buf[count] = control;
+Node* WasmGraphBuilder::Phi(wasm::ValueType type, unsigned count,
+ Node** vals_and_control) {
+ DCHECK(IrOpcode::IsMergeOpcode(vals_and_control[count]->opcode()));
return graph()->NewNode(
mcgraph()->common()->Phi(wasm::ValueTypes::MachineRepresentationFor(type),
count),
- count + 1, buf.begin());
+ count + 1, vals_and_control);
}
-Node* WasmGraphBuilder::EffectPhi(unsigned count, Node** effects,
- Node* control) {
- DCHECK(IrOpcode::IsMergeOpcode(control->opcode()));
- Vector<Node*> buf = Realloc(effects, count, count + 1);
- buf[count] = control;
+Node* WasmGraphBuilder::EffectPhi(unsigned count, Node** effects_and_control) {
+ DCHECK(IrOpcode::IsMergeOpcode(effects_and_control[count]->opcode()));
return graph()->NewNode(mcgraph()->common()->EffectPhi(count), count + 1,
- buf.begin());
+ effects_and_control);
}
Node* WasmGraphBuilder::RefNull() {
@@ -1114,6 +1107,10 @@ Node* WasmGraphBuilder::ZeroCheck64(wasm::TrapReason reason, Node* node,
}
Node* WasmGraphBuilder::Switch(unsigned count, Node* key) {
+ // The instruction selector will use {kArchTableSwitch} for large switches,
+ // which has limited input count, see {InstructionSelector::EmitTableSwitch}.
+ DCHECK_LE(count, Instruction::kMaxInputCount - 2); // value_range + 2
+ DCHECK_LE(count, wasm::kV8MaxWasmFunctionBrTableSize + 1); // plus IfDefault
return graph()->NewNode(mcgraph()->common()->Switch(count), key, Control());
}
@@ -1266,27 +1263,9 @@ Node* WasmGraphBuilder::BuildChangeEndiannessStore(
case 8:
result = graph()->NewNode(m->Word64ReverseBytes(), value);
break;
- case 16: {
- Node* byte_reversed_lanes[4];
- for (int lane = 0; lane < 4; lane++) {
- byte_reversed_lanes[lane] = graph()->NewNode(
- m->Word32ReverseBytes(),
- graph()->NewNode(mcgraph()->machine()->I32x4ExtractLane(lane),
- value));
- }
-
- // This is making a copy of the value.
- result =
- graph()->NewNode(mcgraph()->machine()->S128And(), value, value);
-
- for (int lane = 0; lane < 4; lane++) {
- result =
- graph()->NewNode(mcgraph()->machine()->I32x4ReplaceLane(3 - lane),
- result, byte_reversed_lanes[lane]);
- }
-
+ case 16:
+ result = graph()->NewNode(m->Simd128ReverseBytes(), value);
break;
- }
default:
UNREACHABLE();
break;
@@ -1405,27 +1384,9 @@ Node* WasmGraphBuilder::BuildChangeEndiannessLoad(Node* node,
case 8:
result = graph()->NewNode(m->Word64ReverseBytes(), value);
break;
- case 16: {
- Node* byte_reversed_lanes[4];
- for (int lane = 0; lane < 4; lane++) {
- byte_reversed_lanes[lane] = graph()->NewNode(
- m->Word32ReverseBytes(),
- graph()->NewNode(mcgraph()->machine()->I32x4ExtractLane(lane),
- value));
- }
-
- // This is making a copy of the value.
- result =
- graph()->NewNode(mcgraph()->machine()->S128And(), value, value);
-
- for (int lane = 0; lane < 4; lane++) {
- result =
- graph()->NewNode(mcgraph()->machine()->I32x4ReplaceLane(3 - lane),
- result, byte_reversed_lanes[lane]);
- }
-
+ case 16:
+ result = graph()->NewNode(m->Simd128ReverseBytes(), value);
break;
- }
default:
UNREACHABLE();
}
@@ -2295,13 +2256,14 @@ Node* WasmGraphBuilder::GetExceptionTag(Node* except_obj) {
return BuildCallToRuntime(Runtime::kWasmExceptionGetTag, &except_obj, 1);
}
-Vector<Node*> WasmGraphBuilder::GetExceptionValues(
- Node* except_obj, const wasm::WasmException* exception) {
+Node* WasmGraphBuilder::GetExceptionValues(Node* except_obj,
+ const wasm::WasmException* exception,
+ Vector<Node*> values) {
Node* values_array =
BuildCallToRuntime(Runtime::kWasmExceptionGetValues, &except_obj, 1);
uint32_t index = 0;
const wasm::WasmExceptionSig* sig = exception->sig;
- Vector<Node*> values = Buffer(sig->parameter_count());
+ DCHECK_EQ(sig->parameter_count(), values.size());
for (size_t i = 0; i < sig->parameter_count(); ++i) {
Node* value;
switch (sig->GetParam(i)) {
@@ -2347,7 +2309,7 @@ Vector<Node*> WasmGraphBuilder::GetExceptionValues(
values[i] = value;
}
DCHECK_EQ(index, WasmExceptionPackage::GetEncodedSize(exception));
- return values;
+ return values_array;
}
Node* WasmGraphBuilder::BuildI32DivS(Node* left, Node* right,
@@ -2682,7 +2644,8 @@ Node* WasmGraphBuilder::BuildCCall(MachineSignature* sig, Node* function,
return SetEffect(graph()->NewNode(op, arraysize(call_args), call_args));
}
-Node* WasmGraphBuilder::BuildCallNode(wasm::FunctionSig* sig, Node** args,
+Node* WasmGraphBuilder::BuildCallNode(wasm::FunctionSig* sig,
+ Vector<Node*> args,
wasm::WasmCodePosition position,
Node* instance_node, const Operator* op) {
if (instance_node == nullptr) {
@@ -2695,25 +2658,28 @@ Node* WasmGraphBuilder::BuildCallNode(wasm::FunctionSig* sig, Node** args,
const size_t count = 1 + params + extra;
// Reallocate the buffer to make space for extra inputs.
- args = Realloc(args, 1 + params, count).begin();
+ base::SmallVector<Node*, 16 + extra> inputs(count);
+ DCHECK_EQ(1 + params, args.size());
// Make room for the instance_node parameter at index 1, just after code.
- memmove(&args[2], &args[1], params * sizeof(Node*));
- args[1] = instance_node;
+ inputs[0] = args[0]; // code
+ inputs[1] = instance_node;
+ if (params > 0) memcpy(&inputs[2], &args[1], params * sizeof(Node*));
// Add effect and control inputs.
- args[params + 2] = Effect();
- args[params + 3] = Control();
+ inputs[params + 2] = Effect();
+ inputs[params + 3] = Control();
- Node* call = SetEffect(graph()->NewNode(op, static_cast<int>(count), args));
+ Node* call =
+ SetEffect(graph()->NewNode(op, static_cast<int>(count), inputs.begin()));
DCHECK(position == wasm::kNoCodePosition || position > 0);
if (position > 0) SetSourcePosition(call, position);
return call;
}
-Node* WasmGraphBuilder::BuildWasmCall(wasm::FunctionSig* sig, Node** args,
- Node*** rets,
+Node* WasmGraphBuilder::BuildWasmCall(wasm::FunctionSig* sig,
+ Vector<Node*> args, Vector<Node*> rets,
wasm::WasmCodePosition position,
Node* instance_node,
UseRetpoline use_retpoline) {
@@ -2725,21 +2691,22 @@ Node* WasmGraphBuilder::BuildWasmCall(wasm::FunctionSig* sig, Node** args,
size_t ret_count = sig->return_count();
if (ret_count == 0) return call; // No return value.
- *rets = Buffer(ret_count).begin();
+ DCHECK_EQ(ret_count, rets.size());
if (ret_count == 1) {
// Only a single return value.
- (*rets)[0] = call;
+ rets[0] = call;
} else {
// Create projections for all return values.
for (size_t i = 0; i < ret_count; i++) {
- (*rets)[i] = graph()->NewNode(mcgraph()->common()->Projection(i), call,
- graph()->start());
+ rets[i] = graph()->NewNode(mcgraph()->common()->Projection(i), call,
+ graph()->start());
}
}
return call;
}
-Node* WasmGraphBuilder::BuildWasmReturnCall(wasm::FunctionSig* sig, Node** args,
+Node* WasmGraphBuilder::BuildWasmReturnCall(wasm::FunctionSig* sig,
+ Vector<Node*> args,
wasm::WasmCodePosition position,
Node* instance_node,
UseRetpoline use_retpoline) {
@@ -2753,8 +2720,8 @@ Node* WasmGraphBuilder::BuildWasmReturnCall(wasm::FunctionSig* sig, Node** args,
return call;
}
-Node* WasmGraphBuilder::BuildImportCall(wasm::FunctionSig* sig, Node** args,
- Node*** rets,
+Node* WasmGraphBuilder::BuildImportCall(wasm::FunctionSig* sig,
+ Vector<Node*> args, Vector<Node*> rets,
wasm::WasmCodePosition position,
int func_index,
IsReturnCall continuation) {
@@ -2779,13 +2746,13 @@ Node* WasmGraphBuilder::BuildImportCall(wasm::FunctionSig* sig, Node** args,
case kCallContinues:
return BuildWasmCall(sig, args, rets, position, ref_node, use_retpoline);
case kReturnCall:
- DCHECK_NULL(rets);
+ DCHECK(rets.empty());
return BuildWasmReturnCall(sig, args, position, ref_node, use_retpoline);
}
}
-Node* WasmGraphBuilder::BuildImportCall(wasm::FunctionSig* sig, Node** args,
- Node*** rets,
+Node* WasmGraphBuilder::BuildImportCall(wasm::FunctionSig* sig,
+ Vector<Node*> args, Vector<Node*> rets,
wasm::WasmCodePosition position,
Node* func_index,
IsReturnCall continuation) {
@@ -2829,12 +2796,13 @@ Node* WasmGraphBuilder::BuildImportCall(wasm::FunctionSig* sig, Node** args,
case kCallContinues:
return BuildWasmCall(sig, args, rets, position, ref_node, use_retpoline);
case kReturnCall:
- DCHECK_NULL(rets);
+ DCHECK(rets.empty());
return BuildWasmReturnCall(sig, args, position, ref_node, use_retpoline);
}
}
-Node* WasmGraphBuilder::CallDirect(uint32_t index, Node** args, Node*** rets,
+Node* WasmGraphBuilder::CallDirect(uint32_t index, Vector<Node*> args,
+ Vector<Node*> rets,
wasm::WasmCodePosition position) {
DCHECK_NULL(args[0]);
wasm::FunctionSig* sig = env_->module->functions[index].sig;
@@ -2853,7 +2821,7 @@ Node* WasmGraphBuilder::CallDirect(uint32_t index, Node** args, Node*** rets,
}
Node* WasmGraphBuilder::CallIndirect(uint32_t table_index, uint32_t sig_index,
- Node** args, Node*** rets,
+ Vector<Node*> args, Vector<Node*> rets,
wasm::WasmCodePosition position) {
return BuildIndirectCall(table_index, sig_index, args, rets, position,
kCallContinues);
@@ -2902,8 +2870,9 @@ void WasmGraphBuilder::LoadIndirectFunctionTable(uint32_t table_index,
}
Node* WasmGraphBuilder::BuildIndirectCall(uint32_t table_index,
- uint32_t sig_index, Node** args,
- Node*** rets,
+ uint32_t sig_index,
+ Vector<Node*> args,
+ Vector<Node*> rets,
wasm::WasmCodePosition position,
IsReturnCall continuation) {
DCHECK_NOT_NULL(args[0]);
@@ -2993,14 +2962,14 @@ Node* WasmGraphBuilder::BuildIndirectCall(uint32_t table_index,
}
}
-Node* WasmGraphBuilder::ReturnCall(uint32_t index, Node** args,
+Node* WasmGraphBuilder::ReturnCall(uint32_t index, Vector<Node*> args,
wasm::WasmCodePosition position) {
DCHECK_NULL(args[0]);
wasm::FunctionSig* sig = env_->module->functions[index].sig;
if (env_ && index < env_->module->num_imported_functions) {
// Return Call to an imported function.
- return BuildImportCall(sig, args, nullptr, position, index, kReturnCall);
+ return BuildImportCall(sig, args, {}, position, index, kReturnCall);
}
// A direct tail call to a wasm function defined in this module.
@@ -3013,9 +2982,10 @@ Node* WasmGraphBuilder::ReturnCall(uint32_t index, Node** args,
}
Node* WasmGraphBuilder::ReturnCallIndirect(uint32_t table_index,
- uint32_t sig_index, Node** args,
+ uint32_t sig_index,
+ Vector<Node*> args,
wasm::WasmCodePosition position) {
- return BuildIndirectCall(table_index, sig_index, args, nullptr, position,
+ return BuildIndirectCall(table_index, sig_index, args, {}, position,
kReturnCall);
}
@@ -3062,6 +3032,14 @@ bool CanCover(Node* value, IrOpcode::Value opcode) {
return true;
}
+Node* WasmGraphBuilder::BuildTruncateIntPtrToInt32(Node* value) {
+ if (mcgraph()->machine()->Is64()) {
+ value =
+ graph()->NewNode(mcgraph()->machine()->TruncateInt64ToInt32(), value);
+ }
+ return value;
+}
+
Node* WasmGraphBuilder::BuildChangeInt32ToIntPtr(Node* value) {
if (mcgraph()->machine()->Is64()) {
value = graph()->NewNode(mcgraph()->machine()->ChangeInt32ToInt64(), value);
@@ -3070,12 +3048,20 @@ Node* WasmGraphBuilder::BuildChangeInt32ToIntPtr(Node* value) {
}
Node* WasmGraphBuilder::BuildChangeInt32ToSmi(Node* value) {
+ if (COMPRESS_POINTERS_BOOL) {
+ return graph()->NewNode(mcgraph()->machine()->Word32Shl(), value,
+ BuildSmiShiftBitsConstant32());
+ }
value = BuildChangeInt32ToIntPtr(value);
return graph()->NewNode(mcgraph()->machine()->WordShl(), value,
BuildSmiShiftBitsConstant());
}
Node* WasmGraphBuilder::BuildChangeUint31ToSmi(Node* value) {
+ if (COMPRESS_POINTERS_BOOL) {
+ return graph()->NewNode(mcgraph()->machine()->Word32Shl(), value,
+ BuildSmiShiftBitsConstant32());
+ }
return graph()->NewNode(mcgraph()->machine()->WordShl(),
Uint32ToUintptr(value), BuildSmiShiftBitsConstant());
}
@@ -3084,16 +3070,32 @@ Node* WasmGraphBuilder::BuildSmiShiftBitsConstant() {
return mcgraph()->IntPtrConstant(kSmiShiftSize + kSmiTagSize);
}
+Node* WasmGraphBuilder::BuildSmiShiftBitsConstant32() {
+ return mcgraph()->Int32Constant(kSmiShiftSize + kSmiTagSize);
+}
+
Node* WasmGraphBuilder::BuildChangeSmiToInt32(Node* value) {
- value = graph()->NewNode(mcgraph()->machine()->WordSar(), value,
- BuildSmiShiftBitsConstant());
- if (mcgraph()->machine()->Is64()) {
+ if (COMPRESS_POINTERS_BOOL) {
value =
graph()->NewNode(mcgraph()->machine()->TruncateInt64ToInt32(), value);
+ value = graph()->NewNode(mcgraph()->machine()->Word32Sar(), value,
+ BuildSmiShiftBitsConstant32());
+ } else {
+ value = BuildChangeSmiToIntPtr(value);
+ value = BuildTruncateIntPtrToInt32(value);
}
return value;
}
+Node* WasmGraphBuilder::BuildChangeSmiToIntPtr(Node* value) {
+ if (COMPRESS_POINTERS_BOOL) {
+ value = BuildChangeSmiToInt32(value);
+ return BuildChangeInt32ToIntPtr(value);
+ }
+ return graph()->NewNode(mcgraph()->machine()->WordSar(), value,
+ BuildSmiShiftBitsConstant());
+}
+
Node* WasmGraphBuilder::BuildConvertUint32ToSmiWithSaturation(Node* value,
uint32_t maxval) {
DCHECK(Smi::IsValid(maxval));
@@ -3181,14 +3183,16 @@ Node* WasmGraphBuilder::CreateOrMergeIntoPhi(MachineRepresentation rep,
if (IsPhiWithMerge(tnode, merge)) {
AppendToPhi(tnode, fnode);
} else if (tnode != fnode) {
+ // Note that it is not safe to use {Buffer} here since this method is used
+ // via {CheckForException} while the {Buffer} is in use by another method.
uint32_t count = merge->InputCount();
// + 1 for the merge node.
- Vector<Node*> vals = Buffer(count + 1);
- for (uint32_t j = 0; j < count - 1; j++) vals[j] = tnode;
- vals[count - 1] = fnode;
- vals[count] = merge;
- return graph()->NewNode(mcgraph()->common()->Phi(rep, count), count + 1,
- vals.begin());
+ base::SmallVector<Node*, 9> inputs(count + 1);
+ for (uint32_t j = 0; j < count - 1; j++) inputs[j] = tnode;
+ inputs[count - 1] = fnode;
+ inputs[count] = merge;
+ tnode = graph()->NewNode(mcgraph()->common()->Phi(rep, count), count + 1,
+ inputs.begin());
}
return tnode;
}
@@ -3198,13 +3202,18 @@ Node* WasmGraphBuilder::CreateOrMergeIntoEffectPhi(Node* merge, Node* tnode,
if (IsPhiWithMerge(tnode, merge)) {
AppendToPhi(tnode, fnode);
} else if (tnode != fnode) {
+ // Note that it is not safe to use {Buffer} here since this method is used
+ // via {CheckForException} while the {Buffer} is in use by another method.
uint32_t count = merge->InputCount();
- Vector<Node*> effects = Buffer(count);
+ // + 1 for the merge node.
+ base::SmallVector<Node*, 9> inputs(count + 1);
for (uint32_t j = 0; j < count - 1; j++) {
- effects[j] = tnode;
+ inputs[j] = tnode;
}
- effects[count - 1] = fnode;
- tnode = EffectPhi(count, effects.begin(), merge);
+ inputs[count - 1] = fnode;
+ inputs[count] = merge;
+ tnode = graph()->NewNode(mcgraph()->common()->EffectPhi(count), count + 1,
+ inputs.begin());
}
return tnode;
}
@@ -3310,10 +3319,7 @@ Node* WasmGraphBuilder::CurrentMemoryPages() {
Node* result =
graph()->NewNode(mcgraph()->machine()->WordShr(), mem_size,
mcgraph()->Int32Constant(wasm::kWasmPageSizeLog2));
- if (mcgraph()->machine()->Is64()) {
- result =
- graph()->NewNode(mcgraph()->machine()->TruncateInt64ToInt32(), result);
- }
+ result = BuildTruncateIntPtrToInt32(result);
return result;
}
@@ -3365,7 +3371,7 @@ Node* WasmGraphBuilder::BuildCallToRuntime(Runtime::FunctionId f,
parameter_count, effect_, Control());
}
-Node* WasmGraphBuilder::GetGlobal(uint32_t index) {
+Node* WasmGraphBuilder::GlobalGet(uint32_t index) {
const wasm::WasmGlobal& global = env_->module->globals[index];
if (wasm::ValueTypes::IsReferenceType(global.type)) {
if (global.mutability && global.imported) {
@@ -3395,7 +3401,7 @@ Node* WasmGraphBuilder::GetGlobal(uint32_t index) {
return result;
}
-Node* WasmGraphBuilder::SetGlobal(uint32_t index, Node* val) {
+Node* WasmGraphBuilder::GlobalSet(uint32_t index, Node* val) {
const wasm::WasmGlobal& global = env_->module->globals[index];
if (wasm::ValueTypes::IsReferenceType(global.type)) {
if (global.mutability && global.imported) {
@@ -4008,6 +4014,8 @@ Node* WasmGraphBuilder::SimdOp(wasm::WasmOpcode opcode, Node* const* inputs) {
return graph()->NewNode(mcgraph()->machine()->F64x2Abs(), inputs[0]);
case wasm::kExprF64x2Neg:
return graph()->NewNode(mcgraph()->machine()->F64x2Neg(), inputs[0]);
+ case wasm::kExprF64x2Sqrt:
+ return graph()->NewNode(mcgraph()->machine()->F64x2Sqrt(), inputs[0]);
case wasm::kExprF64x2Add:
return graph()->NewNode(mcgraph()->machine()->F64x2Add(), inputs[0],
inputs[1]);
@@ -4044,6 +4052,12 @@ Node* WasmGraphBuilder::SimdOp(wasm::WasmOpcode opcode, Node* const* inputs) {
case wasm::kExprF64x2Ge:
return graph()->NewNode(mcgraph()->machine()->F64x2Le(), inputs[1],
inputs[0]);
+ case wasm::kExprF64x2Qfma:
+ return graph()->NewNode(mcgraph()->machine()->F64x2Qfma(), inputs[0],
+ inputs[1], inputs[2]);
+ case wasm::kExprF64x2Qfms:
+ return graph()->NewNode(mcgraph()->machine()->F64x2Qfms(), inputs[0],
+ inputs[1], inputs[2]);
case wasm::kExprF32x4Splat:
return graph()->NewNode(mcgraph()->machine()->F32x4Splat(), inputs[0]);
case wasm::kExprF32x4SConvertI32x4:
@@ -4056,6 +4070,8 @@ Node* WasmGraphBuilder::SimdOp(wasm::WasmOpcode opcode, Node* const* inputs) {
return graph()->NewNode(mcgraph()->machine()->F32x4Abs(), inputs[0]);
case wasm::kExprF32x4Neg:
return graph()->NewNode(mcgraph()->machine()->F32x4Neg(), inputs[0]);
+ case wasm::kExprF32x4Sqrt:
+ return graph()->NewNode(mcgraph()->machine()->F32x4Sqrt(), inputs[0]);
case wasm::kExprF32x4RecipApprox:
return graph()->NewNode(mcgraph()->machine()->F32x4RecipApprox(),
inputs[0]);
@@ -4101,6 +4117,12 @@ Node* WasmGraphBuilder::SimdOp(wasm::WasmOpcode opcode, Node* const* inputs) {
case wasm::kExprF32x4Ge:
return graph()->NewNode(mcgraph()->machine()->F32x4Le(), inputs[1],
inputs[0]);
+ case wasm::kExprF32x4Qfma:
+ return graph()->NewNode(mcgraph()->machine()->F32x4Qfma(), inputs[0],
+ inputs[1], inputs[2]);
+ case wasm::kExprF32x4Qfms:
+ return graph()->NewNode(mcgraph()->machine()->F32x4Qfms(), inputs[0],
+ inputs[1], inputs[2]);
case wasm::kExprI64x2Splat:
return graph()->NewNode(mcgraph()->machine()->I64x2Splat(), inputs[0]);
case wasm::kExprI64x2Neg:
@@ -4459,6 +4481,9 @@ Node* WasmGraphBuilder::SimdOp(wasm::WasmOpcode opcode, Node* const* inputs) {
return graph()->NewNode(mcgraph()->machine()->S1x16AnyTrue(), inputs[0]);
case wasm::kExprS1x16AllTrue:
return graph()->NewNode(mcgraph()->machine()->S1x16AllTrue(), inputs[0]);
+ case wasm::kExprS8x16Swizzle:
+ return graph()->NewNode(mcgraph()->machine()->S8x16Swizzle(), inputs[0],
+ inputs[1]);
default:
FATAL_UNSUPPORTED_OPCODE(opcode);
}
@@ -4492,13 +4517,23 @@ Node* WasmGraphBuilder::SimdLaneOp(wasm::WasmOpcode opcode, uint8_t lane,
case wasm::kExprI32x4ReplaceLane:
return graph()->NewNode(mcgraph()->machine()->I32x4ReplaceLane(lane),
inputs[0], inputs[1]);
- case wasm::kExprI16x8ExtractLane:
+ case wasm::kExprI16x8ExtractLaneS:
+ return graph()->NewNode(
+ mcgraph()->machine()->SignExtendWord16ToInt32(),
+ graph()->NewNode(mcgraph()->machine()->I16x8ExtractLane(lane),
+ inputs[0]));
+ case wasm::kExprI16x8ExtractLaneU:
return graph()->NewNode(mcgraph()->machine()->I16x8ExtractLane(lane),
inputs[0]);
case wasm::kExprI16x8ReplaceLane:
return graph()->NewNode(mcgraph()->machine()->I16x8ReplaceLane(lane),
inputs[0], inputs[1]);
- case wasm::kExprI8x16ExtractLane:
+ case wasm::kExprI8x16ExtractLaneS:
+ return graph()->NewNode(
+ mcgraph()->machine()->SignExtendWord8ToInt32(),
+ graph()->NewNode(mcgraph()->machine()->I8x16ExtractLane(lane),
+ inputs[0]));
+ case wasm::kExprI8x16ExtractLaneU:
return graph()->NewNode(mcgraph()->machine()->I8x16ExtractLane(lane),
inputs[0]);
case wasm::kExprI8x16ReplaceLane:
@@ -5076,7 +5111,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
CallDescriptor* GetI64ToBigIntCallDescriptor() {
if (!lowering_special_case_) {
- lowering_special_case_ = base::make_unique<Int64LoweringSpecialCase>();
+ lowering_special_case_ = std::make_unique<Int64LoweringSpecialCase>();
}
if (lowering_special_case_->i64_to_bigint_call_descriptor) {
@@ -5112,7 +5147,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
CallDescriptor* GetBigIntToI64CallDescriptor() {
if (!lowering_special_case_) {
- lowering_special_case_ = base::make_unique<Int64LoweringSpecialCase>();
+ lowering_special_case_ = std::make_unique<Int64LoweringSpecialCase>();
}
if (lowering_special_case_->bigint_to_i64_call_descriptor) {
@@ -5613,7 +5648,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
Node* function_index_smi = LOAD_RAW(
function_data,
WasmExportedFunctionData::kFunctionIndexOffset - kHeapObjectTag,
- MachineType::TypeCompressedTagged());
+ MachineType::TypeCompressedTaggedSigned());
Node* function_index = BuildChangeSmiToInt32(function_index_smi);
return function_index;
}
@@ -5622,13 +5657,30 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
Node* jump_table_offset_smi = LOAD_RAW(
function_data,
WasmExportedFunctionData::kJumpTableOffsetOffset - kHeapObjectTag,
- MachineType::TypeCompressedTagged());
- Node* jump_table_offset = BuildChangeSmiToInt32(jump_table_offset_smi);
+ MachineType::TypeCompressedTaggedSigned());
+ Node* jump_table_offset = BuildChangeSmiToIntPtr(jump_table_offset_smi);
return jump_table_offset;
}
+ Node* BuildMultiReturnFixedArrayFromIterable(const wasm::FunctionSig* sig,
+ Node* iterable, Node* context) {
+ Node* iterable_to_fixed_array =
+ BuildLoadBuiltinFromIsolateRoot(Builtins::kIterableToFixedArrayForWasm);
+ IterableToFixedArrayForWasmDescriptor interface_descriptor;
+ Node* length = BuildChangeUint31ToSmi(
+ Uint32Constant(static_cast<uint32_t>(sig->return_count())));
+ auto call_descriptor = Linkage::GetStubCallDescriptor(
+ mcgraph()->zone(), interface_descriptor,
+ interface_descriptor.GetStackParameterCount(), CallDescriptor::kNoFlags,
+ Operator::kNoProperties, StubCallMode::kCallCodeObject);
+ return SetEffect(graph()->NewNode(
+ mcgraph()->common()->Call(call_descriptor), iterable_to_fixed_array,
+ iterable, length, context, Effect(), Control()));
+ }
+
void BuildJSToWasmWrapper(bool is_import) {
const int wasm_count = static_cast<int>(sig_->parameter_count());
+ const int rets_count = static_cast<int>(sig_->return_count());
// Build the start and the JS parameter nodes.
SetEffect(SetControl(Start(wasm_count + 5)));
@@ -5662,8 +5714,8 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
}
const int args_count = wasm_count + 1; // +1 for wasm_code.
- Vector<Node*> args = Buffer(args_count);
- Node** rets;
+ base::SmallVector<Node*, 16> args(args_count);
+ base::SmallVector<Node*, 1> rets(rets_count);
// Convert JS parameters to wasm numbers.
for (int i = 0; i < wasm_count; ++i) {
@@ -5680,8 +5732,8 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
// Load function index from {WasmExportedFunctionData}.
Node* function_index =
BuildLoadFunctionIndexFromExportedFunctionData(function_data);
- BuildImportCall(sig_, args.begin(), &rets, wasm::kNoCodePosition,
- function_index, kCallContinues);
+ BuildImportCall(sig_, VectorOf(args), VectorOf(rets),
+ wasm::kNoCodePosition, function_index, kCallContinues);
} else {
// Call to a wasm function defined in this module.
// The call target is the jump table slot for that function.
@@ -5693,8 +5745,8 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
mcgraph()->machine()->IntAdd(), jump_table_start, jump_table_offset);
args[0] = jump_table_slot;
- BuildWasmCall(sig_, args.begin(), &rets, wasm::kNoCodePosition, nullptr,
- kNoRetpoline);
+ BuildWasmCall(sig_, VectorOf(args), VectorOf(rets), wasm::kNoCodePosition,
+ nullptr, kNoRetpoline);
}
// Clear the ThreadInWasm flag.
@@ -5765,7 +5817,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
sloppy_receiver = false;
V8_FALLTHROUGH; // fallthru
case WasmImportCallKind::kJSFunctionArityMatchSloppy: {
- Vector<Node*> args = Buffer(wasm_count + 7);
+ base::SmallVector<Node*, 16> args(wasm_count + 7);
int pos = 0;
Node* function_context =
LOAD_RAW(callable_node,
@@ -5785,7 +5837,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
graph()->zone(), false, wasm_count + 1, CallDescriptor::kNoFlags);
// Convert wasm numbers to JS values.
- pos = AddArgumentNodes(args, pos, wasm_count, sig_);
+ pos = AddArgumentNodes(VectorOf(args), pos, wasm_count, sig_);
args[pos++] = undefined_node; // new target
args[pos++] = mcgraph()->Int32Constant(wasm_count); // argument count
@@ -5805,7 +5857,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
sloppy_receiver = false;
V8_FALLTHROUGH; // fallthru
case WasmImportCallKind::kJSFunctionArityMismatchSloppy: {
- Vector<Node*> args = Buffer(wasm_count + 9);
+ base::SmallVector<Node*, 16> args(wasm_count + 9);
int pos = 0;
Node* function_context =
LOAD_RAW(callable_node,
@@ -5852,7 +5904,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
flags, Operator::kNoProperties);
// Convert wasm numbers to JS values.
- pos = AddArgumentNodes(args, pos, wasm_count, sig_);
+ pos = AddArgumentNodes(VectorOf(args), pos, wasm_count, sig_);
args[pos++] = function_context;
args[pos++] = Effect();
args[pos++] = Control();
@@ -5866,7 +5918,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
// === General case of unknown callable ==================================
// =======================================================================
case WasmImportCallKind::kUseCallBuiltin: {
- Vector<Node*> args = Buffer(wasm_count + 7);
+ base::SmallVector<Node*, 16> args(wasm_count + 7);
int pos = 0;
args[pos++] =
BuildLoadBuiltinFromIsolateRoot(Builtins::kCall_ReceiverIsAny);
@@ -5879,7 +5931,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
CallDescriptor::kNoFlags, Operator::kNoProperties);
// Convert wasm numbers to JS values.
- pos = AddArgumentNodes(args, pos, wasm_count, sig_);
+ pos = AddArgumentNodes(VectorOf(args), pos, wasm_count, sig_);
// The native_context is sufficient here, because all kind of callables
// which depend on the context provide their own context. The context
@@ -5903,15 +5955,24 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
SetEffect(call);
SetSourcePosition(call, 0);
- // Convert the return value back.
- Node* val = sig_->return_count() == 0
- ? mcgraph()->Int32Constant(0)
- : FromJS(call, native_context, sig_->GetReturn());
-
- // Set the ThreadInWasm flag again.
- BuildModifyThreadInWasmFlag(true);
-
- Return(val);
+ // Convert the return value(s) back.
+ if (sig_->return_count() <= 1) {
+ Node* val = sig_->return_count() == 0
+ ? mcgraph()->Int32Constant(0)
+ : FromJS(call, native_context, sig_->GetReturn());
+ BuildModifyThreadInWasmFlag(true);
+ Return(val);
+ } else {
+ Node* fixed_array =
+ BuildMultiReturnFixedArrayFromIterable(sig_, call, native_context);
+ base::SmallVector<Node*, 8> wasm_values(sig_->return_count());
+ for (unsigned i = 0; i < sig_->return_count(); ++i) {
+ wasm_values[i] = FromJS(LOAD_FIXED_ARRAY_SLOT_ANY(fixed_array, i),
+ native_context, sig_->GetReturn(i));
+ }
+ BuildModifyThreadInWasmFlag(true);
+ Return(VectorOf(wasm_values));
+ }
if (ContainsInt64(sig_)) LowerInt64(kCalledFromWasm);
return true;
@@ -6006,7 +6067,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
if (return_count == 0) {
Return(Int32Constant(0));
} else {
- Vector<Node*> returns = Buffer(return_count);
+ base::SmallVector<Node*, 8> returns(return_count);
offset = 0;
for (size_t i = 0; i < return_count; ++i) {
wasm::ValueType type = sig_->GetReturn(i);
@@ -6016,7 +6077,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
returns[i] = val;
offset += wasm::ValueTypes::ElementSizeInBytes(type);
}
- Return(returns);
+ Return(VectorOf(returns));
}
if (ContainsInt64(sig_)) LowerInt64(kCalledFromWasm);
@@ -6078,7 +6139,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
if (return_count == 0) {
Return(Int32Constant(0));
} else {
- Vector<Node*> returns = Buffer(return_count);
+ base::SmallVector<Node*, 8> returns(return_count);
offset = 0;
for (size_t i = 0; i < return_count; ++i) {
wasm::ValueType type = sig_->GetReturn(i);
@@ -6088,7 +6149,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
returns[i] = val;
offset += wasm::ValueTypes::ElementSizeInBytes(type);
}
- Return(returns);
+ Return(VectorOf(returns));
}
if (ContainsInt64(sig_)) LowerInt64(kCalledFromWasm);
@@ -6130,10 +6191,10 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
wasm::ObjectAccess::ToTagged(WasmJSFunctionData::kCallableOffset));
// Call the underlying closure.
- Vector<Node*> args = Buffer(wasm_count + 7);
+ base::SmallVector<Node*, 16> args(wasm_count + 7);
int pos = 0;
- args[pos++] = graph()->NewNode(mcgraph()->common()->HeapConstant(
- BUILTIN_CODE(isolate, Call_ReceiverIsAny)));
+ args[pos++] =
+ BuildLoadBuiltinFromIsolateRoot(Builtins::kCall_ReceiverIsAny);
args[pos++] = callable;
args[pos++] = mcgraph()->Int32Constant(wasm_count); // argument count
args[pos++] = BuildLoadUndefinedValueFromInstance(); // receiver
@@ -6158,14 +6219,30 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
Node* call = SetEffect(graph()->NewNode(
mcgraph()->common()->Call(call_descriptor), pos, args.begin()));
- // TODO(wasm): Extend this to support multi-return.
- DCHECK_LE(sig_->return_count(), 1);
-
// Convert return JS values to wasm numbers and back to JS values.
- Node* jsval =
- sig_->return_count() == 0
- ? BuildLoadUndefinedValueFromInstance()
- : ToJS(FromJS(call, context, sig_->GetReturn()), sig_->GetReturn());
+ Node* jsval;
+ if (sig_->return_count() == 0) {
+ jsval = BuildLoadUndefinedValueFromInstance();
+ } else if (sig_->return_count() == 1) {
+ jsval = ToJS(FromJS(call, context, sig_->GetReturn()), sig_->GetReturn());
+ } else {
+ Node* fixed_array =
+ BuildMultiReturnFixedArrayFromIterable(sig_, call, context);
+ int32_t return_count = static_cast<int32_t>(sig_->return_count());
+ Node* size =
+ graph()->NewNode(mcgraph()->common()->NumberConstant(return_count));
+ Node* result_fixed_array =
+ BuildCallToRuntime(Runtime::kWasmNewMultiReturnFixedArray, &size, 1);
+ for (unsigned i = 0; i < sig_->return_count(); ++i) {
+ const auto& type = sig_->GetReturn(i);
+ Node* elem = LOAD_FIXED_ARRAY_SLOT_ANY(fixed_array, i);
+ Node* cast = ToJS(FromJS(elem, context, type), type);
+ STORE_FIXED_ARRAY_SLOT_ANY(result_fixed_array, i, cast);
+ }
+ jsval = BuildCallToRuntimeWithContext(Runtime::kWasmNewMultiReturnJSArray,
+ context, &result_fixed_array, 1,
+ effect_, Control());
+ }
Return(jsval);
}
@@ -6184,7 +6261,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
kNoWriteBarrier);
int wasm_arg_count = static_cast<int>(sig_->parameter_count());
- Vector<Node*> args = Buffer(wasm_arg_count + 4);
+ base::SmallVector<Node*, 16> args(wasm_arg_count + 4);
int pos = 0;
args[pos++] = code_entry;
@@ -6222,14 +6299,12 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
pos = 0;
offset = 0;
for (wasm::ValueType type : sig_->returns()) {
- StoreRepresentation store_rep(
- wasm::ValueTypes::MachineRepresentationFor(type), kNoWriteBarrier);
Node* value = sig_->return_count() == 1
? call
: graph()->NewNode(mcgraph()->common()->Projection(pos),
call, Control());
- SetEffect(graph()->NewNode(mcgraph()->machine()->Store(store_rep),
- arg_buffer, Int32Constant(offset), value,
+ SetEffect(graph()->NewNode(GetSafeStoreOperator(offset, type), arg_buffer,
+ Int32Constant(offset), value,
Effect(), Control()));
offset += wasm::ValueTypes::ElementSizeInBytes(type);
pos++;
@@ -6287,7 +6362,7 @@ std::unique_ptr<OptimizedCompilationJob> NewJSToWasmCompilationJob(
// Create the Graph.
//----------------------------------------------------------------------------
std::unique_ptr<Zone> zone =
- base::make_unique<Zone>(wasm_engine->allocator(), ZONE_NAME);
+ std::make_unique<Zone>(wasm_engine->allocator(), ZONE_NAME);
Graph* graph = new (zone.get()) Graph(zone.get());
CommonOperatorBuilder common(zone.get());
MachineOperatorBuilder machine(
@@ -6702,7 +6777,7 @@ wasm::WasmCompilationResult CompileWasmInterpreterEntry(
MaybeHandle<Code> CompileJSToJSWrapper(Isolate* isolate,
wasm::FunctionSig* sig) {
std::unique_ptr<Zone> zone =
- base::make_unique<Zone>(isolate->allocator(), ZONE_NAME);
+ std::make_unique<Zone>(isolate->allocator(), ZONE_NAME);
Graph* graph = new (zone.get()) Graph(zone.get());
CommonOperatorBuilder common(zone.get());
MachineOperatorBuilder machine(
@@ -6749,7 +6824,7 @@ MaybeHandle<Code> CompileJSToJSWrapper(Isolate* isolate,
MaybeHandle<Code> CompileCWasmEntry(Isolate* isolate, wasm::FunctionSig* sig) {
std::unique_ptr<Zone> zone =
- base::make_unique<Zone>(isolate->allocator(), ZONE_NAME);
+ std::make_unique<Zone>(isolate->allocator(), ZONE_NAME);
Graph* graph = new (zone.get()) Graph(zone.get());
CommonOperatorBuilder common(zone.get());
MachineOperatorBuilder machine(
@@ -6916,6 +6991,7 @@ wasm::WasmCompilationResult ExecuteTurbofanWasmCompilation(
counters->wasm_compile_function_peak_memory_bytes()->AddSample(
static_cast<int>(mcgraph->graph()->zone()->allocation_size()));
auto result = info.ReleaseWasmCompilationResult();
+ CHECK_NOT_NULL(result); // Compilation expected to succeed.
DCHECK_EQ(wasm::ExecutionTier::kTurbofan, result->result_tier);
return std::move(*result);
}