diff options
Diffstat (limited to 'deps/v8/src/compiler/wasm-compiler.cc')
-rw-r--r-- | deps/v8/src/compiler/wasm-compiler.cc | 386 |
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); } |