diff options
Diffstat (limited to 'deps/v8/src/compiler/wasm-compiler.cc')
-rw-r--r-- | deps/v8/src/compiler/wasm-compiler.cc | 712 |
1 files changed, 429 insertions, 283 deletions
diff --git a/deps/v8/src/compiler/wasm-compiler.cc b/deps/v8/src/compiler/wasm-compiler.cc index 3396214e58..2da7177ece 100644 --- a/deps/v8/src/compiler/wasm-compiler.cc +++ b/deps/v8/src/compiler/wasm-compiler.cc @@ -14,6 +14,7 @@ #include "src/codegen/assembler-inl.h" #include "src/codegen/assembler.h" #include "src/codegen/code-factory.h" +#include "src/codegen/compiler.h" #include "src/codegen/interface-descriptors.h" #include "src/codegen/optimized-compilation-info.h" #include "src/compiler/backend/code-generator.h" @@ -276,8 +277,9 @@ Node* WasmGraphBuilder::EffectPhi(unsigned count, Node** effects, } Node* WasmGraphBuilder::RefNull() { - return LOAD_INSTANCE_FIELD(NullValue, - MachineType::TypeCompressedTaggedPointer()); + Node* isolate_root = LOAD_INSTANCE_FIELD(IsolateRoot, MachineType::Pointer()); + return LOAD_TAGGED_POINTER( + isolate_root, IsolateData::root_slot_offset(RootIndex::kNullValue)); } Node* WasmGraphBuilder::RefFunc(uint32_t function_index) { @@ -2195,8 +2197,8 @@ Node* WasmGraphBuilder::Throw(uint32_t exception_index, graph()->NewNode(m->I32x4ExtractLane(3), value)); break; case wasm::kWasmAnyRef: - case wasm::kWasmAnyFunc: - case wasm::kWasmExceptRef: + case wasm::kWasmFuncRef: + case wasm::kWasmExnRef: STORE_FIXED_ARRAY_SLOT_ANY(values_array, index, value); ++index; break; @@ -2334,8 +2336,8 @@ Node** WasmGraphBuilder::GetExceptionValues( BuildDecodeException32BitValue(values_array, &index)); break; case wasm::kWasmAnyRef: - case wasm::kWasmAnyFunc: - case wasm::kWasmExceptRef: + case wasm::kWasmFuncRef: + case wasm::kWasmExnRef: value = LOAD_FIXED_ARRAY_SLOT_ANY(values_array, index); ++index; break; @@ -2853,25 +2855,69 @@ 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, wasm::WasmCodePosition position) { - if (table_index == 0) { - return BuildIndirectCall(sig_index, args, rets, position, kCallContinues); - } return BuildIndirectCall(table_index, sig_index, args, rets, position, kCallContinues); } -Node* WasmGraphBuilder::BuildIndirectCall(uint32_t sig_index, Node** args, +void WasmGraphBuilder::LoadIndirectFunctionTable(uint32_t table_index, + Node** ift_size, + Node** ift_sig_ids, + Node** ift_targets, + Node** ift_instances) { + if (table_index == 0) { + *ift_size = + LOAD_INSTANCE_FIELD(IndirectFunctionTableSize, MachineType::Uint32()); + *ift_sig_ids = LOAD_INSTANCE_FIELD(IndirectFunctionTableSigIds, + MachineType::Pointer()); + *ift_targets = LOAD_INSTANCE_FIELD(IndirectFunctionTableTargets, + MachineType::Pointer()); + *ift_instances = LOAD_INSTANCE_FIELD( + IndirectFunctionTableRefs, MachineType::TypeCompressedTaggedPointer()); + return; + } + + Node* ift_tables = LOAD_INSTANCE_FIELD( + IndirectFunctionTables, MachineType::TypeCompressedTaggedPointer()); + Node* ift_table = LOAD_FIXED_ARRAY_SLOT_ANY(ift_tables, table_index); + + *ift_size = LOAD_RAW( + ift_table, + wasm::ObjectAccess::ToTagged(WasmIndirectFunctionTable::kSizeOffset), + MachineType::Int32()); + + *ift_sig_ids = LOAD_RAW( + ift_table, + wasm::ObjectAccess::ToTagged(WasmIndirectFunctionTable::kSigIdsOffset), + MachineType::Pointer()); + + *ift_targets = LOAD_RAW( + ift_table, + wasm::ObjectAccess::ToTagged(WasmIndirectFunctionTable::kTargetsOffset), + MachineType::Pointer()); + + *ift_instances = LOAD_RAW( + ift_table, + wasm::ObjectAccess::ToTagged(WasmIndirectFunctionTable::kRefsOffset), + MachineType::TypeCompressedTaggedPointer()); +} + +Node* WasmGraphBuilder::BuildIndirectCall(uint32_t table_index, + uint32_t sig_index, Node** args, Node*** rets, wasm::WasmCodePosition position, IsReturnCall continuation) { DCHECK_NOT_NULL(args[0]); DCHECK_NOT_NULL(env_); - // Assume only one table for now. - wasm::FunctionSig* sig = env_->module->signatures[sig_index]; + // First we have to load the table. + Node* ift_size; + Node* ift_sig_ids; + Node* ift_targets; + Node* ift_instances; + LoadIndirectFunctionTable(table_index, &ift_size, &ift_sig_ids, &ift_targets, + &ift_instances); - Node* ift_size = - LOAD_INSTANCE_FIELD(IndirectFunctionTableSize, MachineType::Uint32()); + wasm::FunctionSig* sig = env_->module->signatures[sig_index]; MachineOperatorBuilder* machine = mcgraph()->machine(); Node* key = args[0]; @@ -2894,9 +2940,6 @@ Node* WasmGraphBuilder::BuildIndirectCall(uint32_t sig_index, Node** args, } // Load signature from the table and check. - Node* ift_sig_ids = - LOAD_INSTANCE_FIELD(IndirectFunctionTableSigIds, MachineType::Pointer()); - int32_t expected_sig_id = env_->module->signature_ids[sig_index]; Node* int32_scaled_key = Uint32ToUintptr( graph()->NewNode(machine->Word32Shl(), key, Int32Constant(2))); @@ -2909,11 +2952,6 @@ Node* WasmGraphBuilder::BuildIndirectCall(uint32_t sig_index, Node** args, TrapIfFalse(wasm::kTrapFuncSigMismatch, sig_match, position); - Node* ift_targets = - LOAD_INSTANCE_FIELD(IndirectFunctionTableTargets, MachineType::Pointer()); - Node* ift_instances = LOAD_INSTANCE_FIELD( - IndirectFunctionTableRefs, MachineType::TypeCompressedTaggedPointer()); - Node* tagged_scaled_key; if (kTaggedSize == kInt32Size) { tagged_scaled_key = int32_scaled_key; @@ -2955,48 +2993,6 @@ Node* WasmGraphBuilder::BuildIndirectCall(uint32_t sig_index, Node** args, } } -Node* WasmGraphBuilder::BuildIndirectCall(uint32_t table_index, - uint32_t sig_index, Node** args, - Node*** rets, - wasm::WasmCodePosition position, - IsReturnCall continuation) { - DCHECK_NOT_NULL(args[0]); - Node* entry_index = args[0]; - DCHECK_NOT_NULL(env_); - BoundsCheckTable(table_index, entry_index, position, wasm::kTrapFuncInvalid, - nullptr); - - DCHECK(Smi::IsValid(table_index)); - DCHECK(Smi::IsValid(sig_index)); - Node* runtime_args[]{ - graph()->NewNode(mcgraph()->common()->NumberConstant(table_index)), - BuildChangeUint31ToSmi(entry_index), - graph()->NewNode(mcgraph()->common()->NumberConstant(sig_index))}; - - Node* target_instance = BuildCallToRuntime( - Runtime::kWasmIndirectCallCheckSignatureAndGetTargetInstance, - runtime_args, arraysize(runtime_args)); - - // We reuse the runtime_args array here, even though we only need the first - // two arguments. - Node* call_target = BuildCallToRuntime( - Runtime::kWasmIndirectCallGetTargetAddress, runtime_args, 2); - - wasm::FunctionSig* sig = env_->module->signatures[sig_index]; - args[0] = call_target; - const UseRetpoline use_retpoline = - untrusted_code_mitigations_ ? kRetpoline : kNoRetpoline; - - switch (continuation) { - case kCallContinues: - return BuildWasmCall(sig, args, rets, position, target_instance, - use_retpoline); - case kReturnCall: - return BuildWasmReturnCall(sig, args, position, target_instance, - use_retpoline); - } -} - Node* WasmGraphBuilder::ReturnCall(uint32_t index, Node** args, wasm::WasmCodePosition position) { DCHECK_NULL(args[0]); @@ -3019,9 +3015,6 @@ Node* WasmGraphBuilder::ReturnCall(uint32_t index, Node** args, Node* WasmGraphBuilder::ReturnCallIndirect(uint32_t table_index, uint32_t sig_index, Node** args, wasm::WasmCodePosition position) { - if (table_index == 0) { - return BuildIndirectCall(sig_index, args, nullptr, position, kReturnCall); - } return BuildIndirectCall(table_index, sig_index, args, nullptr, position, kReturnCall); } @@ -3324,13 +3317,6 @@ Node* WasmGraphBuilder::CurrentMemoryPages() { return result; } -Node* WasmGraphBuilder::BuildLoadBuiltinFromInstance(int builtin_index) { - DCHECK(Builtins::IsBuiltinId(builtin_index)); - Node* isolate_root = LOAD_INSTANCE_FIELD(IsolateRoot, MachineType::Pointer()); - return LOAD_TAGGED_POINTER(isolate_root, - IsolateData::builtin_slot_offset(builtin_index)); -} - // Only call this function for code which is not reused across instantiations, // as we do not patch the embedded js_context. Node* WasmGraphBuilder::BuildCallToRuntimeWithContext( @@ -3492,7 +3478,7 @@ void WasmGraphBuilder::GetTableBaseAndOffset(uint32_t table_index, wasm::ObjectAccess::ElementOffsetInTaggedFixedArray(0))); } -Node* WasmGraphBuilder::GetTable(uint32_t table_index, Node* index, +Node* WasmGraphBuilder::TableGet(uint32_t table_index, Node* index, wasm::WasmCodePosition position) { if (env_->module->tables[table_index].type == wasm::kWasmAnyRef) { Node* base = nullptr; @@ -3501,7 +3487,7 @@ Node* WasmGraphBuilder::GetTable(uint32_t table_index, Node* index, return LOAD_RAW_NODE_OFFSET(base, offset, MachineType::TypeCompressedTagged()); } - // We access anyfunc tables through runtime calls. + // We access funcref tables through runtime calls. WasmTableGetDescriptor interface_descriptor; auto call_descriptor = Linkage::GetStubCallDescriptor( mcgraph()->zone(), // zone @@ -3521,7 +3507,7 @@ Node* WasmGraphBuilder::GetTable(uint32_t table_index, Node* index, Effect(), Control()))); } -Node* WasmGraphBuilder::SetTable(uint32_t table_index, Node* index, Node* val, +Node* WasmGraphBuilder::TableSet(uint32_t table_index, Node* index, Node* val, wasm::WasmCodePosition position) { if (env_->module->tables[table_index].type == wasm::kWasmAnyRef) { Node* base = nullptr; @@ -3530,7 +3516,7 @@ Node* WasmGraphBuilder::SetTable(uint32_t table_index, Node* index, Node* val, return STORE_RAW_NODE_OFFSET( base, offset, val, MachineRepresentation::kTagged, kFullWriteBarrier); } else { - // We access anyfunc tables through runtime calls. + // We access funcref tables through runtime calls. WasmTableSetDescriptor interface_descriptor; auto call_descriptor = Linkage::GetStubCallDescriptor( mcgraph()->zone(), // zone @@ -4000,6 +3986,30 @@ Node* WasmGraphBuilder::S128Zero() { Node* WasmGraphBuilder::SimdOp(wasm::WasmOpcode opcode, Node* const* inputs) { has_simd_ = true; switch (opcode) { + case wasm::kExprF64x2Splat: + return graph()->NewNode(mcgraph()->machine()->F64x2Splat(), inputs[0]); + case wasm::kExprF64x2Abs: + return graph()->NewNode(mcgraph()->machine()->F64x2Abs(), inputs[0]); + case wasm::kExprF64x2Neg: + return graph()->NewNode(mcgraph()->machine()->F64x2Neg(), inputs[0]); + case wasm::kExprF64x2Eq: + return graph()->NewNode(mcgraph()->machine()->F64x2Eq(), inputs[0], + inputs[1]); + case wasm::kExprF64x2Ne: + return graph()->NewNode(mcgraph()->machine()->F64x2Ne(), inputs[0], + inputs[1]); + case wasm::kExprF64x2Lt: + return graph()->NewNode(mcgraph()->machine()->F64x2Lt(), inputs[0], + inputs[1]); + case wasm::kExprF64x2Le: + return graph()->NewNode(mcgraph()->machine()->F64x2Le(), inputs[0], + inputs[1]); + case wasm::kExprF64x2Gt: + return graph()->NewNode(mcgraph()->machine()->F64x2Lt(), inputs[1], + inputs[0]); + case wasm::kExprF64x2Ge: + return graph()->NewNode(mcgraph()->machine()->F64x2Le(), inputs[1], + inputs[0]); case wasm::kExprF32x4Splat: return graph()->NewNode(mcgraph()->machine()->F32x4Splat(), inputs[0]); case wasm::kExprF32x4SConvertI32x4: @@ -4054,6 +4064,49 @@ Node* WasmGraphBuilder::SimdOp(wasm::WasmOpcode opcode, Node* const* inputs) { case wasm::kExprF32x4Ge: return graph()->NewNode(mcgraph()->machine()->F32x4Le(), inputs[1], inputs[0]); + case wasm::kExprI64x2Splat: + return graph()->NewNode(mcgraph()->machine()->I64x2Splat(), inputs[0]); + case wasm::kExprI64x2Neg: + return graph()->NewNode(mcgraph()->machine()->I64x2Neg(), inputs[0]); + case wasm::kExprI64x2Add: + return graph()->NewNode(mcgraph()->machine()->I64x2Add(), inputs[0], + inputs[1]); + case wasm::kExprI64x2Sub: + return graph()->NewNode(mcgraph()->machine()->I64x2Sub(), inputs[0], + inputs[1]); + case wasm::kExprI64x2Mul: + return graph()->NewNode(mcgraph()->machine()->I64x2Mul(), inputs[0], + inputs[1]); + case wasm::kExprI64x2Eq: + return graph()->NewNode(mcgraph()->machine()->I64x2Eq(), inputs[0], + inputs[1]); + case wasm::kExprI64x2Ne: + return graph()->NewNode(mcgraph()->machine()->I64x2Ne(), inputs[0], + inputs[1]); + case wasm::kExprI64x2LtS: + return graph()->NewNode(mcgraph()->machine()->I64x2GtS(), inputs[1], + inputs[0]); + case wasm::kExprI64x2LeS: + return graph()->NewNode(mcgraph()->machine()->I64x2GeS(), inputs[1], + inputs[0]); + case wasm::kExprI64x2GtS: + return graph()->NewNode(mcgraph()->machine()->I64x2GtS(), inputs[0], + inputs[1]); + case wasm::kExprI64x2GeS: + return graph()->NewNode(mcgraph()->machine()->I64x2GeS(), inputs[0], + inputs[1]); + case wasm::kExprI64x2LtU: + return graph()->NewNode(mcgraph()->machine()->I64x2GtU(), inputs[1], + inputs[0]); + case wasm::kExprI64x2LeU: + return graph()->NewNode(mcgraph()->machine()->I64x2GeU(), inputs[1], + inputs[0]); + case wasm::kExprI64x2GtU: + return graph()->NewNode(mcgraph()->machine()->I64x2GtU(), inputs[0], + inputs[1]); + case wasm::kExprI64x2GeU: + return graph()->NewNode(mcgraph()->machine()->I64x2GeU(), inputs[0], + inputs[1]); case wasm::kExprI32x4Splat: return graph()->NewNode(mcgraph()->machine()->I32x4Splat(), inputs[0]); case wasm::kExprI32x4SConvertF32x4: @@ -4305,6 +4358,10 @@ Node* WasmGraphBuilder::SimdOp(wasm::WasmOpcode opcode, Node* const* inputs) { case wasm::kExprS128Select: return graph()->NewNode(mcgraph()->machine()->S128Select(), inputs[2], inputs[0], inputs[1]); + case wasm::kExprS1x2AnyTrue: + return graph()->NewNode(mcgraph()->machine()->S1x2AnyTrue(), inputs[0]); + case wasm::kExprS1x2AllTrue: + return graph()->NewNode(mcgraph()->machine()->S1x2AllTrue(), inputs[0]); case wasm::kExprS1x4AnyTrue: return graph()->NewNode(mcgraph()->machine()->S1x4AnyTrue(), inputs[0]); case wasm::kExprS1x4AllTrue: @@ -4326,12 +4383,24 @@ Node* WasmGraphBuilder::SimdLaneOp(wasm::WasmOpcode opcode, uint8_t lane, Node* const* inputs) { has_simd_ = true; switch (opcode) { + case wasm::kExprF64x2ExtractLane: + return graph()->NewNode(mcgraph()->machine()->F64x2ExtractLane(lane), + inputs[0]); + case wasm::kExprF64x2ReplaceLane: + return graph()->NewNode(mcgraph()->machine()->F64x2ReplaceLane(lane), + inputs[0], inputs[1]); case wasm::kExprF32x4ExtractLane: return graph()->NewNode(mcgraph()->machine()->F32x4ExtractLane(lane), inputs[0]); case wasm::kExprF32x4ReplaceLane: return graph()->NewNode(mcgraph()->machine()->F32x4ReplaceLane(lane), inputs[0], inputs[1]); + case wasm::kExprI64x2ExtractLane: + return graph()->NewNode(mcgraph()->machine()->I64x2ExtractLane(lane), + inputs[0]); + case wasm::kExprI64x2ReplaceLane: + return graph()->NewNode(mcgraph()->machine()->I64x2ReplaceLane(lane), + inputs[0], inputs[1]); case wasm::kExprI32x4ExtractLane: return graph()->NewNode(mcgraph()->machine()->I32x4ExtractLane(lane), inputs[0]); @@ -4359,6 +4428,14 @@ Node* WasmGraphBuilder::SimdShiftOp(wasm::WasmOpcode opcode, uint8_t shift, Node* const* inputs) { has_simd_ = true; switch (opcode) { + case wasm::kExprI64x2Shl: + return graph()->NewNode(mcgraph()->machine()->I64x2Shl(shift), inputs[0]); + case wasm::kExprI64x2ShrS: + return graph()->NewNode(mcgraph()->machine()->I64x2ShrS(shift), + inputs[0]); + case wasm::kExprI64x2ShrU: + return graph()->NewNode(mcgraph()->machine()->I64x2ShrU(shift), + inputs[0]); case wasm::kExprI32x4Shl: return graph()->NewNode(mcgraph()->machine()->I32x4Shl(shift), inputs[0]); case wasm::kExprI32x4ShrS: @@ -4612,6 +4689,11 @@ Node* WasmGraphBuilder::AtomicOp(wasm::WasmOpcode opcode, Node* const* inputs, return SetEffect(node); } +Node* WasmGraphBuilder::AtomicFence() { + return SetEffect(graph()->NewNode(mcgraph()->machine()->MemBarrier(), + Effect(), Control())); +} + #undef ATOMIC_BINOP_LIST #undef ATOMIC_CMP_EXCHG_LIST #undef ATOMIC_LOAD_LIST @@ -4636,8 +4718,19 @@ Node* WasmGraphBuilder::MemoryInit(uint32_t data_segment_index, Node* dst, Node* src, Node* size, wasm::WasmCodePosition position) { CheckDataSegmentIsPassiveAndNotDropped(data_segment_index, position); - Node* dst_fail = BoundsCheckMemRange(&dst, &size, position); auto m = mcgraph()->machine(); + auto common = mcgraph()->common(); + Node* size_null_check = + graph()->NewNode(m->Word32Equal(), size, mcgraph()->Int32Constant(0)); + Node* size_null_branch = graph()->NewNode(common->Branch(BranchHint::kFalse), + size_null_check, Control()); + + Node* size_null_etrue = Effect(); + Node* size_null_if_false = + graph()->NewNode(common->IfFalse(), size_null_branch); + SetControl(size_null_if_false); + + Node* dst_fail = BoundsCheckMemRange(&dst, &size, position); Node* seg_index = Uint32Constant(data_segment_index); Node* src_fail; @@ -4679,9 +4772,16 @@ Node* WasmGraphBuilder::MemoryInit(uint32_t data_segment_index, Node* dst, MachineType::Uint32()}; MachineSignature sig(0, 3, sig_types); BuildCCall(&sig, function, dst, src, size); - return TrapIfTrue(wasm::kTrapMemOutOfBounds, - graph()->NewNode(m->Word32Or(), dst_fail, src_fail), - position); + TrapIfTrue(wasm::kTrapMemOutOfBounds, + graph()->NewNode(m->Word32Or(), dst_fail, src_fail), position); + Node* size_null_if_true = + graph()->NewNode(common->IfTrue(), size_null_branch); + + Node* merge = SetControl( + graph()->NewNode(common->Merge(2), size_null_if_true, Control())); + SetEffect( + graph()->NewNode(common->EffectPhi(2), size_null_etrue, Effect(), merge)); + return merge; } Node* WasmGraphBuilder::DataDrop(uint32_t data_segment_index, @@ -4699,16 +4799,19 @@ Node* WasmGraphBuilder::DataDrop(uint32_t data_segment_index, Node* WasmGraphBuilder::MemoryCopy(Node* dst, Node* src, Node* size, wasm::WasmCodePosition position) { auto m = mcgraph()->machine(); - // The data must be copied backward if the regions overlap and src < dst. The - // regions overlap if {src + size > dst && dst + size > src}. Since we already - // test that {src < dst}, we know that {dst + size > src}, so this simplifies - // to just {src + size > dst}. That sum can overflow, but if we subtract - // {size} from both sides of the inequality we get the equivalent test - // {size > dst - src}. - Node* copy_backward = graph()->NewNode( - m->Word32And(), graph()->NewNode(m->Uint32LessThan(), src, dst), - graph()->NewNode(m->Uint32LessThan(), - graph()->NewNode(m->Int32Sub(), dst, src), size)); + auto common = mcgraph()->common(); + // If size == 0, then memory.copy is a no-op. + Node* size_null_check = + graph()->NewNode(m->Word32Equal(), size, mcgraph()->Int32Constant(0)); + Node* size_null_branch = graph()->NewNode(common->Branch(BranchHint::kFalse), + size_null_check, Control()); + + Node* size_null_etrue = Effect(); + Node* size_null_if_false = + graph()->NewNode(common->IfFalse(), size_null_branch); + SetControl(size_null_if_false); + // The data must be copied backward if src < dst. + Node* copy_backward = graph()->NewNode(m->Uint32LessThan(), src, dst); Node* dst_fail = BoundsCheckMemRange(&dst, &size, position); @@ -4728,13 +4831,32 @@ Node* WasmGraphBuilder::MemoryCopy(Node* dst, Node* src, Node* size, MachineType::Uint32()}; MachineSignature sig(0, 3, sig_types); BuildCCall(&sig, function, dst, src, size); - return TrapIfTrue(wasm::kTrapMemOutOfBounds, - graph()->NewNode(m->Word32Or(), dst_fail, src_fail), - position); + TrapIfTrue(wasm::kTrapMemOutOfBounds, + graph()->NewNode(m->Word32Or(), dst_fail, src_fail), position); + Node* size_null_if_true = + graph()->NewNode(common->IfTrue(), size_null_branch); + + Node* merge = SetControl( + graph()->NewNode(common->Merge(2), size_null_if_true, Control())); + SetEffect( + graph()->NewNode(common->EffectPhi(2), size_null_etrue, Effect(), merge)); + return merge; } Node* WasmGraphBuilder::MemoryFill(Node* dst, Node* value, Node* size, wasm::WasmCodePosition position) { + auto machine = mcgraph()->machine(); + auto common = mcgraph()->common(); + // If size == 0, then memory.copy is a no-op. + Node* size_null_check = graph()->NewNode(machine->Word32Equal(), size, + mcgraph()->Int32Constant(0)); + Node* size_null_branch = graph()->NewNode(common->Branch(BranchHint::kFalse), + size_null_check, Control()); + + Node* size_null_etrue = Effect(); + Node* size_null_if_false = + graph()->NewNode(common->IfFalse(), size_null_branch); + SetControl(size_null_if_false); Node* fail = BoundsCheckMemRange(&dst, &size, position); Node* function = graph()->NewNode(mcgraph()->common()->ExternalConstant( ExternalReference::wasm_memory_fill())); @@ -4742,7 +4864,15 @@ Node* WasmGraphBuilder::MemoryFill(Node* dst, Node* value, Node* size, MachineType::Uint32()}; MachineSignature sig(0, 3, sig_types); BuildCCall(&sig, function, dst, value, size); - return TrapIfTrue(wasm::kTrapMemOutOfBounds, fail, position); + TrapIfTrue(wasm::kTrapMemOutOfBounds, fail, position); + Node* size_null_if_true = + graph()->NewNode(common->IfTrue(), size_null_branch); + + Node* merge = SetControl( + graph()->NewNode(common->Merge(2), size_null_if_true, Control())); + SetEffect( + graph()->NewNode(common->EffectPhi(2), size_null_etrue, Effect(), merge)); + return merge; } Node* WasmGraphBuilder::CheckElemSegmentIsPassiveAndNotDropped( @@ -4789,13 +4919,13 @@ Node* WasmGraphBuilder::ElemDrop(uint32_t elem_segment_index, mcgraph()->Int32Constant(1), Effect(), Control())); } -Node* WasmGraphBuilder::TableCopy(uint32_t table_src_index, - uint32_t table_dst_index, Node* dst, +Node* WasmGraphBuilder::TableCopy(uint32_t table_dst_index, + uint32_t table_src_index, Node* dst, Node* src, Node* size, wasm::WasmCodePosition position) { Node* args[] = { - graph()->NewNode(mcgraph()->common()->NumberConstant(table_src_index)), graph()->NewNode(mcgraph()->common()->NumberConstant(table_dst_index)), + graph()->NewNode(mcgraph()->common()->NumberConstant(table_src_index)), BuildConvertUint32ToSmiWithSaturation(dst, FLAG_wasm_max_table_size), BuildConvertUint32ToSmiWithSaturation(src, FLAG_wasm_max_table_size), BuildConvertUint32ToSmiWithSaturation(size, FLAG_wasm_max_table_size)}; @@ -4878,28 +5008,6 @@ void WasmGraphBuilder::RemoveBytecodePositionDecorator() { } namespace { -bool must_record_function_compilation(Isolate* isolate) { - return isolate->logger()->is_listening_to_code_events() || - isolate->is_profiling(); -} - -PRINTF_FORMAT(4, 5) -void RecordFunctionCompilation(CodeEventListener::LogEventsAndTags tag, - Isolate* isolate, Handle<Code> code, - const char* format, ...) { - DCHECK(must_record_function_compilation(isolate)); - - ScopedVector<char> buffer(128); - va_list arguments; - va_start(arguments, format); - int len = VSNPrintF(buffer, format, arguments); - CHECK_LT(0, len); - va_end(arguments); - Handle<String> name_str = - isolate->factory()->NewStringFromAsciiChecked(buffer.begin()); - PROFILE(isolate, CodeCreateEvent(tag, AbstractCode::cast(*code), *name_str)); -} - class WasmWrapperGraphBuilder : public WasmGraphBuilder { public: WasmWrapperGraphBuilder(Zone* zone, JSGraph* jsgraph, wasm::FunctionSig* sig, @@ -4914,12 +5022,12 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder { Node* BuildAllocateHeapNumberWithValue(Node* value, Node* control) { MachineOperatorBuilder* machine = mcgraph()->machine(); CommonOperatorBuilder* common = mcgraph()->common(); - Node* target = (stub_mode_ == StubCallMode::kCallWasmRuntimeStub) - ? mcgraph()->RelocatableIntPtrConstant( - wasm::WasmCode::kWasmAllocateHeapNumber, - RelocInfo::WASM_STUB_CALL) - : jsgraph()->HeapConstant( - BUILTIN_CODE(isolate_, AllocateHeapNumber)); + Node* target = + (stub_mode_ == StubCallMode::kCallWasmRuntimeStub) + ? mcgraph()->RelocatableIntPtrConstant( + wasm::WasmCode::kWasmAllocateHeapNumber, + RelocInfo::WASM_STUB_CALL) + : BuildLoadBuiltinFromInstance(Builtins::kAllocateHeapNumber); if (!allocate_heap_number_operator_.is_set()) { auto call_descriptor = Linkage::GetStubCallDescriptor( mcgraph()->zone(), AllocateHeapNumberDescriptor(), 0, @@ -4956,6 +5064,34 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder { return mcgraph()->IntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag); } + Node* BuildLoadUndefinedValueFromInstance() { + if (undefined_value_node_ == nullptr) { + Node* isolate_root = graph()->NewNode( + mcgraph()->machine()->Load(MachineType::Pointer()), + instance_node_.get(), + mcgraph()->Int32Constant(WASM_INSTANCE_OBJECT_OFFSET(IsolateRoot)), + graph()->start(), graph()->start()); + undefined_value_node_ = InsertDecompressionIfNeeded( + MachineType::TypeCompressedTaggedPointer(), + graph()->NewNode( + mcgraph()->machine()->Load( + MachineType::TypeCompressedTaggedPointer()), + isolate_root, + mcgraph()->Int32Constant( + IsolateData::root_slot_offset(RootIndex::kUndefinedValue)), + isolate_root, graph()->start())); + } + return undefined_value_node_.get(); + } + + Node* BuildLoadBuiltinFromInstance(int builtin_index) { + DCHECK(Builtins::IsBuiltinId(builtin_index)); + Node* isolate_root = + LOAD_INSTANCE_FIELD(IsolateRoot, MachineType::Pointer()); + return LOAD_TAGGED_POINTER(isolate_root, + IsolateData::builtin_slot_offset(builtin_index)); + } + Node* BuildChangeInt32ToTagged(Node* value) { MachineOperatorBuilder* machine = mcgraph()->machine(); CommonOperatorBuilder* common = mcgraph()->common(); @@ -5096,7 +5232,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder { (stub_mode_ == StubCallMode::kCallWasmRuntimeStub) ? mcgraph()->RelocatableIntPtrConstant( wasm::WasmCode::kWasmToNumber, RelocInfo::WASM_STUB_CALL) - : jsgraph()->HeapConstant(BUILTIN_CODE(isolate_, ToNumber)); + : BuildLoadBuiltinFromInstance(Builtins::kToNumber); Node* result = SetEffect( graph()->NewNode(mcgraph()->common()->Call(call_descriptor), stub_code, @@ -5126,8 +5262,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder { SetControl(is_heap_object.if_true); Node* orig_effect = Effect(); - Node* undefined_node = LOAD_INSTANCE_FIELD( - UndefinedValue, MachineType::TypeCompressedTaggedPointer()); + Node* undefined_node = BuildLoadUndefinedValueFromInstance(); Node* check_undefined = graph()->NewNode(machine->WordEqual(), value, undefined_node); Node* effect_tagged = Effect(); @@ -5173,8 +5308,8 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder { case wasm::kWasmF64: return BuildChangeFloat64ToTagged(node); case wasm::kWasmAnyRef: - case wasm::kWasmAnyFunc: - case wasm::kWasmExceptRef: + case wasm::kWasmFuncRef: + case wasm::kWasmExnRef: return node; default: UNREACHABLE(); @@ -5196,7 +5331,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder { (stub_mode_ == StubCallMode::kCallWasmRuntimeStub) ? mcgraph()->RelocatableIntPtrConstant( wasm::WasmCode::kWasmI64ToBigInt, RelocInfo::WASM_STUB_CALL) - : jsgraph()->HeapConstant(BUILTIN_CODE(isolate_, I64ToBigInt)); + : BuildLoadBuiltinFromInstance(Builtins::kI64ToBigInt); return SetEffect( SetControl(graph()->NewNode(mcgraph()->common()->Call(call_descriptor), @@ -5218,7 +5353,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder { (stub_mode_ == StubCallMode::kCallWasmRuntimeStub) ? mcgraph()->RelocatableIntPtrConstant( wasm::WasmCode::kWasmBigIntToI64, RelocInfo::WASM_STUB_CALL) - : jsgraph()->HeapConstant(BUILTIN_CODE(isolate_, BigIntToI64)); + : BuildLoadBuiltinFromInstance(Builtins::kBigIntToI64); return SetEffect(SetControl( graph()->NewNode(mcgraph()->common()->Call(call_descriptor), target, @@ -5228,15 +5363,15 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder { Node* FromJS(Node* node, Node* js_context, wasm::ValueType type) { DCHECK_NE(wasm::kWasmStmt, type); - // The parameter is of type anyref or except_ref, we take it as is. - if (type == wasm::kWasmAnyRef || type == wasm::kWasmExceptRef) { + // The parameter is of type anyref or exnref, we take it as is. + if (type == wasm::kWasmAnyRef || type == wasm::kWasmExnRef) { return node; } - if (type == wasm::kWasmAnyFunc) { + if (type == wasm::kWasmFuncRef) { Node* check = BuildChangeSmiToInt32(SetEffect(BuildCallToRuntimeWithContext( - Runtime::kWasmIsValidAnyFuncValue, js_context, &node, 1, effect_, + Runtime::kWasmIsValidFuncRefValue, js_context, &node, 1, effect_, Control()))); Diamond type_check(graph(), mcgraph()->common(), check, @@ -5471,8 +5606,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder { // The callable is passed as the last parameter, after WASM arguments. Node* callable_node = Param(wasm_count + 1); - Node* undefined_node = LOAD_INSTANCE_FIELD( - UndefinedValue, MachineType::TypeCompressedTaggedPointer()); + Node* undefined_node = BuildLoadUndefinedValueFromInstance(); Node* call = nullptr; bool sloppy_receiver = true; @@ -5811,22 +5945,26 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder { } void BuildCWasmEntry() { - // Build the start and the JS parameter nodes. - SetEffect(SetControl(Start(CWasmEntryParameters::kNumParameters + 5))); + // +1 offset for first parameter index being -1. + SetEffect(SetControl(Start(CWasmEntryParameters::kNumParameters + 1))); - // Create parameter nodes (offset by 1 for the receiver parameter). - Node* code_entry = Param(CWasmEntryParameters::kCodeEntry + 1); - Node* object_ref_node = Param(CWasmEntryParameters::kObjectRef + 1); - Node* arg_buffer = Param(CWasmEntryParameters::kArgumentsBuffer + 1); + Node* code_entry = Param(CWasmEntryParameters::kCodeEntry); + Node* object_ref = Param(CWasmEntryParameters::kObjectRef); + Node* arg_buffer = Param(CWasmEntryParameters::kArgumentsBuffer); + Node* c_entry_fp = Param(CWasmEntryParameters::kCEntryFp); + + Node* fp_value = graph()->NewNode(mcgraph()->machine()->LoadFramePointer()); + STORE_RAW(fp_value, TypedFrameConstants::kFirstPushedFrameValueOffset, + c_entry_fp, MachineType::PointerRepresentation(), + kNoWriteBarrier); int wasm_arg_count = static_cast<int>(sig_->parameter_count()); - int arg_count = - wasm_arg_count + 4; // code, object_ref_node, control, effect + int arg_count = wasm_arg_count + 4; // code, object_ref, control, effect Node** args = Buffer(arg_count); int pos = 0; args[pos++] = code_entry; - args[pos++] = object_ref_node; + args[pos++] = object_ref; int offset = 0; for (wasm::ValueType type : sig_->parameters()) { @@ -5847,26 +5985,43 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder { Node* call = SetEffect(graph()->NewNode( mcgraph()->common()->Call(call_descriptor), arg_count, args)); - // Store the return value. - DCHECK_GE(1, sig_->return_count()); - if (sig_->return_count() == 1) { + Node* if_success = graph()->NewNode(mcgraph()->common()->IfSuccess(), call); + Node* if_exception = + graph()->NewNode(mcgraph()->common()->IfException(), call, call); + + // Handle exception: return it. + SetControl(if_exception); + Return(if_exception); + + // Handle success: store the return value(s). + SetControl(if_success); + pos = 0; + offset = 0; + for (wasm::ValueType type : sig_->returns()) { StoreRepresentation store_rep( - wasm::ValueTypes::MachineRepresentationFor(sig_->GetReturn()), - kNoWriteBarrier); + 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(0), call, Effect(), - Control())); + arg_buffer, Int32Constant(offset), value, + Effect(), Control())); + offset += wasm::ValueTypes::ElementSizeInBytes(type); + pos++; } + Return(jsgraph()->SmiConstant(0)); if (mcgraph()->machine()->Is32() && ContainsInt64(sig_)) { MachineRepresentation sig_reps[] = { - MachineRepresentation::kWord32, // return value - MachineRepresentation::kTagged, // receiver - MachineRepresentation::kTagged, // arg0 (code) - MachineRepresentation::kTagged // arg1 (buffer) + MachineType::PointerRepresentation(), // return value + MachineType::PointerRepresentation(), // target + MachineRepresentation::kTagged, // object_ref + MachineType::PointerRepresentation(), // argv + MachineType::PointerRepresentation() // c_entry_fp }; - Signature<MachineRepresentation> c_entry_sig(1, 2, sig_reps); + Signature<MachineRepresentation> c_entry_sig(1, 4, sig_reps); Int64Lowering r(mcgraph()->graph(), mcgraph()->machine(), mcgraph()->common(), mcgraph()->zone(), &c_entry_sig); r.LowerGraph(); @@ -5879,6 +6034,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder { Isolate* const isolate_; JSGraph* jsgraph_; StubCallMode stub_mode_; + SetOncePointer<Node> undefined_value_node_; SetOncePointer<const Operator> allocate_heap_number_operator_; wasm::WasmFeatures enabled_features_; }; @@ -5901,27 +6057,25 @@ void AppendSignature(char* buffer, size_t max_name_len, } // namespace -MaybeHandle<Code> CompileJSToWasmWrapper(Isolate* isolate, - wasm::FunctionSig* sig, - bool is_import) { - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm"), - "CompileJSToWasmWrapper"); +std::unique_ptr<OptimizedCompilationJob> NewJSToWasmCompilationJob( + Isolate* isolate, wasm::FunctionSig* sig, bool is_import) { //---------------------------------------------------------------------------- // Create the Graph. //---------------------------------------------------------------------------- - Zone zone(isolate->allocator(), ZONE_NAME); - Graph graph(&zone); - CommonOperatorBuilder common(&zone); + std::unique_ptr<Zone> zone = + base::make_unique<Zone>(isolate->allocator(), ZONE_NAME); + Graph* graph = new (zone.get()) Graph(zone.get()); + CommonOperatorBuilder common(zone.get()); MachineOperatorBuilder machine( - &zone, MachineType::PointerRepresentation(), + zone.get(), MachineType::PointerRepresentation(), InstructionSelector::SupportedMachineOperatorFlags(), InstructionSelector::AlignmentRequirements()); - JSGraph jsgraph(isolate, &graph, &common, nullptr, nullptr, &machine); + JSGraph jsgraph(isolate, graph, &common, nullptr, nullptr, &machine); Node* control = nullptr; Node* effect = nullptr; - WasmWrapperGraphBuilder builder(&zone, &jsgraph, sig, nullptr, + WasmWrapperGraphBuilder builder(zone.get(), &jsgraph, sig, nullptr, StubCallMode::kCallCodeObject, wasm::WasmFeaturesFromIsolate(isolate)); builder.set_control_ptr(&control); @@ -5929,73 +6083,66 @@ MaybeHandle<Code> CompileJSToWasmWrapper(Isolate* isolate, builder.BuildJSToWasmWrapper(is_import); //---------------------------------------------------------------------------- - // Run the compilation pipeline. + // Create the compilation job. //---------------------------------------------------------------------------- static constexpr size_t kMaxNameLen = 128; - char debug_name[kMaxNameLen] = "js_to_wasm:"; - AppendSignature(debug_name, kMaxNameLen, sig); + auto debug_name = std::unique_ptr<char[]>(new char[kMaxNameLen]); + memcpy(debug_name.get(), "js_to_wasm:", 12); + AppendSignature(debug_name.get(), kMaxNameLen, sig); - // Schedule and compile to machine code. int params = static_cast<int>(sig->parameter_count()); CallDescriptor* incoming = Linkage::GetJSCallDescriptor( - &zone, false, params + 1, CallDescriptor::kNoFlags); + zone.get(), false, params + 1, CallDescriptor::kNoFlags); - MaybeHandle<Code> maybe_code = Pipeline::GenerateCodeForWasmHeapStub( - isolate, incoming, &graph, Code::JS_TO_WASM_FUNCTION, debug_name, - WasmAssemblerOptions()); - Handle<Code> code; - if (!maybe_code.ToHandle(&code)) { - return maybe_code; - } -#ifdef ENABLE_DISASSEMBLER - if (FLAG_print_opt_code) { - CodeTracer::Scope tracing_scope(isolate->GetCodeTracer()); - OFStream os(tracing_scope.file()); - code->Disassemble(debug_name, os); - } -#endif - - if (must_record_function_compilation(isolate)) { - RecordFunctionCompilation(CodeEventListener::STUB_TAG, isolate, code, "%s", - debug_name); - } - - return code; + return Pipeline::NewWasmHeapStubCompilationJob( + isolate, incoming, std::move(zone), graph, Code::JS_TO_WASM_FUNCTION, + std::move(debug_name), WasmAssemblerOptions()); } -WasmImportCallKind GetWasmImportCallKind(Handle<JSReceiver> target, - wasm::FunctionSig* expected_sig, - bool has_bigint_feature) { - if (WasmExportedFunction::IsWasmExportedFunction(*target)) { - auto imported_function = WasmExportedFunction::cast(*target); - auto func_index = imported_function.function_index(); - auto module = imported_function.instance().module(); +std::pair<WasmImportCallKind, Handle<JSReceiver>> ResolveWasmImportCall( + Handle<JSReceiver> callable, wasm::FunctionSig* expected_sig, + bool has_bigint_feature) { + if (WasmExportedFunction::IsWasmExportedFunction(*callable)) { + auto imported_function = Handle<WasmExportedFunction>::cast(callable); + auto func_index = imported_function->function_index(); + auto module = imported_function->instance().module(); wasm::FunctionSig* imported_sig = module->functions[func_index].sig; if (*imported_sig != *expected_sig) { - return WasmImportCallKind::kLinkError; + return std::make_pair(WasmImportCallKind::kLinkError, callable); } - if (static_cast<uint32_t>(func_index) < module->num_imported_functions) { - // TODO(wasm): this redirects all imported-reexported functions - // through the call builtin. Fall through to JS function cases below? - return WasmImportCallKind::kUseCallBuiltin; + if (static_cast<uint32_t>(func_index) >= module->num_imported_functions) { + return std::make_pair(WasmImportCallKind::kWasmToWasm, callable); } - return WasmImportCallKind::kWasmToWasm; - } - if (WasmCapiFunction::IsWasmCapiFunction(*target)) { - WasmCapiFunction capi_function = WasmCapiFunction::cast(*target); - if (!capi_function.IsSignatureEqual(expected_sig)) { - return WasmImportCallKind::kLinkError; + Isolate* isolate = callable->GetIsolate(); + // Resolve the short-cut to the underlying callable and continue. + Handle<WasmInstanceObject> instance(imported_function->instance(), isolate); + ImportedFunctionEntry entry(instance, func_index); + callable = handle(entry.callable(), isolate); + } + if (WasmJSFunction::IsWasmJSFunction(*callable)) { + auto js_function = Handle<WasmJSFunction>::cast(callable); + if (!js_function->MatchesSignature(expected_sig)) { + return std::make_pair(WasmImportCallKind::kLinkError, callable); + } + Isolate* isolate = callable->GetIsolate(); + // Resolve the short-cut to the underlying callable and continue. + callable = handle(js_function->GetCallable(), isolate); + } + if (WasmCapiFunction::IsWasmCapiFunction(*callable)) { + auto capi_function = Handle<WasmCapiFunction>::cast(callable); + if (!capi_function->IsSignatureEqual(expected_sig)) { + return std::make_pair(WasmImportCallKind::kLinkError, callable); } - return WasmImportCallKind::kWasmToCapi; + 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, has_bigint_feature)) { - return WasmImportCallKind::kRuntimeTypeError; + return std::make_pair(WasmImportCallKind::kRuntimeTypeError, callable); } // For JavaScript calls, determine whether the target has an arity match // and whether it has a sloppy receiver. - if (target->IsJSFunction()) { - Handle<JSFunction> function = Handle<JSFunction>::cast(target); + if (callable->IsJSFunction()) { + Handle<JSFunction> function = Handle<JSFunction>::cast(callable); SharedFunctionInfo shared = function->shared(); // Check for math intrinsics. @@ -6004,7 +6151,9 @@ WasmImportCallKind GetWasmImportCallKind(Handle<JSReceiver> target, wasm::FunctionSig* sig = wasm::WasmOpcodes::Signature(wasm::kExpr##name); \ if (!sig) sig = wasm::WasmOpcodes::AsmjsSignature(wasm::kExpr##name); \ DCHECK_NOT_NULL(sig); \ - if (*expected_sig == *sig) return WasmImportCallKind::k##name; \ + if (*expected_sig == *sig) { \ + return std::make_pair(WasmImportCallKind::k##name, callable); \ + } \ } #define COMPARE_SIG_FOR_BUILTIN_F64(name) \ case Builtins::kMath##name: \ @@ -6051,19 +6200,23 @@ WasmImportCallKind GetWasmImportCallKind(Handle<JSReceiver> target, if (IsClassConstructor(shared.kind())) { // Class constructor will throw anyway. - return WasmImportCallKind::kUseCallBuiltin; + return std::make_pair(WasmImportCallKind::kUseCallBuiltin, callable); } bool sloppy = is_sloppy(shared.language_mode()) && !shared.native(); if (shared.internal_formal_parameter_count() == expected_sig->parameter_count()) { - return sloppy ? WasmImportCallKind::kJSFunctionArityMatchSloppy - : WasmImportCallKind::kJSFunctionArityMatch; + return std::make_pair( + sloppy ? WasmImportCallKind::kJSFunctionArityMatchSloppy + : WasmImportCallKind::kJSFunctionArityMatch, + callable); } - return sloppy ? WasmImportCallKind::kJSFunctionArityMismatchSloppy - : WasmImportCallKind::kJSFunctionArityMismatch; + return std::make_pair( + sloppy ? WasmImportCallKind::kJSFunctionArityMismatchSloppy + : WasmImportCallKind::kJSFunctionArityMismatch, + callable); } // Unknown case. Use the call builtin. - return WasmImportCallKind::kUseCallBuiltin; + return std::make_pair(WasmImportCallKind::kUseCallBuiltin, callable); } wasm::WasmOpcode GetMathIntrinsicOpcode(WasmImportCallKind kind, @@ -6103,10 +6256,9 @@ wasm::WasmOpcode GetMathIntrinsicOpcode(WasmImportCallKind kind, #undef CASE } -wasm::WasmCode* CompileWasmMathIntrinsic(wasm::WasmEngine* wasm_engine, - wasm::NativeModule* native_module, - WasmImportCallKind kind, - wasm::FunctionSig* sig) { +wasm::WasmCompilationResult CompileWasmMathIntrinsic( + wasm::WasmEngine* wasm_engine, WasmImportCallKind kind, + wasm::FunctionSig* sig) { DCHECK_EQ(1, sig->return_count()); TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm"), @@ -6125,7 +6277,7 @@ wasm::WasmCode* CompileWasmMathIntrinsic(wasm::WasmEngine* wasm_engine, InstructionSelector::AlignmentRequirements())); wasm::CompilationEnv env( - native_module->module(), wasm::UseTrapHandler::kNoTrapHandler, + nullptr, wasm::UseTrapHandler::kNoTrapHandler, wasm::RuntimeExceptionSupport::kNoRuntimeExceptionSupport, wasm::kAllWasmFeatures, wasm::LowerSimd::kNoLowerSimd); @@ -6167,21 +6319,12 @@ wasm::WasmCode* CompileWasmMathIntrinsic(wasm::WasmEngine* wasm_engine, wasm_engine, call_descriptor, mcgraph, Code::WASM_FUNCTION, wasm::WasmCode::kFunction, debug_name, WasmStubAssemblerOptions(), source_positions); - std::unique_ptr<wasm::WasmCode> wasm_code = native_module->AddCode( - wasm::WasmCode::kAnonymousFuncIndex, result.code_desc, - result.frame_slot_count, result.tagged_parameter_slots, - std::move(result.protected_instructions), - std::move(result.source_positions), wasm::WasmCode::kFunction, - wasm::ExecutionTier::kNone); - // TODO(titzer): add counters for math intrinsic code size / allocation - return native_module->PublishCode(std::move(wasm_code)); + return result; } -wasm::WasmCode* CompileWasmImportCallWrapper(wasm::WasmEngine* wasm_engine, - wasm::NativeModule* native_module, - WasmImportCallKind kind, - wasm::FunctionSig* sig, - bool source_positions) { +wasm::WasmCompilationResult CompileWasmImportCallWrapper( + wasm::WasmEngine* wasm_engine, wasm::CompilationEnv* env, + WasmImportCallKind kind, wasm::FunctionSig* sig, bool source_positions) { DCHECK_NE(WasmImportCallKind::kLinkError, kind); DCHECK_NE(WasmImportCallKind::kWasmToWasm, kind); @@ -6189,7 +6332,7 @@ wasm::WasmCode* CompileWasmImportCallWrapper(wasm::WasmEngine* wasm_engine, if (FLAG_wasm_math_intrinsics && kind >= WasmImportCallKind::kFirstMathIntrinsic && kind <= WasmImportCallKind::kLastMathIntrinsic) { - return CompileWasmMathIntrinsic(wasm_engine, native_module, kind, sig); + return CompileWasmMathIntrinsic(wasm_engine, kind, sig); } TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm"), @@ -6214,7 +6357,7 @@ wasm::WasmCode* CompileWasmImportCallWrapper(wasm::WasmEngine* wasm_engine, WasmWrapperGraphBuilder builder(&zone, &jsgraph, sig, source_position_table, StubCallMode::kCallWasmRuntimeStub, - native_module->enabled_features()); + env->enabled_features); builder.set_control_ptr(&control); builder.set_effect_ptr(&effect); builder.BuildWasmImportCallWrapper(kind); @@ -6232,13 +6375,8 @@ wasm::WasmCode* CompileWasmImportCallWrapper(wasm::WasmEngine* wasm_engine, wasm_engine, incoming, &jsgraph, Code::WASM_TO_JS_FUNCTION, wasm::WasmCode::kWasmToJsWrapper, func_name, WasmStubAssemblerOptions(), source_position_table); - std::unique_ptr<wasm::WasmCode> wasm_code = native_module->AddCode( - wasm::WasmCode::kAnonymousFuncIndex, result.code_desc, - result.frame_slot_count, result.tagged_parameter_slots, - std::move(result.protected_instructions), - std::move(result.source_positions), wasm::WasmCode::kWasmToJsWrapper, - wasm::ExecutionTier::kNone); - return native_module->PublishCode(std::move(wasm_code)); + result.kind = wasm::WasmCompilationResult::kWasmToJsWrapper; + return result; } wasm::WasmCode* CompileWasmCapiCallWrapper(wasm::WasmEngine* wasm_engine, @@ -6290,9 +6428,8 @@ wasm::WasmCode* CompileWasmCapiCallWrapper(wasm::WasmEngine* wasm_engine, wasm::WasmCode::kWasmToCapiWrapper, debug_name, WasmStubAssemblerOptions(), source_positions); std::unique_ptr<wasm::WasmCode> wasm_code = native_module->AddCode( - wasm::WasmCode::kAnonymousFuncIndex, result.code_desc, - result.frame_slot_count, result.tagged_parameter_slots, - std::move(result.protected_instructions), + wasm::kAnonymousFuncIndex, result.code_desc, result.frame_slot_count, + result.tagged_parameter_slots, std::move(result.protected_instructions), std::move(result.source_positions), wasm::WasmCode::kWasmToCapiWrapper, wasm::ExecutionTier::kNone); return native_module->PublishCode(std::move(wasm_code)); @@ -6338,24 +6475,26 @@ wasm::WasmCompilationResult CompileWasmInterpreterEntry( wasm::WasmCode::kInterpreterEntry, func_name.begin(), WasmStubAssemblerOptions()); result.result_tier = wasm::ExecutionTier::kInterpreter; + result.kind = wasm::WasmCompilationResult::kInterpreterEntry; return result; } MaybeHandle<Code> CompileCWasmEntry(Isolate* isolate, wasm::FunctionSig* sig) { - Zone zone(isolate->allocator(), ZONE_NAME); - Graph graph(&zone); - CommonOperatorBuilder common(&zone); + std::unique_ptr<Zone> zone = + base::make_unique<Zone>(isolate->allocator(), ZONE_NAME); + Graph* graph = new (zone.get()) Graph(zone.get()); + CommonOperatorBuilder common(zone.get()); MachineOperatorBuilder machine( - &zone, MachineType::PointerRepresentation(), + zone.get(), MachineType::PointerRepresentation(), InstructionSelector::SupportedMachineOperatorFlags(), InstructionSelector::AlignmentRequirements()); - JSGraph jsgraph(isolate, &graph, &common, nullptr, nullptr, &machine); + JSGraph jsgraph(isolate, graph, &common, nullptr, nullptr, &machine); Node* control = nullptr; Node* effect = nullptr; - WasmWrapperGraphBuilder builder(&zone, &jsgraph, sig, nullptr, + WasmWrapperGraphBuilder builder(zone.get(), &jsgraph, sig, nullptr, StubCallMode::kCallCodeObject, wasm::WasmFeaturesFromIsolate(isolate)); builder.set_control_ptr(&control); @@ -6363,29 +6502,36 @@ MaybeHandle<Code> CompileCWasmEntry(Isolate* isolate, wasm::FunctionSig* sig) { builder.BuildCWasmEntry(); // Schedule and compile to machine code. - CallDescriptor* incoming = Linkage::GetJSCallDescriptor( - &zone, false, CWasmEntryParameters::kNumParameters + 1, - CallDescriptor::kNoFlags); + MachineType sig_types[] = {MachineType::Pointer(), // return + MachineType::Pointer(), // target + MachineType::AnyTagged(), // object_ref + MachineType::Pointer(), // argv + MachineType::Pointer()}; // c_entry_fp + MachineSignature incoming_sig(1, 4, sig_types); + // Traps need the root register, for TailCallRuntimeWithCEntry to call + // Runtime::kThrowWasmError. + bool initialize_root_flag = true; + CallDescriptor* incoming = Linkage::GetSimplifiedCDescriptor( + zone.get(), &incoming_sig, initialize_root_flag); // Build a name in the form "c-wasm-entry:<params>:<returns>". static constexpr size_t kMaxNameLen = 128; - char debug_name[kMaxNameLen] = "c-wasm-entry:"; - AppendSignature(debug_name, kMaxNameLen, sig); - - MaybeHandle<Code> maybe_code = Pipeline::GenerateCodeForWasmHeapStub( - isolate, incoming, &graph, Code::C_WASM_ENTRY, debug_name, - AssemblerOptions::Default(isolate)); - Handle<Code> code; - if (!maybe_code.ToHandle(&code)) { - return maybe_code; - } -#ifdef ENABLE_DISASSEMBLER - if (FLAG_print_opt_code) { - CodeTracer::Scope tracing_scope(isolate->GetCodeTracer()); - OFStream os(tracing_scope.file()); - code->Disassemble(debug_name, os); - } -#endif + auto debug_name = std::unique_ptr<char[]>(new char[kMaxNameLen]); + memcpy(debug_name.get(), "c-wasm-entry:", 14); + AppendSignature(debug_name.get(), kMaxNameLen, sig); + + // Run the compilation job synchronously. + std::unique_ptr<OptimizedCompilationJob> job( + Pipeline::NewWasmHeapStubCompilationJob( + isolate, incoming, std::move(zone), graph, Code::C_WASM_ENTRY, + std::move(debug_name), AssemblerOptions::Default(isolate))); + + if (job->PrepareJob(isolate) == CompilationJob::FAILED || + job->ExecuteJob() == CompilationJob::FAILED || + job->FinalizeJob(isolate) == CompilationJob::FAILED) { + return {}; + } + Handle<Code> code = job->compilation_info()->code(); return code; } |