diff options
author | Michaël Zasso <targos@protonmail.com> | 2020-11-13 12:51:53 +0100 |
---|---|---|
committer | Michaël Zasso <targos@protonmail.com> | 2020-11-15 16:46:54 +0100 |
commit | 48db20f6f53060e38b2272566b014741eb4f519f (patch) | |
tree | e2f9b4c7f69d2e4597b73b4c3c09f4371d5cc963 /deps/v8/src/compiler/wasm-compiler.cc | |
parent | 79916428a48df937aa5b2b69c061d2d42181a76b (diff) | |
download | node-new-48db20f6f53060e38b2272566b014741eb4f519f.tar.gz |
deps: update V8 to 8.7.220
PR-URL: https://github.com/nodejs/node/pull/35700
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Jiawen Geng <technicalcute@gmail.com>
Reviewed-By: Shelley Vohr <codebytere@gmail.com>
Diffstat (limited to 'deps/v8/src/compiler/wasm-compiler.cc')
-rw-r--r-- | deps/v8/src/compiler/wasm-compiler.cc | 441 |
1 files changed, 318 insertions, 123 deletions
diff --git a/deps/v8/src/compiler/wasm-compiler.cc b/deps/v8/src/compiler/wasm-compiler.cc index f8f333da2b..91dde088f6 100644 --- a/deps/v8/src/compiler/wasm-compiler.cc +++ b/deps/v8/src/compiler/wasm-compiler.cc @@ -134,15 +134,18 @@ MachineType assert_size(int expected_size, MachineType type) { wasm::ObjectAccess::ElementOffsetInTaggedFixedArray(index), value, \ MachineRepresentation::kTagged, kFullWriteBarrier) -void MergeControlToEnd(MachineGraph* mcgraph, Node* node) { +void EnsureEnd(MachineGraph* mcgraph) { Graph* g = mcgraph->graph(); - if (g->end()) { - NodeProperties::MergeControlToEnd(g, mcgraph->common(), node); - } else { - g->SetEnd(g->NewNode(mcgraph->common()->End(1), node)); + if (g->end() == nullptr) { + g->SetEnd(g->NewNode(mcgraph->common()->End(0))); } } +void MergeControlToEnd(MachineGraph* mcgraph, Node* node) { + EnsureEnd(mcgraph); + NodeProperties::MergeControlToEnd(mcgraph->graph(), mcgraph->common(), node); +} + bool ContainsSimd(const wasm::FunctionSig* sig) { for (auto type : sig->all()) { if (type == wasm::kWasmS128) return true; @@ -3051,15 +3054,6 @@ Node* WasmGraphBuilder::BuildCallRef(uint32_t sig_index, Vector<Node*> args, { // Function imported to module. - // TODO(9495): Make sure it works with functions imported from other - // modules. Currently, this will never happen: Since functions have to be - // tunneled through JS, and we currently do not have a JS API to pass - // specific function types, we habe to export/import function references - // as funcref. Then, we cannot cast down to the type of the function, - // because we do not have access to the defining module's types. This - // could be fixed either by building a richer JS API, or by implementing - // the type import proposal. That said, this code should work for those - // cases too. gasm_->Bind(&imported_label); Node* imported_instance = gasm_->Load( @@ -3087,8 +3081,9 @@ Node* WasmGraphBuilder::BuildCallRef(uint32_t sig_index, Vector<Node*> args, // Call to a WasmJSFunction. // The call target is the wasm-to-js wrapper code. gasm_->Bind(&js_label); - // TODO(7748): Implement. - TrapIfTrue(wasm::kTrapUnreachable, gasm_->Int32Constant(1), position); + // TODO(9495): Implement when the interaction with the type reflection + // proposal is clear. + TrapIfTrue(wasm::kTrapWasmJSFunction, gasm_->Int32Constant(1), position); gasm_->Goto(&end_label, args[0], RefNull() /* Dummy value */); } @@ -3675,7 +3670,7 @@ Node* WasmGraphBuilder::CheckBoundsAndAlignment( // bounds-checked index, which is guaranteed to have (the equivalent of) // {uintptr_t} representation. Node* WasmGraphBuilder::BoundsCheckMem(uint8_t access_size, Node* index, - uint32_t offset, + uint64_t offset, wasm::WasmCodePosition position, EnforceBoundsCheck enforce_check) { DCHECK_LE(1, access_size); @@ -3686,13 +3681,17 @@ Node* WasmGraphBuilder::BoundsCheckMem(uint8_t access_size, Node* index, return index; } - if (!base::IsInBounds<uint64_t>(offset, access_size, env_->max_memory_size)) { + // If the offset does not fit in a uintptr_t, this can never succeed on this + // machine. + if (offset > std::numeric_limits<uintptr_t>::max() || + !base::IsInBounds<uintptr_t>(offset, access_size, + env_->max_memory_size)) { // The access will be out of bounds, even for the largest memory. TrapIfEq32(wasm::kTrapMemOutOfBounds, Int32Constant(0), 0, position); - return mcgraph()->IntPtrConstant(0); + return mcgraph()->UintPtrConstant(0); } - uint64_t end_offset = uint64_t{offset} + access_size - 1u; - Node* end_offset_node = IntPtrConstant(end_offset); + uintptr_t end_offset = offset + access_size - 1u; + Node* end_offset_node = mcgraph_->UintPtrConstant(end_offset); // The accessed memory is [index + offset, index + end_offset]. // Check that the last read byte (at {index + end_offset}) is in bounds. @@ -3996,9 +3995,7 @@ Node* WasmGraphBuilder::LoadTransform(wasm::ValueType type, MachineType memtype, Node* index, uint32_t offset, uint32_t alignment, wasm::WasmCodePosition position) { - if (memtype.representation() == MachineRepresentation::kSimd128) { - has_simd_ = true; - } + has_simd_ = true; Node* load; @@ -4366,15 +4363,17 @@ CallDescriptor* WasmGraphBuilder::GetI64AtomicWaitCallDescriptor() { return i64_atomic_wait_descriptor_; } -void WasmGraphBuilder::LowerInt64(CallOrigin origin) { +void WasmGraphBuilder::LowerInt64(Signature<MachineRepresentation>* sig) { if (mcgraph()->machine()->Is64()) return; Int64Lowering r(mcgraph()->graph(), mcgraph()->machine(), mcgraph()->common(), - mcgraph()->zone(), - CreateMachineSignature(mcgraph()->zone(), sig_, origin), - std::move(lowering_special_case_)); + mcgraph()->zone(), sig, std::move(lowering_special_case_)); r.LowerGraph(); } +void WasmGraphBuilder::LowerInt64(CallOrigin origin) { + LowerInt64(CreateMachineSignature(mcgraph()->zone(), sig_, origin)); +} + void WasmGraphBuilder::SimdScalarLoweringForTesting() { SimdScalarLowering(mcgraph(), CreateMachineSignature(mcgraph()->zone(), sig_, kCalledFromWasm)) @@ -4952,8 +4951,8 @@ Node* WasmGraphBuilder::SimdOp(wasm::WasmOpcode opcode, Node* const* inputs) { return graph()->NewNode(mcgraph()->machine()->V8x16AnyTrue(), inputs[0]); case wasm::kExprV8x16AllTrue: return graph()->NewNode(mcgraph()->machine()->V8x16AllTrue(), inputs[0]); - case wasm::kExprS8x16Swizzle: - return graph()->NewNode(mcgraph()->machine()->S8x16Swizzle(), inputs[0], + case wasm::kExprI8x16Swizzle: + return graph()->NewNode(mcgraph()->machine()->I8x16Swizzle(), inputs[0], inputs[1]); default: FATAL_UNSUPPORTED_OPCODE(opcode); @@ -5014,7 +5013,7 @@ Node* WasmGraphBuilder::SimdLaneOp(wasm::WasmOpcode opcode, uint8_t lane, Node* WasmGraphBuilder::Simd8x16ShuffleOp(const uint8_t shuffle[16], Node* const* inputs) { has_simd_ = true; - return graph()->NewNode(mcgraph()->machine()->S8x16Shuffle(shuffle), + return graph()->NewNode(mcgraph()->machine()->I8x16Shuffle(shuffle), inputs[0], inputs[1]); } @@ -5568,13 +5567,13 @@ Node* IsI31(GraphAssembler* gasm, Node* object) { } } -void AssertFalse(GraphAssembler* gasm, Node* condition) { +void AssertFalse(MachineGraph* mcgraph, GraphAssembler* gasm, Node* condition) { #if DEBUG if (FLAG_debug_code) { auto ok = gasm->MakeLabel(); gasm->GotoIfNot(condition, &ok); + EnsureEnd(mcgraph); gasm->Unreachable(); - gasm->Goto(&ok); gasm->Bind(&ok); } #endif @@ -5592,7 +5591,7 @@ Node* WasmGraphBuilder::RefTest(Node* object, Node* rtt, gasm_->GotoIf(IsI31(gasm_.get(), object), &done, gasm_->Int32Constant(0)); need_done_label = true; } else { - AssertFalse(gasm_.get(), IsI31(gasm_.get(), object)); + AssertFalse(mcgraph(), gasm_.get(), IsI31(gasm_.get(), object)); } if (null_check == kWithNullCheck) { gasm_->GotoIf(gasm_->WordEqual(object, RefNull()), &done, @@ -5627,7 +5626,7 @@ Node* WasmGraphBuilder::RefCast(Node* object, Node* rtt, TrapIfTrue(wasm::kTrapIllegalCast, IsI31(gasm_.get(), object), position); } } else { - AssertFalse(gasm_.get(), IsI31(gasm_.get(), object)); + AssertFalse(mcgraph(), gasm_.get(), IsI31(gasm_.get(), object)); } if (null_check == kWithNullCheck) { TrapIfTrue(wasm::kTrapIllegalCast, gasm_->WordEqual(object, RefNull()), @@ -5667,7 +5666,7 @@ Node* WasmGraphBuilder::BrOnCast(Node* object, Node* rtt, merge_effects.emplace_back(effect()); } } else { - AssertFalse(gasm_.get(), is_i31); + AssertFalse(mcgraph(), gasm_.get(), is_i31); } if (null_check == kWithNullCheck) { @@ -5855,9 +5854,11 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder { public: WasmWrapperGraphBuilder(Zone* zone, MachineGraph* mcgraph, const wasm::FunctionSig* sig, + const wasm::WasmModule* module, compiler::SourcePositionTable* spt, StubCallMode stub_mode, wasm::WasmFeatures features) : WasmGraphBuilder(nullptr, zone, mcgraph, sig, spt), + module_(module), stub_mode_(stub_mode), enabled_features_(features) {} @@ -6063,6 +6064,10 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder { if (representation == wasm::HeapType::kEq) { return BuildAllocateObjectWrapper(node); } + if (type.has_index() && module_->has_signature(type.ref_index())) { + // Typed function + return node; + } // TODO(7748): Figure out a JS interop story for arrays and structs. // If this is reached, then IsJSCompatibleSignature() is too permissive. UNREACHABLE(); @@ -6148,6 +6153,29 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder { graph()->NewNode(call, target, input, context, effect(), control())); } + void BuildCheckValidRefValue(Node* input, Node* js_context, + wasm::ValueType type) { + // Make sure ValueType fits in a Smi. + STATIC_ASSERT(wasm::ValueType::kLastUsedBit + 1 <= kSmiValueSize); + Node* inputs[] = { + instance_node_.get(), input, + IntPtrConstant(IntToSmi(static_cast<int>(type.raw_bit_field())))}; + + Node* check = BuildChangeSmiToInt32(SetEffect(BuildCallToRuntimeWithContext( + Runtime::kWasmIsValidRefValue, js_context, inputs, 3))); + + Diamond type_check(graph(), mcgraph()->common(), check, BranchHint::kTrue); + type_check.Chain(control()); + SetControl(type_check.if_false); + + Node* old_effect = effect(); + BuildCallToRuntimeWithContext(Runtime::kWasmThrowTypeError, js_context, + nullptr, 0); + + SetEffectControl(type_check.EffectPhi(old_effect, effect()), + type_check.merge); + } + Node* FromJS(Node* input, Node* js_context, wasm::ValueType type) { switch (type.kind()) { case wasm::ValueType::kRef: @@ -6156,28 +6184,21 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder { case wasm::HeapType::kExtern: case wasm::HeapType::kExn: return input; - case wasm::HeapType::kFunc: { - Node* check = - BuildChangeSmiToInt32(SetEffect(BuildCallToRuntimeWithContext( - Runtime::kWasmIsValidFuncRefValue, js_context, &input, 1))); - - Diamond type_check(graph(), mcgraph()->common(), check, - BranchHint::kTrue); - type_check.Chain(control()); - SetControl(type_check.if_false); - - Node* old_effect = effect(); - BuildCallToRuntimeWithContext(Runtime::kWasmThrowTypeError, - js_context, nullptr, 0); - - SetEffectControl(type_check.EffectPhi(old_effect, effect()), - type_check.merge); - + case wasm::HeapType::kFunc: + BuildCheckValidRefValue(input, js_context, type); return input; - } case wasm::HeapType::kEq: + BuildCheckValidRefValue(input, js_context, type); return BuildUnpackObjectWrapper(input); + case wasm::HeapType::kI31: + // If this is reached, then IsJSCompatibleSignature() is too + // permissive. + UNREACHABLE(); default: + if (module_->has_signature(type.ref_index())) { + BuildCheckValidRefValue(input, js_context, type); + return input; + } // If this is reached, then IsJSCompatibleSignature() is too // permissive. UNREACHABLE(); @@ -6210,6 +6231,38 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder { } } + Node* SmiToFloat32(Node* input) { + return graph()->NewNode(mcgraph()->machine()->RoundInt32ToFloat32(), + BuildChangeSmiToInt32(input)); + } + + Node* SmiToFloat64(Node* input) { + return graph()->NewNode(mcgraph()->machine()->ChangeInt32ToFloat64(), + BuildChangeSmiToInt32(input)); + } + + Node* FromJSFast(Node* input, wasm::ValueType type) { + switch (type.kind()) { + case wasm::ValueType::kI32: + return BuildChangeSmiToInt32(input); + case wasm::ValueType::kF32: + return SmiToFloat32(input); + case wasm::ValueType::kF64: + return SmiToFloat64(input); + case wasm::ValueType::kRef: + case wasm::ValueType::kOptRef: + case wasm::ValueType::kI64: + case wasm::ValueType::kRtt: + case wasm::ValueType::kS128: + case wasm::ValueType::kI8: + case wasm::ValueType::kI16: + case wasm::ValueType::kBottom: + case wasm::ValueType::kStmt: + UNREACHABLE(); + break; + } + } + void BuildModifyThreadInWasmFlag(bool new_value) { if (!trap_handler::IsTrapHandlerEnabled()) return; Node* isolate_root = BuildLoadIsolateRoot(); @@ -6280,55 +6333,15 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder { return SetControl(CALL_BUILTIN(WasmAllocateJSArray, array_length, context)); } - 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. - SetEffectControl(Start(wasm_count + 5)); - - // Create the js_closure and js_context parameters. - Node* js_closure = - graph()->NewNode(mcgraph()->common()->Parameter( - Linkage::kJSCallClosureParamIndex, "%closure"), - graph()->start()); - Node* js_context = graph()->NewNode( - mcgraph()->common()->Parameter( - Linkage::GetJSCallContextParamIndex(wasm_count + 1), "%context"), - graph()->start()); - - // Create the instance_node node to pass as parameter. It is loaded from - // an actual reference to an instance or a placeholder reference, - // called {WasmExportedFunction} via the {WasmExportedFunctionData} - // structure. - Node* function_data = BuildLoadFunctionDataFromExportedFunction(js_closure); - instance_node_.set( - BuildLoadInstanceFromExportedFunctionData(function_data)); - - if (!wasm::IsJSCompatibleSignature(sig_, enabled_features_)) { - // Throw a TypeError. Use the js_context of the calling javascript - // function (passed as a parameter), such that the generated code is - // js_context independent. - BuildCallToRuntimeWithContext(Runtime::kWasmThrowTypeError, js_context, - nullptr, 0); - TerminateThrow(effect(), control()); - return; - } - - const int args_count = wasm_count + 1; // +1 for wasm_code. - 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) { - Node* param = Param(i + 1); - Node* wasm_param = FromJS(param, js_context, sig_->GetParam(i)); - args[i + 1] = wasm_param; - } - + Node* BuildCallAndReturn(bool is_import, Node* js_context, + Node* function_data, + base::SmallVector<Node*, 16> args) { // Set the ThreadInWasm flag before we do the actual call. BuildModifyThreadInWasmFlag(true); + const int rets_count = static_cast<int>(sig_->return_count()); + base::SmallVector<Node*, 1> rets(rets_count); + if (is_import) { // Call to an imported function. // Load function index from {WasmExportedFunctionData}. @@ -6373,7 +6386,147 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder { STORE_FIXED_ARRAY_SLOT_ANY(fixed_array, i, value); } } - Return(jsval); + return jsval; + } + + bool QualifiesForFastTransform(const wasm::FunctionSig*) { + const int wasm_count = static_cast<int>(sig_->parameter_count()); + for (int i = 0; i < wasm_count; ++i) { + wasm::ValueType type = sig_->GetParam(i); + switch (type.kind()) { + case wasm::ValueType::kRef: + case wasm::ValueType::kOptRef: + case wasm::ValueType::kI64: + case wasm::ValueType::kRtt: + case wasm::ValueType::kS128: + case wasm::ValueType::kI8: + case wasm::ValueType::kI16: + case wasm::ValueType::kBottom: + case wasm::ValueType::kStmt: + return false; + case wasm::ValueType::kI32: + case wasm::ValueType::kF32: + case wasm::ValueType::kF64: + break; + } + } + return true; + } + + Node* IsSmi(Node* input) { + return gasm_->Word32Equal( + gasm_->Word32And(BuildTruncateIntPtrToInt32(input), + gasm_->Int32Constant(kSmiTagMask)), + gasm_->Int32Constant(0)); + } + + Node* CanTransformFast(Node* input, wasm::ValueType type) { + switch (type.kind()) { + case wasm::ValueType::kI32: + case wasm::ValueType::kF64: + case wasm::ValueType::kF32: + return IsSmi(input); + case wasm::ValueType::kRef: + case wasm::ValueType::kOptRef: + case wasm::ValueType::kI64: + case wasm::ValueType::kRtt: + case wasm::ValueType::kS128: + case wasm::ValueType::kI8: + case wasm::ValueType::kI16: + case wasm::ValueType::kBottom: + case wasm::ValueType::kStmt: + UNREACHABLE(); + break; + } + } + + void BuildJSToWasmWrapper(bool is_import) { + const int wasm_count = static_cast<int>(sig_->parameter_count()); + + // Build the start and the JS parameter nodes. + SetEffectControl(Start(wasm_count + 5)); + + // Create the js_closure and js_context parameters. + Node* js_closure = + graph()->NewNode(mcgraph()->common()->Parameter( + Linkage::kJSCallClosureParamIndex, "%closure"), + graph()->start()); + Node* js_context = graph()->NewNode( + mcgraph()->common()->Parameter( + Linkage::GetJSCallContextParamIndex(wasm_count + 1), "%context"), + graph()->start()); + + // Create the instance_node node to pass as parameter. It is loaded from + // an actual reference to an instance or a placeholder reference, + // called {WasmExportedFunction} via the {WasmExportedFunctionData} + // structure. + Node* function_data = BuildLoadFunctionDataFromExportedFunction(js_closure); + instance_node_.set( + BuildLoadInstanceFromExportedFunctionData(function_data)); + + if (!wasm::IsJSCompatibleSignature(sig_, module_, enabled_features_)) { + // Throw a TypeError. Use the js_context of the calling javascript + // function (passed as a parameter), such that the generated code is + // js_context independent. + BuildCallToRuntimeWithContext(Runtime::kWasmThrowTypeError, js_context, + nullptr, 0); + TerminateThrow(effect(), control()); + return; + } + + const int args_count = wasm_count + 1; // +1 for wasm_code. + + // Check whether the signature of the function allows for a fast + // transformation (if any params exist that need transformation). + // Create a fast transformation path, only if it does. + bool include_fast_path = wasm_count && QualifiesForFastTransform(sig_); + + // Prepare Param() nodes. Param() nodes can only be created once, + // so we need to use the same nodes along all possible transformation paths. + base::SmallVector<Node*, 16> params(args_count); + for (int i = 0; i < wasm_count; ++i) params[i + 1] = Param(i + 1); + + auto done = gasm_->MakeLabel(MachineRepresentation::kTagged); + if (include_fast_path) { + auto slow_path = gasm_->MakeDeferredLabel(); + // Check if the params received on runtime can be actually transformed + // using the fast transformation. When a param that cannot be transformed + // fast is encountered, skip checking the rest and fall back to the slow + // path. + for (int i = 0; i < wasm_count; ++i) { + gasm_->GotoIfNot(CanTransformFast(params[i + 1], sig_->GetParam(i)), + &slow_path); + } + // Convert JS parameters to wasm numbers using the fast transformation + // and build the call. + base::SmallVector<Node*, 16> args(args_count); + for (int i = 0; i < wasm_count; ++i) { + Node* wasm_param = FromJSFast(params[i + 1], sig_->GetParam(i)); + args[i + 1] = wasm_param; + } + Node* jsval = + BuildCallAndReturn(is_import, js_context, function_data, args); + gasm_->Goto(&done, jsval); + gasm_->Bind(&slow_path); + } + // Convert JS parameters to wasm numbers using the default transformation + // and build the call. + base::SmallVector<Node*, 16> args(args_count); + for (int i = 0; i < wasm_count; ++i) { + Node* wasm_param = FromJS(params[i + 1], js_context, sig_->GetParam(i)); + args[i + 1] = wasm_param; + } + Node* jsval = + BuildCallAndReturn(is_import, js_context, function_data, args); + // If both the default and a fast transformation paths are present, + // get the return value based on the path used. + if (include_fast_path) { + gasm_->Goto(&done, jsval); + gasm_->Bind(&done); + Return(done.PhiAt(0)); + } else { + Return(jsval); + } if (ContainsInt64(sig_)) LowerInt64(kCalledFromJS); } @@ -6743,7 +6896,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder { isolate->factory()->undefined_value())); // Throw a TypeError if the signature is incompatible with JavaScript. - if (!wasm::IsJSCompatibleSignature(sig_, enabled_features_)) { + if (!wasm::IsJSCompatibleSignature(sig_, module_, enabled_features_)) { BuildCallToRuntimeWithContext(Runtime::kWasmThrowTypeError, context, nullptr, 0); TerminateThrow(effect(), control()); @@ -6898,6 +7051,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder { } private: + const wasm::WasmModule* module_; StubCallMode stub_mode_; SetOncePointer<Node> undefined_value_node_; SetOncePointer<const Operator> int32_to_heapnumber_operator_; @@ -6914,8 +7068,8 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder { std::unique_ptr<OptimizedCompilationJob> NewJSToWasmCompilationJob( Isolate* isolate, wasm::WasmEngine* wasm_engine, - const wasm::FunctionSig* sig, bool is_import, - const wasm::WasmFeatures& enabled_features) { + const wasm::FunctionSig* sig, const wasm::WasmModule* module, + bool is_import, const wasm::WasmFeatures& enabled_features) { //---------------------------------------------------------------------------- // Create the Graph. //---------------------------------------------------------------------------- @@ -6929,7 +7083,7 @@ std::unique_ptr<OptimizedCompilationJob> NewJSToWasmCompilationJob( InstructionSelector::AlignmentRequirements()); MachineGraph* mcgraph = zone->New<MachineGraph>(graph, common, machine); - WasmWrapperGraphBuilder builder(zone.get(), mcgraph, sig, nullptr, + WasmWrapperGraphBuilder builder(zone.get(), mcgraph, sig, module, nullptr, StubCallMode::kCallBuiltinPointer, enabled_features); builder.BuildJSToWasmWrapper(is_import); @@ -6956,6 +7110,7 @@ std::unique_ptr<OptimizedCompilationJob> NewJSToWasmCompilationJob( std::pair<WasmImportCallKind, Handle<JSReceiver>> ResolveWasmImportCall( Handle<JSReceiver> callable, const wasm::FunctionSig* expected_sig, + const wasm::WasmModule* module, const wasm::WasmFeatures& enabled_features) { if (WasmExportedFunction::IsWasmExportedFunction(*callable)) { auto imported_function = Handle<WasmExportedFunction>::cast(callable); @@ -6985,13 +7140,13 @@ std::pair<WasmImportCallKind, Handle<JSReceiver>> ResolveWasmImportCall( } if (WasmCapiFunction::IsWasmCapiFunction(*callable)) { auto capi_function = Handle<WasmCapiFunction>::cast(callable); - if (!capi_function->IsSignatureEqual(expected_sig)) { + if (!capi_function->MatchesSignature(expected_sig)) { return std::make_pair(WasmImportCallKind::kLinkError, callable); } return std::make_pair(WasmImportCallKind::kWasmToCapi, callable); } // Assuming we are calling to JS, check whether this would be a runtime error. - if (!wasm::IsJSCompatibleSignature(expected_sig, enabled_features)) { + if (!wasm::IsJSCompatibleSignature(expected_sig, module, enabled_features)) { return std::make_pair(WasmImportCallKind::kRuntimeTypeError, callable); } // For JavaScript calls, determine whether the target has an arity match. @@ -7069,10 +7224,14 @@ std::pair<WasmImportCallKind, Handle<JSReceiver>> ResolveWasmImportCall( Compiler::Compile(function, Compiler::CLEAR_EXCEPTION, &is_compiled_scope); } +#ifndef V8_REVERSE_JSARGS + // This optimization is disabled when the arguments are reversed. It will be + // subsumed when the argumens adaptor frame is removed. if (shared->is_safe_to_skip_arguments_adaptor()) { return std::make_pair( WasmImportCallKind::kJSFunctionArityMismatchSkipAdaptor, callable); } +#endif return std::make_pair(WasmImportCallKind::kJSFunctionArityMismatch, callable); @@ -7216,9 +7375,9 @@ wasm::WasmCompilationResult CompileWasmImportCallWrapper( SourcePositionTable* source_position_table = source_positions ? zone.New<SourcePositionTable>(graph) : nullptr; - WasmWrapperGraphBuilder builder(&zone, mcgraph, sig, source_position_table, - StubCallMode::kCallWasmRuntimeStub, - env->enabled_features); + WasmWrapperGraphBuilder builder( + &zone, mcgraph, sig, env->module, source_position_table, + StubCallMode::kCallWasmRuntimeStub, env->enabled_features); builder.BuildWasmImportCallWrapper(kind, expected_arity); // Build a name in the form "wasm-to-js-<kind>-<signature>". @@ -7261,9 +7420,9 @@ wasm::WasmCode* CompileWasmCapiCallWrapper(wasm::WasmEngine* wasm_engine, InstructionSelector::SupportedMachineOperatorFlags(), InstructionSelector::AlignmentRequirements())); - WasmWrapperGraphBuilder builder(&zone, mcgraph, sig, source_positions, - StubCallMode::kCallWasmRuntimeStub, - native_module->enabled_features()); + WasmWrapperGraphBuilder builder( + &zone, mcgraph, sig, native_module->module(), source_positions, + StubCallMode::kCallWasmRuntimeStub, native_module->enabled_features()); // Set up the graph start. int param_count = static_cast<int>(sig->parameter_count()) + @@ -7297,7 +7456,8 @@ wasm::WasmCode* CompileWasmCapiCallWrapper(wasm::WasmEngine* wasm_engine, } MaybeHandle<Code> CompileJSToJSWrapper(Isolate* isolate, - const wasm::FunctionSig* sig) { + const wasm::FunctionSig* sig, + const wasm::WasmModule* module) { std::unique_ptr<Zone> zone = std::make_unique<Zone>( isolate->allocator(), ZONE_NAME, kCompressGraphZone); Graph* graph = zone->New<Graph>(zone.get()); @@ -7308,7 +7468,7 @@ MaybeHandle<Code> CompileJSToJSWrapper(Isolate* isolate, InstructionSelector::AlignmentRequirements()); MachineGraph* mcgraph = zone->New<MachineGraph>(graph, common, machine); - WasmWrapperGraphBuilder builder(zone.get(), mcgraph, sig, nullptr, + WasmWrapperGraphBuilder builder(zone.get(), mcgraph, sig, module, nullptr, StubCallMode::kCallBuiltinPointer, wasm::WasmFeatures::FromIsolate(isolate)); builder.BuildJSToJSWrapper(isolate); @@ -7342,7 +7502,8 @@ MaybeHandle<Code> CompileJSToJSWrapper(Isolate* isolate, return code; } -Handle<Code> CompileCWasmEntry(Isolate* isolate, const wasm::FunctionSig* sig) { +Handle<Code> CompileCWasmEntry(Isolate* isolate, const wasm::FunctionSig* sig, + const wasm::WasmModule* module) { std::unique_ptr<Zone> zone = std::make_unique<Zone>( isolate->allocator(), ZONE_NAME, kCompressGraphZone); Graph* graph = zone->New<Graph>(zone.get()); @@ -7353,7 +7514,7 @@ Handle<Code> CompileCWasmEntry(Isolate* isolate, const wasm::FunctionSig* sig) { InstructionSelector::AlignmentRequirements()); MachineGraph* mcgraph = zone->New<MachineGraph>(graph, common, machine); - WasmWrapperGraphBuilder builder(zone.get(), mcgraph, sig, nullptr, + WasmWrapperGraphBuilder builder(zone.get(), mcgraph, sig, module, nullptr, StubCallMode::kCallBuiltinPointer, wasm::WasmFeatures::FromIsolate(isolate)); builder.BuildCWasmEntry(); @@ -7417,16 +7578,50 @@ bool BuildGraphForWasmFunction(AccountingAllocator* allocator, return false; } - builder.LowerInt64(WasmWrapperGraphBuilder::kCalledFromWasm); - + // Lower SIMD first, i64x2 nodes will be lowered to int64 nodes, then int64 + // lowering will take care of them. + auto sig = CreateMachineSignature(mcgraph->zone(), func_body.sig, + WasmGraphBuilder::kCalledFromWasm); if (builder.has_simd() && (!CpuFeatures::SupportsWasmSimd128() || env->lower_simd)) { - SimdScalarLowering( - mcgraph, CreateMachineSignature(mcgraph->zone(), func_body.sig, - WasmGraphBuilder::kCalledFromWasm)) - .LowerGraph(); + SimdScalarLowering(mcgraph, sig).LowerGraph(); + + // SimdScalarLowering changes all v128 to 4 i32, so update the machine + // signature for the call to LowerInt64. + size_t return_count = 0; + size_t param_count = 0; + for (auto ret : sig->returns()) { + return_count += ret == MachineRepresentation::kSimd128 ? 4 : 1; + } + for (auto param : sig->parameters()) { + param_count += param == MachineRepresentation::kSimd128 ? 4 : 1; + } + + Signature<MachineRepresentation>::Builder sig_builder( + mcgraph->zone(), return_count, param_count); + for (auto ret : sig->returns()) { + if (ret == MachineRepresentation::kSimd128) { + for (int i = 0; i < 4; ++i) { + sig_builder.AddReturn(MachineRepresentation::kWord32); + } + } else { + sig_builder.AddReturn(ret); + } + } + for (auto param : sig->parameters()) { + if (param == MachineRepresentation::kSimd128) { + for (int i = 0; i < 4; ++i) { + sig_builder.AddParam(MachineRepresentation::kWord32); + } + } else { + sig_builder.AddParam(param); + } + } + sig = sig_builder.Build(); } + builder.LowerInt64(sig); + if (func_index >= FLAG_trace_wasm_ast_start && func_index < FLAG_trace_wasm_ast_end) { PrintRawWasmCode(allocator, func_body, env->module, wasm::kPrintLocals); |