v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
wasm-compiler.cc
Go to the documentation of this file.
1// Copyright 2015 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
7#include <memory>
8#include <optional>
9
11#include "src/base/vector.h"
41#include "src/heap/factory.h"
46#include "src/objects/name.h"
47#include "src/objects/string.h"
48#include "src/roots/roots.h"
66
67namespace v8::internal::compiler {
68
69namespace {
70
71// Use MachineType::Pointer() over Tagged() to load root pointers because they
72// do not get compressed.
73#define LOAD_ROOT(RootName, factory_name) \
74 (isolate_ ? graph()->NewNode(mcgraph()->common()->HeapConstant( \
75 isolate_->factory()->factory_name())) \
76 : gasm_->LoadImmutable( \
77 MachineType::Pointer(), BuildLoadIsolateRoot(), \
78 IsolateData::root_slot_offset(RootIndex::k##RootName)))
79
80template <typename T>
81bool ContainsSimd(const Signature<T>* sig) {
82 for (auto type : sig->all()) {
83 if (type == wasm::kWasmS128) return true;
84 }
85 return false;
86}
87
88bool ContainsInt64(const wasm::CanonicalSig* sig) {
89 for (auto type : sig->all()) {
90 if (type == wasm::kWasmI64) return true;
91 }
92 return false;
93}
94
95} // namespace
96
98 wasm::CompilationEnv* env, Zone* zone, MachineGraph* mcgraph,
100 compiler::SourcePositionTable* source_position_table,
101 ParameterMode parameter_mode, Isolate* isolate,
102 wasm::WasmEnabledFeatures enabled_features,
103 const wasm::CanonicalSig* wrapper_sig)
104 : gasm_(std::make_unique<WasmGraphAssembler>(mcgraph, zone)),
105 zone_(zone),
106 mcgraph_(mcgraph),
107 env_(env),
108 enabled_features_(enabled_features),
109 has_simd_(sig ? ContainsSimd(sig) : ContainsSimd(wrapper_sig)),
110 function_sig_(sig),
111 wrapper_sig_(wrapper_sig),
112 source_position_table_(source_position_table),
113 parameter_mode_(parameter_mode),
114 isolate_(isolate),
115 null_check_strategy_(trap_handler::IsTrapHandlerEnabled() &&
119 // This code is only used
120 // - for compiling certain wrappers (wasm-to-fast API, C-wasm-entry), and
121 // - for inlining js-to-wasm wrappers into Turbofan-compile JS functions.
123
124 // There are two kinds of isolate-specific code: JS-to-JS wrappers (passing
125 // kNoSpecialParameterMode) and JS-to-Wasm wrappers (passing
126 // kJSFunctionAbiMode).
127 DCHECK_IMPLIES(isolate != nullptr,
130 DCHECK_IMPLIES(env && env->module &&
131 std::any_of(env->module->memories.begin(),
132 env->module->memories.end(),
133 [](auto& memory) {
134 return memory.bounds_checks ==
135 wasm::kTrapHandler;
136 }),
139}
140
141// Destructor define here where the definition of {WasmGraphAssembler} is
142// available.
144
146 wasm::NativeModule* native_module,
147 int inlining_id) {
148#define TRACE(x) \
149 do { \
150 if (v8_flags.trace_turbo_inlining) { \
151 StdoutStream() << x << "\n"; \
152 } \
153 } while (false)
154
155 DCHECK(native_module->HasWireBytes());
156 const wasm::WasmModule* module = native_module->module();
157 const wasm::WasmFunction& inlinee = module->functions[fct_index];
158 // TODO(mliedtke): What would be a proper maximum size?
159 const uint32_t kMaxWasmInlineeSize = 30;
160 if (inlinee.code.length() > kMaxWasmInlineeSize) {
161 TRACE("- not inlining: function body is larger than max inlinee size ("
162 << inlinee.code.length() << " > " << kMaxWasmInlineeSize << ")");
163 return false;
164 }
165 if (inlinee.imported) {
166 TRACE("- not inlining: function is imported");
167 return false;
168 }
169 base::Vector<const uint8_t> bytes(native_module->wire_bytes().SubVector(
170 inlinee.code.offset(), inlinee.code.end_offset()));
171 bool is_shared = module->type(inlinee.sig_index).is_shared;
172 const wasm::FunctionBody inlinee_body(inlinee.sig, inlinee.code.offset(),
173 bytes.begin(), bytes.end(), is_shared);
174 // If the inlinee was not validated before, do that now.
175 if (V8_UNLIKELY(!module->function_was_validated(fct_index))) {
176 wasm::WasmDetectedFeatures unused_detected_features;
177 if (ValidateFunctionBody(graph()->zone(), enabled_features_, module,
178 &unused_detected_features, inlinee_body)
179 .failed()) {
180 // At this point we cannot easily raise a compilation error any more.
181 // Since this situation is highly unlikely though, we just ignore this
182 // inlinee and move on. The same validation error will be triggered
183 // again when actually compiling the invalid function.
184 TRACE("- not inlining: function body is invalid");
185 return false;
186 }
187 module->set_function_validated(fct_index);
188 }
190 graph()->zone(), module, mcgraph_, inlinee_body, bytes,
191 source_position_table_, inlining_id);
192 TRACE((
193 result
194 ? "- inlining"
195 : "- not inlining: function body contains unsupported instructions"));
196 return result;
197#undef TRACE
198}
199
200void WasmGraphBuilder::Start(unsigned params) {
201 Node* start = graph()->NewNode(mcgraph()->common()->Start(params));
202 graph()->SetStart(start);
204 // Initialize parameter nodes.
205 parameters_ = zone_->AllocateArray<Node*>(params);
206 for (unsigned i = 0; i < params; i++) {
207 parameters_[i] = nullptr;
208 }
209 // Initialize instance node.
210 switch (parameter_mode_) {
213 if (v8_flags.debug_code) {
214 Assert(gasm_->HasInstanceType(param, WASM_TRUSTED_INSTANCE_DATA_TYPE),
215 AbortReason::kUnexpectedInstanceType);
216 }
217 instance_data_node_ = param;
218 break;
219 }
220 case kWasmImportDataMode: {
221 Node* param = Param(0);
222 if (v8_flags.debug_code) {
223 Assert(gasm_->HasInstanceType(param, WASM_IMPORT_DATA_TYPE),
224 AbortReason::kUnexpectedInstanceType);
225 }
226 instance_data_node_ = gasm_->LoadProtectedPointerFromObject(
228 WasmImportData::kProtectedInstanceDataOffset));
229 break;
230 }
231 case kJSFunctionAbiMode: {
232 Node* param = Param(Linkage::kJSCallClosureParamIndex, "%closure");
233 if (v8_flags.debug_code) {
234 Assert(gasm_->HasInstanceType(param, JS_FUNCTION_TYPE),
235 AbortReason::kUnexpectedInstanceType);
236 }
237 instance_data_node_ = gasm_->LoadExportedFunctionInstanceData(
238 gasm_->LoadFunctionDataFromJSFunction(param));
239 break;
240 }
242 break;
243 }
244 graph()->SetEnd(graph()->NewNode(mcgraph()->common()->End(0)));
245}
246
247Node* WasmGraphBuilder::Param(int index, const char* debug_name) {
249 // Turbofan allows negative parameter indices.
251 int array_index = index - kMinParameterIndex;
252 if (parameters_[array_index] == nullptr) {
253 parameters_[array_index] = graph()->NewNode(
254 mcgraph()->common()->Parameter(index, debug_name), graph()->start());
255 }
256 return parameters_[array_index];
257}
258
260 Node* terminate =
261 graph()->NewNode(mcgraph()->common()->Throw(), effect, control);
262 gasm_->MergeControlToEnd(terminate);
263 gasm_->InitializeEffectControl(nullptr, nullptr);
264}
265
269
274
276 return mcgraph()->Int32Constant(value);
277}
278
280 return LOAD_ROOT(UndefinedValue, undefined_value);
281}
282
283// TODO(ahaas): Merge TrapId with TrapReason.
285 switch (reason) {
286#define TRAPREASON_TO_TRAPID(name) \
287 case wasm::k##name: \
288 static_assert(static_cast<int>(TrapId::k##name) == \
289 static_cast<int>(Builtin::kThrowWasm##name), \
290 "trap id mismatch"); \
291 return TrapId::k##name;
293#undef TRAPREASON_TO_TRAPID
294 default:
295 UNREACHABLE();
296 }
297}
298
300 unsigned count = static_cast<unsigned>(vals.size());
302
303 // TODOC: What is the meaning of the 0-constant?
304 buf[0] = Int32Constant(0);
305 if (count > 0) {
306 memcpy(buf.data() + 1, vals.begin(), sizeof(void*) * count);
307 }
308 buf[count + 1] = effect();
309 buf[count + 2] = control();
310 Node* ret = graph()->NewNode(mcgraph()->common()->Return(count), count + 3,
311 buf.data());
312
313 gasm_->MergeControlToEnd(ret);
314 return ret;
315}
316
318 // This version is for Wasm functions (i.e. not wrappers):
319 // - they use module-specific types
320 // - they go through a lowering phase later
321 // Both points are different in wrappers, see
322 // WasmWrapperGraphBuilder::IsNull().
324 return gasm_->IsNull(object, type);
325}
326
327Node* WasmGraphBuilder::effect() { return gasm_->effect(); }
328
329Node* WasmGraphBuilder::control() { return gasm_->control(); }
330
332 SetEffectControl(node, control());
333 return node;
334}
335
337 SetEffectControl(effect(), node);
338 return node;
339}
340
342 gasm_->InitializeEffectControl(effect, control);
343}
344
348 Node* implicit_first_arg,
349 const Operator* op, Node* frame_state) {
350 needs_stack_check_ = true;
351 const size_t has_frame_state = frame_state != nullptr ? 1 : 0;
352 const size_t extra = 3; // instance_node, effect, and control.
353 const size_t count = 1 + param_count + extra + has_frame_state;
354
355 // Reallocate the buffer to make space for extra inputs.
357 DCHECK_EQ(1 + param_count, args.size());
358
359 // Make room for the first argument at index 1, just after code.
360 inputs[0] = args[0]; // code
361 inputs[1] = implicit_first_arg;
362 if (param_count > 0) {
363 memcpy(&inputs[2], &args[1], param_count * sizeof(Node*));
364 }
365
366 // Add effect and control inputs.
367 if (has_frame_state != 0) inputs[param_count + 2] = frame_state;
368 inputs[param_count + has_frame_state + 2] = effect();
369 inputs[param_count + has_frame_state + 3] = control();
370
371 Node* call = graph()->NewNode(op, static_cast<int>(count), inputs.begin());
372 // Return calls have no effect output. Other calls are the new effect node.
373 if (op->EffectOutputCount() > 0) SetEffect(call);
375 if (position > 0) SetSourcePosition(call, position);
376
377 return call;
378}
379
380template <typename T>
385 Node* implicit_first_arg, bool indirect,
386 Node* frame_state) {
387 WasmCallKind call_kind = indirect ? kWasmIndirectFunction : kWasmFunction;
388 CallDescriptor* call_descriptor = GetWasmCallDescriptor(
389 mcgraph()->zone(), sig, call_kind, frame_state != nullptr);
390 const Operator* op = mcgraph()->common()->Call(call_descriptor);
391 Node* call = BuildCallNode(sig->parameter_count(), args, position,
392 implicit_first_arg, op, frame_state);
393 // TODO(manoskouk): These assume the call has control and effect outputs.
396 SetEffectControl(call);
397
398 size_t ret_count = sig->return_count();
399 if (ret_count == 0) return call; // No return value.
400
401 DCHECK_EQ(ret_count, rets.size());
402 if (ret_count == 1) {
403 // Only a single return value.
404 rets[0] = call;
405 } else {
406 // Create projections for all return values.
407 for (size_t i = 0; i < ret_count; i++) {
408 rets[i] = graph()->NewNode(mcgraph()->common()->Projection(i), call,
409 graph()->start());
410 }
411 }
412 return call;
413}
414
415// Only call this function for code which is not reused across instantiations,
416// as we do not patch the embedded js_context.
418 Node* js_context,
419 Node** parameters,
420 int parameter_count) {
422 auto call_descriptor = Linkage::GetRuntimeCallDescriptor(
423 mcgraph()->zone(), f, fun->nargs, Operator::kNoProperties,
425 // The CEntryStub is loaded from the IsolateRoot so that generated code is
426 // Isolate independent. At the moment this is only done for CEntryStub(1).
427 Node* isolate_root = BuildLoadIsolateRoot();
428 DCHECK_EQ(1, fun->result_size);
429 auto centry_id = Builtin::kWasmCEntry;
430 int builtin_slot_offset = IsolateData::BuiltinSlotOffset(centry_id);
431 Node* centry_stub =
432 gasm_->Load(MachineType::Pointer(), isolate_root, builtin_slot_offset);
433 // TODO(titzer): allow arbitrary number of runtime arguments
434 // At the moment we only allow 5 parameters. If more parameters are needed,
435 // increase this constant accordingly.
436 static const int kMaxParams = 5;
437 DCHECK_GE(kMaxParams, parameter_count);
438 Node* inputs[kMaxParams + 6];
439 int count = 0;
440 inputs[count++] = centry_stub;
441 for (int i = 0; i < parameter_count; i++) {
442 inputs[count++] = parameters[i];
443 }
444 inputs[count++] =
446 inputs[count++] = Int32Constant(fun->nargs); // arity
447 inputs[count++] = js_context; // js_context
448 inputs[count++] = effect();
449 inputs[count++] = control();
450
451 return gasm_->Call(call_descriptor, count, inputs);
452}
453
460
462 int offset, wasm::ValueTypeBase type) {
463 int alignment = offset % type.value_kind_size();
464 MachineType mach_type = type.machine_type();
465 if (COMPRESS_POINTERS_BOOL && mach_type.IsTagged()) {
466 // We are loading tagged value from off-heap location, so we need to load
467 // it as a full word otherwise we will not be able to decompress it.
468 mach_type = MachineType::Pointer();
469 }
470 if (alignment == 0 || mcgraph()->machine()->UnalignedLoadSupported(
471 type.machine_representation())) {
472 return mcgraph()->machine()->Load(mach_type);
473 }
474 return mcgraph()->machine()->UnalignedLoad(mach_type);
475}
476
478 Node* arg_buffer, Node* value,
479 Node* effect, Node* control) {
480 int alignment = offset % type.value_kind_size();
481 MachineRepresentation rep = type.machine_representation();
483 // We are storing tagged value to off-heap location, so we need to store
484 // it as a full word otherwise we will not be able to decompress it.
486 value = effect = graph()->NewNode(
487 mcgraph()->machine()->BitcastTaggedToWord(), value, effect, control);
488 }
489 if (alignment == 0 || mcgraph()->machine()->UnalignedStoreSupported(rep)) {
491 return graph()->NewNode(mcgraph()->machine()->Store(store_rep), arg_buffer,
492 Int32Constant(offset), value, effect, control);
493 }
494 UnalignedStoreRepresentation store_rep(rep);
495 return graph()->NewNode(mcgraph()->machine()->UnalignedStore(store_rep),
496 arg_buffer, Int32Constant(offset), value, effect,
497 control);
498}
499
501
503
504template <typename T>
506 Zone* zone, const Signature<T>* sig, wasm::CallOrigin origin) {
507 Signature<MachineRepresentation>::Builder builder(zone, sig->return_count(),
508 sig->parameter_count());
509 for (auto ret : sig->returns()) {
510 if (origin == wasm::kCalledFromJS) {
512 } else {
513 builder.AddReturn(ret.machine_representation());
514 }
515 }
516
517 for (auto param : sig->parameters()) {
518 if (origin == wasm::kCalledFromJS) {
519 // Parameters coming from JavaScript are always tagged values. Especially
520 // when the signature says that it's an I64 value, then a BigInt object is
521 // provided by JavaScript, and not two 32-bit parameters.
523 } else {
524 builder.AddParam(param.machine_representation());
525 }
526 }
527 return builder.Get();
528}
529
534
536 if (mcgraph()->machine()->Is64()) return;
537 Int64Lowering r(mcgraph()->graph(), mcgraph()->machine(), mcgraph()->common(),
538 gasm_->simplified(), mcgraph()->zone(), sig);
539 r.LowerGraph();
540}
541
544 function_sig_ != nullptr
545 ? CreateMachineSignature(mcgraph()->zone(), function_sig_, origin)
546 : CreateMachineSignature(mcgraph()->zone(), wrapper_sig_, origin);
547 LowerInt64(machine_sig);
548}
549
551 StubCallMode stub_mode) {
552 if (mcgraph()->machine()->Is64()) {
553 return gasm_->CallBuiltin(Builtin::kI64ToBigInt, Operator::kEliminatable,
554 input);
555 } else {
556 Node* low_word = gasm_->TruncateInt64ToInt32(input);
557 Node* high_word = gasm_->TruncateInt64ToInt32(
558 gasm_->Word64Shr(input, gasm_->Int32Constant(32)));
559 return gasm_->CallBuiltin(Builtin::kI32PairToBigInt,
560 Operator::kEliminatable, low_word, high_word);
561 }
562}
563
572
575 return SetEffect(graph()->NewNode(mcgraph()->common()->TypeGuard(Type::Wasm(
576 type, env_->module, graph()->zone())),
577 value, effect(), control()));
578}
579
581 Node* thread_in_wasm_flag_address, bool new_value) {
582 if (v8_flags.debug_code) {
583 Node* flag_value =
584 gasm_->Load(MachineType::Int32(), thread_in_wasm_flag_address, 0);
585 Node* check =
586 gasm_->Word32Equal(flag_value, Int32Constant(new_value ? 0 : 1));
587 Assert(check, new_value ? AbortReason::kUnexpectedThreadInWasmSet
588 : AbortReason::kUnexpectedThreadInWasmUnset);
589 }
590
592 thread_in_wasm_flag_address, 0,
593 Int32Constant(new_value ? 1 : 0));
594}
595
598 Node* isolate_root = BuildLoadIsolateRoot();
599
600 Node* thread_in_wasm_flag_address =
601 gasm_->Load(MachineType::Pointer(), isolate_root,
603
604 BuildModifyThreadInWasmFlagHelper(thread_in_wasm_flag_address, new_value);
605}
606
608 if (!v8_flags.debug_code) return;
609
610 Diamond check(graph(), mcgraph()->common(), condition, BranchHint::kTrue);
611 check.Chain(control());
612 SetControl(check.if_false);
613 Node* message_id = gasm_->NumberConstant(static_cast<int32_t>(abort_reason));
614 Node* old_effect = effect();
616 Runtime::kAbort, NoContextConstant(), &message_id, 1);
617 check.merge->ReplaceInput(1, call);
618 SetEffectControl(check.EffectPhi(old_effect, effect()), check.merge);
619}
620
625 node, compiler::Type::Wasm(type, env_->module, graph_zone()));
626 } else {
627 // We might try to set the type twice since some nodes are cached in the
628 // graph assembler, but we should never change the type.
629 // The exception is imported strings support, which may special-case
630 // values that are officially externref-typed as being known to be strings.
631#if DEBUG
632 static constexpr wasm::ValueType kRefExtern =
634 DCHECK((compiler::NodeProperties::GetType(node).AsWasm().type == type) ||
635 (enabled_features_.has_imported_strings() &&
636 compiler::NodeProperties::GetType(node).AsWasm().type ==
638 (type == wasm::kWasmExternRef || type == kRefExtern)));
639#endif
640 }
641 return node;
642}
643
644class WasmDecorator final : public GraphDecorator {
645 public:
647 : origins_(origins), decoder_(decoder) {}
648
649 void Decorate(Node* node) final {
650 origins_->SetNodeOrigin(
651 node, NodeOrigin("wasm graph creation", "n/a",
652 NodeOrigin::kWasmBytecode, decoder_->position()));
653 }
654
655 private:
658};
659
660namespace {
661
662// A non-null {isolate} signifies that the generated code is treated as being in
663// a JS frame for functions like BuildLoadIsolateRoot().
664class WasmWrapperGraphBuilder : public WasmGraphBuilder {
665 public:
666 WasmWrapperGraphBuilder(Zone* zone, MachineGraph* mcgraph,
667 const wasm::CanonicalSig* sig,
668 ParameterMode parameter_mode, Isolate* isolate,
670 : WasmGraphBuilder(nullptr, zone, mcgraph, nullptr, spt, parameter_mode,
671 isolate, wasm::WasmEnabledFeatures::All(), sig) {}
672
673 class ModifyThreadInWasmFlagScope {
674 public:
675 ModifyThreadInWasmFlagScope(
676 WasmWrapperGraphBuilder* wasm_wrapper_graph_builder,
677 WasmGraphAssembler* gasm)
678 : wasm_wrapper_graph_builder_(wasm_wrapper_graph_builder) {
680 Node* isolate_root = wasm_wrapper_graph_builder_->BuildLoadIsolateRoot();
681
683 gasm->Load(MachineType::Pointer(), isolate_root,
685
686 wasm_wrapper_graph_builder_->BuildModifyThreadInWasmFlagHelper(
688 }
689
690 ModifyThreadInWasmFlagScope(const ModifyThreadInWasmFlagScope&) = delete;
691
692 ~ModifyThreadInWasmFlagScope() {
694
695 wasm_wrapper_graph_builder_->BuildModifyThreadInWasmFlagHelper(
697 }
698
699 private:
700 WasmWrapperGraphBuilder* wasm_wrapper_graph_builder_;
702 };
703
704 Node* BuildCallAndReturn(Node* js_context, Node* function_data,
705 base::SmallVector<Node*, 16> args, Node* frame_state,
706 bool set_in_wasm_flag) {
707 const int rets_count = static_cast<int>(wrapper_sig_->return_count());
708 base::SmallVector<Node*, 1> rets(rets_count);
709
710 // Set the ThreadInWasm flag before we do the actual call.
711 {
712 std::optional<ModifyThreadInWasmFlagScope>
713 modify_thread_in_wasm_flag_builder;
714 if (set_in_wasm_flag) {
715 modify_thread_in_wasm_flag_builder.emplace(this, gasm_.get());
716 }
717
718 // Call to an import or a wasm function defined in this module.
719 // The (cached) call target is the jump table slot for that function.
720 // We do not use the imports dispatch table here so that the wrapper is
721 // target independent, in particular for tier-up.
723 function_data, wasm::ObjectAccess::ToTagged(
724 WasmFunctionData::kProtectedInternalOffset));
728 WasmInternalFunction::kRawCallTargetOffset));
731 WasmInternalFunction::kProtectedImplicitArgOffset));
732 BuildWasmCall(wrapper_sig_, base::VectorOf(args), base::VectorOf(rets),
733 wasm::kNoCodePosition, implicit_arg, true, frame_state);
734 }
735
736 Node* jsval;
737 if (wrapper_sig_->return_count() == 0) {
738 jsval = UndefinedValue();
739 } else if (wrapper_sig_->return_count() == 1) {
740 jsval = rets[0];
741 } else {
742 UNREACHABLE();
743 }
744 return jsval;
745 }
746
747 void BuildJSToWasmWrapper(Node* frame_state = nullptr,
748 bool set_in_wasm_flag = true) {
749 const int wasm_param_count =
750 static_cast<int>(wrapper_sig_->parameter_count());
751
752 // Build the start and the JS parameter nodes.
753 // TODO(saelo): this should probably be a constant with a descriptive name.
754 // As far as I understand, it's the number of additional parameters in the
755 // JS calling convention. Also there should be a static_assert here that it
756 // matches the number of parameters in the JSTrampolineDescriptor?
757 // static_assert
758 Start(wasm_param_count + 6);
759
760 // Create the js_closure and js_context parameters.
761 Node* js_closure = Param(Linkage::kJSCallClosureParamIndex, "%closure");
762 Node* js_context = Param(
763 Linkage::GetJSCallContextParamIndex(wasm_param_count + 1), "%context");
764 Node* function_data = gasm_->LoadFunctionDataFromJSFunction(js_closure);
765
766 if (!wasm::IsJSCompatibleSignature(wrapper_sig_)) {
767 // Throw a TypeError. Use the js_context of the calling javascript
768 // function (passed as a parameter), such that the generated code is
769 // js_context independent.
770 BuildCallToRuntimeWithContext(Runtime::kWasmThrowJSTypeError, js_context,
771 nullptr, 0);
772 TerminateThrow(effect(), control());
773 return;
774 }
775
776#if V8_ENABLE_DRUMBRAKE
777 if (v8_flags.wasm_enable_exec_time_histograms && v8_flags.slow_histograms &&
778 !v8_flags.wasm_jitless) {
779 Node* runtime_call = BuildCallToRuntimeWithContext(
780 Runtime::kWasmTraceBeginExecution, js_context, nullptr, 0);
781 SetControl(runtime_call);
782 }
783#endif // V8_ENABLE_DRUMBRAKE
784
785 const int args_count = wasm_param_count + 1; // +1 for wasm_code.
786
787 // Prepare Param() nodes. Param() nodes can only be created once,
788 // so we need to use the same nodes along all possible transformation paths.
789 base::SmallVector<Node*, 16> params(args_count);
790 for (int i = 0; i < wasm_param_count; ++i) params[i + 1] = Param(i + 1);
791
793 // Convert JS parameters to wasm numbers using the default transformation
794 // and build the call.
795 base::SmallVector<Node*, 16> args(args_count);
796 for (int i = 0; i < wasm_param_count; ++i) {
797 Node* wasm_param = params[i + 1];
798
799 // For Float32 parameters
800 // we set UseInfo::CheckedNumberOrOddballAsFloat64 in
801 // simplified-lowering and we need to add here a conversion from Float64
802 // to Float32.
803 if (wrapper_sig_->GetParam(i).kind() == wasm::kF32) {
804 wasm_param = gasm_->TruncateFloat64ToFloat32(wasm_param);
805 }
806
807 args[i + 1] = wasm_param;
808 }
809
810 Node* jsval = BuildCallAndReturn(js_context, function_data, args,
811 frame_state, set_in_wasm_flag);
812
813#if V8_ENABLE_DRUMBRAKE
814 if (v8_flags.wasm_enable_exec_time_histograms && v8_flags.slow_histograms &&
815 !v8_flags.wasm_jitless) {
816 Node* runtime_call = BuildCallToRuntimeWithContext(
817 Runtime::kWasmTraceEndExecution, js_context, nullptr, 0);
818 SetControl(runtime_call);
819 }
820#endif // V8_ENABLE_DRUMBRAKE
821
822 Return(jsval);
823 if (ContainsInt64(wrapper_sig_)) LowerInt64(wasm::kCalledFromJS);
824 }
825
826 Node* BuildReceiverNode(Node* callable_node, Node* native_context,
827 Node* undefined_node) {
828 // Check function strict bit.
829 Node* shared_function_info = gasm_->LoadSharedFunctionInfo(callable_node);
830 Node* flags = gasm_->LoadFromObject(
831 MachineType::Int32(), shared_function_info,
833 Node* strict_check = gasm_->Word32And(
834 flags, Int32Constant(SharedFunctionInfo::IsNativeBit::kMask |
835 SharedFunctionInfo::IsStrictBit::kMask));
836
837 // Load global receiver if sloppy else use undefined.
838 Diamond strict_d(graph(), mcgraph()->common(), strict_check,
840 Node* old_effect = effect();
841 SetControl(strict_d.if_false);
842 Node* global_proxy = gasm_->LoadFixedArrayElementPtr(
843 native_context, Context::GLOBAL_PROXY_INDEX);
844 SetEffectControl(strict_d.EffectPhi(old_effect, global_proxy),
845 strict_d.merge);
846 return strict_d.Phi(MachineRepresentation::kTagged, undefined_node,
847 global_proxy);
848 }
849
850 template <typename... Args>
851 Node* BuildCCall(MachineSignature* sig, Node* function, Args... args) {
852 DCHECK_LE(sig->return_count(), 1);
853 DCHECK_EQ(sizeof...(args), sig->parameter_count());
854 Node* call_args[] = {function, args..., effect(), control()};
855
856 auto call_descriptor =
857 Linkage::GetSimplifiedCDescriptor(mcgraph()->zone(), sig);
858
859 return gasm_->Call(call_descriptor, arraysize(call_args), call_args);
860 }
861
862 Node* BuildSwitchToTheCentralStack() {
863 Node* do_switch = gasm_->ExternalConstant(
864 ExternalReference::wasm_switch_to_the_central_stack_for_js());
865 MachineType reps[] = {MachineType::Pointer(), MachineType::Pointer(),
867 MachineSignature sig(1, 2, reps);
868
869 Node* central_stack_sp = BuildCCall(
870 &sig, do_switch,
873 Node* old_sp = gasm_->LoadStackPointer();
874 // Temporarily disallow sp-relative offsets.
875 gasm_->SetStackPointer(central_stack_sp);
876 return old_sp;
877 }
878
879 void BuildSwitchBackFromCentralStack(Node* old_sp) {
880 auto skip = gasm_->MakeLabel();
881 gasm_->GotoIf(gasm_->IntPtrEqual(old_sp, gasm_->IntPtrConstant(0)), &skip);
882 Node* do_switch = gasm_->ExternalConstant(
883 ExternalReference::wasm_switch_from_the_central_stack_for_js());
884 MachineType reps[] = {MachineType::Pointer()};
885 MachineSignature sig(0, 1, reps);
886 BuildCCall(&sig, do_switch,
888 gasm_->SetStackPointer(old_sp);
889 gasm_->Goto(&skip);
890 gasm_->Bind(&skip);
891 }
892
893 Node* BuildSwitchToTheCentralStackIfNeeded() {
894 // If the current stack is a secondary stack, switch to the central stack.
896 Node* isolate_root = BuildLoadIsolateRoot();
897 Node* is_on_central_stack_flag =
898 gasm_->Load(MachineType::Uint8(), isolate_root,
899 IsolateData::is_on_central_stack_flag_offset());
900 gasm_->GotoIf(is_on_central_stack_flag, &end, BranchHint::kTrue,
902
903 Node* old_sp = BuildSwitchToTheCentralStack();
904 gasm_->Goto(&end, old_sp);
905
906 gasm_->Bind(&end);
907 return end.PhiAt(0);
908 }
909
910 void BuildJSFastApiCallWrapper(DirectHandle<JSReceiver> callable) {
911 // Here 'callable_node' must be equal to 'callable' but we cannot pass a
912 // HeapConstant(callable) because WasmCode::Validate() fails with
913 // Unexpected mode: FULL_EMBEDDED_OBJECT.
914 Node* callable_node = gasm_->Load(
915 MachineType::TaggedPointer(), Param(0),
916 wasm::ObjectAccess::ToTagged(WasmImportData::kCallableOffset));
917 Node* native_context = gasm_->Load(
918 MachineType::TaggedPointer(), Param(0),
919 wasm::ObjectAccess::ToTagged(WasmImportData::kNativeContextOffset));
920
921 gasm_->Store(StoreRepresentation(mcgraph_->machine()->Is64()
927
928 Node* undefined_node = UndefinedValue();
929
930 BuildModifyThreadInWasmFlag(false);
931
932 DirectHandle<JSFunction> target;
933 Node* target_node;
934 Node* receiver_node;
935 Isolate* isolate = callable->GetIsolate();
936 if (IsJSBoundFunction(*callable)) {
937 target = direct_handle(
939 Cast<JSBoundFunction>(callable)->bound_target_function()),
940 isolate);
941 target_node =
942 gasm_->Load(MachineType::TaggedPointer(), callable_node,
944 JSBoundFunction::kBoundTargetFunctionOffset));
945 receiver_node = gasm_->Load(
946 MachineType::TaggedPointer(), callable_node,
947 wasm::ObjectAccess::ToTagged(JSBoundFunction::kBoundThisOffset));
948 } else {
949 DCHECK(IsJSFunction(*callable));
950 target = Cast<JSFunction>(callable);
951 target_node = callable_node;
952 receiver_node =
953 BuildReceiverNode(callable_node, native_context, undefined_node);
954 }
955
956 Tagged<SharedFunctionInfo> shared = target->shared();
957 Tagged<FunctionTemplateInfo> api_func_data = shared->api_func_data();
958 const Address c_address = api_func_data->GetCFunction(isolate, 0);
959 const v8::CFunctionInfo* c_signature =
960 api_func_data->GetCSignature(target->GetIsolate(), 0);
961
962#ifdef V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
963 Address c_functions[] = {c_address};
964 const v8::CFunctionInfo* const c_signatures[] = {c_signature};
965 target->GetIsolate()->simulator_data()->RegisterFunctionsAndSignatures(
966 c_functions, c_signatures, 1);
967#endif // V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
968
969 Node* shared_function_info = gasm_->LoadSharedFunctionInfo(target_node);
970 Node* function_template_info =
971 gasm_->Load(MachineType::TaggedPointer(), shared_function_info,
973 SharedFunctionInfo::kUntrustedFunctionDataOffset));
974 Node* api_data_argument =
975 gasm_->Load(MachineType::TaggedPointer(), function_template_info,
977 FunctionTemplateInfo::kCallbackDataOffset));
978
979 FastApiCallFunction c_function{c_address, c_signature};
980 Node* old_sp = BuildSwitchToTheCentralStackIfNeeded();
982 target->GetIsolate(), graph(), gasm_.get(), c_function,
983 api_data_argument,
984 // Load and convert parameters passed to C function
985 [this, c_signature, receiver_node](
986 int param_index,
987 GraphAssemblerLabel<0>* /* error label, unused */) {
988 if (param_index == 0) {
989 return gasm_->AdaptLocalArgument(receiver_node);
990 }
991 switch (c_signature->ArgumentInfo(param_index).GetType()) {
992 case CTypeInfo::Type::kV8Value:
993 return gasm_->AdaptLocalArgument(Param(param_index));
994 default:
995 return Param(param_index);
996 }
997 },
998 // Convert return value (no conversion needed for wasm)
999 [](const CFunctionInfo* signature, Node* c_return_value) {
1000 return c_return_value;
1001 },
1002 [](Node* options_stack_slot) {},
1003 // Generate fallback slow call if fast call fails.
1004 []() -> Node* {
1005 // This is not needed because the error label (see the lambda above)
1006 // is not used.
1007 UNREACHABLE();
1008 });
1009 BuildSwitchBackFromCentralStack(old_sp);
1010
1011 BuildModifyThreadInWasmFlag(true);
1012
1013 Return(call);
1014 }
1015
1016 void BuildCWasmEntry() {
1017 // +1 offset for first parameter index being -1.
1019
1020 Node* code_entry = Param(CWasmEntryParameters::kCodeEntry);
1021 Node* object_ref = Param(CWasmEntryParameters::kObjectRef);
1022 Node* arg_buffer = Param(CWasmEntryParameters::kArgumentsBuffer);
1023 Node* c_entry_fp = Param(CWasmEntryParameters::kCEntryFp);
1024
1025 Node* fp_value = graph()->NewNode(mcgraph()->machine()->LoadFramePointer());
1026 gasm_->Store(StoreRepresentation(MachineType::PointerRepresentation(),
1029 c_entry_fp);
1030
1031 int wasm_arg_count = static_cast<int>(wrapper_sig_->parameter_count());
1032 base::SmallVector<Node*, 16> args(wasm_arg_count + 4);
1033
1034 int pos = 0;
1035 args[pos++] = code_entry;
1037
1038 int offset = 0;
1039 for (wasm::CanonicalValueType type : wrapper_sig_->parameters()) {
1040 Node* arg_load = SetEffect(
1041 graph()->NewNode(GetSafeLoadOperator(offset, type), arg_buffer,
1042 Int32Constant(offset), effect(), control()));
1043 args[pos++] = arg_load;
1044 offset += type.value_kind_size();
1045 }
1046
1047 args[pos++] = effect();
1048 args[pos++] = control();
1049
1050 // Call the wasm code.
1051 auto call_descriptor = GetWasmCallDescriptor(
1052 mcgraph()->zone(), wrapper_sig_, WasmCallKind::kWasmIndirectFunction);
1053
1054 DCHECK_EQ(pos, args.size());
1055 Node* call = gasm_->Call(call_descriptor, pos, args.begin());
1056
1057 Node* if_success = graph()->NewNode(mcgraph()->common()->IfSuccess(), call);
1058 Node* if_exception =
1059 graph()->NewNode(mcgraph()->common()->IfException(), call, call);
1060
1061 // Handle exception: return it.
1062 SetEffectControl(if_exception);
1063 Return(if_exception);
1064
1065 // Handle success: store the return value(s).
1066 SetEffectControl(call, if_success);
1067 pos = 0;
1068 offset = 0;
1069 for (wasm::CanonicalValueType type : wrapper_sig_->returns()) {
1070 Node* value = wrapper_sig_->return_count() == 1
1071 ? call
1072 : graph()->NewNode(mcgraph()->common()->Projection(pos),
1073 call, control());
1074 SetEffect(
1075 BuildSafeStore(offset, type, arg_buffer, value, effect(), control()));
1076 offset += type.value_kind_size();
1077 pos++;
1078 }
1079
1080 Return(mcgraph()->IntPtrConstant(0));
1081
1082 if (mcgraph()->machine()->Is32() && ContainsInt64(wrapper_sig_)) {
1083 // These correspond to {sig_types[]} in {CompileCWasmEntry}.
1084 MachineRepresentation sig_reps[] = {
1085 MachineType::PointerRepresentation(), // return value
1087 MachineRepresentation::kTagged, // object_ref
1090 };
1091 Signature<MachineRepresentation> c_entry_sig(1, 4, sig_reps);
1092 Int64Lowering r(mcgraph()->graph(), mcgraph()->machine(),
1093 mcgraph()->common(), gasm_->simplified(),
1094 mcgraph()->zone(), &c_entry_sig);
1095 r.LowerGraph();
1096 }
1097 }
1098
1099 private:
1100 SetOncePointer<const Operator> int32_to_heapnumber_operator_;
1101 SetOncePointer<const Operator> tagged_non_smi_to_int32_operator_;
1102 SetOncePointer<const Operator> float32_to_number_operator_;
1103 SetOncePointer<const Operator> float64_to_number_operator_;
1104 SetOncePointer<const Operator> tagged_to_float64_operator_;
1105};
1106
1107} // namespace
1108
1110 const wasm::CanonicalSig* signature,
1111 Isolate* isolate,
1113 Node* frame_state, bool set_in_wasm_flag) {
1114 WasmWrapperGraphBuilder builder(zone, mcgraph, signature,
1115 WasmGraphBuilder::kJSFunctionAbiMode, isolate,
1116 spt);
1117 builder.BuildJSToWasmWrapper(frame_state, set_in_wasm_flag);
1118}
1119
1120std::unique_ptr<OptimizedCompilationJob> NewJSToWasmCompilationJob(
1121 Isolate* isolate, const wasm::CanonicalSig* sig) {
1122 return Pipeline::NewWasmTurboshaftWrapperCompilationJob(
1123 isolate, sig, wasm::WrapperCompilationInfo{CodeKind::JS_TO_WASM_FUNCTION},
1125}
1126
1127namespace {
1128
1129MachineGraph* CreateCommonMachineGraph(Zone* zone) {
1130 return zone->New<MachineGraph>(
1131 zone->New<TFGraph>(zone), zone->New<CommonOperatorBuilder>(zone),
1132 zone->New<MachineOperatorBuilder>(
1134 InstructionSelector::SupportedMachineOperatorFlags(),
1135 InstructionSelector::AlignmentRequirements()));
1136}
1137
1138} // namespace
1139
1142 bool source_positions, int expected_arity, wasm::Suspend suspend) {
1146
1147 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm.detailed"),
1148 "wasm.CompileWasmImportCallWrapper");
1149 base::TimeTicks start_time;
1150 if (V8_UNLIKELY(v8_flags.trace_wasm_compilation_times)) {
1151 start_time = base::TimeTicks::Now();
1152 }
1153
1154 // Build a name in the form "wasm-to-js-<kind>-<signature>".
1155 constexpr size_t kMaxNameLen = 128;
1156 char func_name[kMaxNameLen];
1157 int name_prefix_len = SNPrintF(base::VectorOf(func_name, kMaxNameLen),
1158 "wasm-to-js-%d-", static_cast<int>(kind));
1159 PrintSignature(base::VectorOf(func_name, kMaxNameLen) + name_prefix_len, sig,
1160 '-');
1161
1162 auto result = Pipeline::GenerateCodeForWasmNativeStubFromTurboshaft(
1163 sig,
1164 wasm::WrapperCompilationInfo{CodeKind::WASM_TO_JS_FUNCTION, kind,
1165 expected_arity, suspend},
1166 func_name, WasmStubAssemblerOptions(), nullptr);
1167
1168 if (V8_UNLIKELY(v8_flags.trace_wasm_compilation_times)) {
1169 base::TimeDelta time = base::TimeTicks::Now() - start_time;
1170 int codesize = result.code_desc.body_size();
1171 StdoutStream{} << "Compiled WasmToJS wrapper " << func_name << ", took "
1172 << time.InMilliseconds() << " ms; codesize " << codesize
1173 << std::endl;
1174 }
1175
1176 return result;
1177}
1178
1180 const wasm::CanonicalSig* sig) {
1181 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm.detailed"),
1182 "wasm.CompileWasmCapiFunction");
1183
1184 return Pipeline::GenerateCodeForWasmNativeStubFromTurboshaft(
1185 sig, wasm::WrapperCompilationInfo{CodeKind::WASM_TO_CAPI_FUNCTION},
1186 "WasmCapiCall", WasmStubAssemblerOptions(), nullptr);
1187}
1188
1190 return fast_api_call::CanOptimizeFastSignature(sig);
1191}
1192
1195 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm.detailed"),
1196 "wasm.CompileWasmJSFastCallWrapper");
1197
1200 MachineGraph* mcgraph = CreateCommonMachineGraph(&zone);
1201
1202 WasmWrapperGraphBuilder builder(&zone, mcgraph, sig,
1203 WasmGraphBuilder::kWasmImportDataMode,
1204 nullptr, source_positions);
1205
1206 // Set up the graph start.
1207 int param_count = static_cast<int>(sig->parameter_count()) +
1208 1 /* offset for first parameter index being -1 */ +
1209 1 /* Wasm instance */ + 1 /* kExtraCallableParam */;
1210 builder.Start(param_count);
1211 builder.BuildJSFastApiCallWrapper(callable);
1212
1213 // Run the compiler pipeline to generate machine code.
1214 CallDescriptor* call_descriptor =
1215 GetWasmCallDescriptor(&zone, sig, WasmCallKind::kWasmImportWrapper);
1216 if (mcgraph->machine()->Is32()) {
1217 call_descriptor = GetI32WasmCallDescriptor(&zone, call_descriptor);
1218 }
1219
1220 const char* debug_name = "WasmJSFastApiCall";
1221 wasm::WasmCompilationResult result = Pipeline::GenerateCodeForWasmNativeStub(
1222 call_descriptor, mcgraph, CodeKind::WASM_TO_JS_FUNCTION, debug_name,
1224 return result;
1225}
1226
1228 const wasm::CanonicalSig* sig) {
1229 DCHECK(!v8_flags.wasm_jitless);
1230
1231 std::unique_ptr<Zone> zone = std::make_unique<Zone>(
1232 isolate->allocator(), ZONE_NAME, kCompressGraphZone);
1233 TFGraph* graph = zone->New<TFGraph>(zone.get());
1234 CommonOperatorBuilder* common = zone->New<CommonOperatorBuilder>(zone.get());
1235 MachineOperatorBuilder* machine = zone->New<MachineOperatorBuilder>(
1237 InstructionSelector::SupportedMachineOperatorFlags(),
1238 InstructionSelector::AlignmentRequirements());
1239 MachineGraph* mcgraph = zone->New<MachineGraph>(graph, common, machine);
1240
1241 WasmWrapperGraphBuilder builder(zone.get(), mcgraph, sig,
1242 WasmGraphBuilder::kNoSpecialParameterMode,
1243 nullptr, nullptr);
1244 builder.BuildCWasmEntry();
1245
1246 // Schedule and compile to machine code.
1247 MachineType sig_types[] = {MachineType::Pointer(), // return
1248 MachineType::Pointer(), // target
1249 MachineType::AnyTagged(), // object_ref
1250 MachineType::Pointer(), // argv
1251 MachineType::Pointer()}; // c_entry_fp
1252 MachineSignature incoming_sig(1, 4, sig_types);
1253 // Traps need the root register, for TailCallRuntime to call
1254 // Runtime::kThrowWasmError.
1255 CallDescriptor::Flags flags = CallDescriptor::kInitializeRootRegister;
1256 CallDescriptor* incoming =
1257 Linkage::GetSimplifiedCDescriptor(zone.get(), &incoming_sig, flags);
1258
1259 // Build a name in the form "c-wasm-entry:<params>:<returns>".
1260 constexpr size_t kMaxNameLen = 128;
1261 constexpr size_t kNamePrefixLen = 13;
1262 auto name_buffer = std::unique_ptr<char[]>(new char[kMaxNameLen]);
1263 memcpy(name_buffer.get(), "c-wasm-entry:", kNamePrefixLen);
1264 PrintSignature(
1265 base::VectorOf(name_buffer.get(), kMaxNameLen) + kNamePrefixLen, sig);
1266
1267 // Run the compilation job synchronously.
1268 std::unique_ptr<TurbofanCompilationJob> job(
1269 Pipeline::NewWasmHeapStubCompilationJob(
1270 isolate, incoming, std::move(zone), graph, CodeKind::C_WASM_ENTRY,
1271 std::move(name_buffer), AssemblerOptions::Default(isolate)));
1272
1273 CHECK_NE(job->ExecuteJob(isolate->counters()->runtime_call_stats(), nullptr),
1275 CHECK_NE(job->FinalizeJob(isolate), CompilationJob::FAILED);
1276
1277 return job->compilation_info()->code();
1278}
1279
1281 return AssemblerOptions{
1282 // Relocation info required to serialize {WasmCode} for proper functions.
1283 .record_reloc_info_for_serialization = true,
1284 .enable_root_relative_access = false,
1285 .is_wasm = true,
1286 };
1287}
1288
1290 return AssemblerOptions{
1291 // Relocation info not necessary because stubs are not serialized.
1292 .record_reloc_info_for_serialization = false,
1293 .enable_root_relative_access = false,
1294 // TODO(jkummerow): Would it be better to have a far jump table in
1295 // the wrapper cache's code space, and call builtins through that?
1296 .builtin_call_jump_mode = BuiltinCallJumpMode::kIndirect,
1297 .is_wasm = true,
1298 };
1299}
1300
1301#undef LOAD_ROOT
1302
1303} // namespace v8::internal::compiler
TFGraph * graph
Isolate * isolate_
#define Assert(condition)
int16_t parameter_count
Definition builtins.cc:67
Builtins::Kind kind
Definition builtins.cc:40
SourcePosition pos
const CTypeInfo & ArgumentInfo(unsigned int index) const
Definition api.cc:11874
static TimeTicks Now()
Definition time.cc:736
Vector< T > SubVector(size_t from, size_t to) const
Definition vector.h:41
constexpr size_t size() const
Definition vector.h:70
constexpr T * begin() const
Definition vector.h:96
static V8_EXPORT_PRIVATE ExternalReference isolate_address()
static ExternalReference Create(const SCTableReference &table_ref)
static constexpr int BuiltinSlotOffset(Builtin id)
static constexpr uint32_t thread_in_wasm_flag_address_offset()
Definition isolate.h:1338
static constexpr uint32_t context_offset()
Definition isolate.h:1351
Address isolate_root() const
Definition isolate.h:1242
constexpr bool IsTagged() const
static constexpr MachineType Pointer()
static constexpr MachineType Uint8()
static constexpr MachineType Int32()
static constexpr MachineType AnyTagged()
static constexpr MachineType Uint32()
static constexpr MachineType TaggedPointer()
static constexpr MachineRepresentation PointerRepresentation()
static V8_EXPORT_PRIVATE const Function * FunctionForId(FunctionId id)
Definition runtime.cc:350
static constexpr int kFirstPushedFrameValueOffset
static std::unique_ptr< char[]> GetDebugName(const wasm::CanonicalSig *sig)
T * AllocateArray(size_t length)
Definition zone.h:127
T * New(Args &&... args)
Definition zone.h:114
const Operator * Call(const CallDescriptor *call_descriptor)
detail::GraphAssemblerLabelForReps< Reps... > MakeLabel(Reps... reps)
Node * Store(StoreRepresentation rep, Node *object, Node *offset, Node *value)
Node * ExternalConstant(ExternalReference ref)
Node * IntPtrEqual(Node *left, Node *right)
TNode< Object > Call(const CallDescriptor *call_descriptor, int inputs_size, Node **inputs)
void GotoIf(Node *condition, detail::GraphAssemblerLabelForVars< Vars... > *label, BranchHint hint, Vars...)
void Bind(GraphAssemblerLabel< VarCount > *label)
Node * Load(MachineType type, Node *object, Node *offset)
void Goto(detail::GraphAssemblerLabelForVars< Vars... > *label, Vars...)
static constexpr int GetJSCallContextParamIndex(int parameter_count)
Definition linkage.h:495
static CallDescriptor * GetSimplifiedCDescriptor(Zone *zone, const MachineSignature *sig, CallDescriptor::Flags flags=CallDescriptor::kNoFlags, Operator::Properties properties=Operator::kNoThrow)
Definition c-linkage.cc:269
static CallDescriptor * GetRuntimeCallDescriptor(Zone *zone, Runtime::FunctionId function, int js_parameter_count, Operator::Properties properties, CallDescriptor::Flags flags, LazyDeoptOnThrow lazy_deopt_on_throw=LazyDeoptOnThrow::kNo)
Definition linkage.cc:426
static constexpr int kJSCallClosureParamIndex
Definition linkage.h:504
Node * ExternalConstant(ExternalReference ref)
CommonOperatorBuilder * common() const
Node * IntPtrConstant(intptr_t value)
MachineOperatorBuilder * machine() const
const Operator * Load(LoadRepresentation rep)
const Operator * UnalignedLoad(LoadRepresentation rep)
static Type GetType(const Node *node)
static bool IsTyped(const Node *node)
static void SetType(Node *node, Type type)
void SetSourcePosition(Node *node, SourcePosition position)
Node * NewNode(const Operator *op, int input_count, Node *const *inputs, bool incomplete=false)
WasmDecorator(NodeOriginTable *origins, wasm::Decoder *decoder)
compiler::NodeOriginTable * origins_
Node * LoadFromObject(MachineType type, Node *base, Node *offset)
Node * LoadTrustedDataFromInstanceObject(Node *instance_object)
SimplifiedOperatorBuilder * simplified() override
Node * LoadFixedArrayElementPtr(Node *array, int index)
Node * LoadImmutableProtectedPointerFromObject(Node *object, Node *offset)
Node * BuildSafeStore(int offset, wasm::ValueTypeBase type, Node *arg_buffer, Node *value, Node *effect, Node *control)
V8_EXPORT_PRIVATE void LowerInt64(Signature< MachineRepresentation > *sig)
Node * Return(base::Vector< Node * > nodes)
Node * SetType(Node *node, wasm::ValueType type)
void BuildModifyThreadInWasmFlagHelper(Node *thread_in_wasm_flag_address, bool new_value)
bool TryWasmInlining(int fct_index, wasm::NativeModule *native_module, int inlining_id)
void Assert(Node *condition, AbortReason abort_reason)
std::unique_ptr< WasmGraphAssembler > gasm_
Node * BuildCallToRuntime(Runtime::FunctionId f, Node **parameters, int parameter_count)
const wasm::CanonicalSig *const wrapper_sig_
Node * TypeGuard(Node *value, wasm::ValueType type)
wasm::WasmEnabledFeatures enabled_features_
Node * BuildWasmCall(const Signature< T > *sig, base::Vector< Node * > args, base::Vector< Node * > rets, wasm::WasmCodePosition position, Node *implicit_first_arg, bool indirect, Node *frame_state=nullptr)
void SetSourcePosition(Node *node, wasm::WasmCodePosition position)
Node * Param(int index, const char *debug_name=nullptr)
Node * IsNull(Node *object, wasm::ValueType type)
Node * BuildCallNode(size_t param_count, base::Vector< Node * > args, wasm::WasmCodePosition position, Node *instance_node, const Operator *op, Node *frame_state=nullptr)
const Operator * GetSafeLoadOperator(int offset, wasm::ValueTypeBase type)
void SetEffectControl(Node *effect, Node *control)
void TerminateThrow(Node *effect, Node *control)
V8_EXPORT_PRIVATE WasmGraphBuilder(wasm::CompilationEnv *env, Zone *zone, MachineGraph *mcgraph, const wasm::FunctionSig *sig, compiler::SourcePositionTable *spt, ParameterMode parameter_mode, Isolate *isolate, wasm::WasmEnabledFeatures enabled_features, const wasm::CanonicalSig *wrapper_sig=nullptr)
const wasm::FunctionSig *const function_sig_
Node * BuildChangeInt64ToBigInt(Node *input, StubCallMode stub_mode)
TrapId GetTrapIdForTrap(wasm::TrapReason reason)
compiler::SourcePositionTable *const source_position_table_
Node * BuildCallToRuntimeWithContext(Runtime::FunctionId f, Node *js_context, Node **parameters, int parameter_count)
static bool TryInlining(Zone *zone, const wasm::WasmModule *module, MachineGraph *mcgraph, const wasm::FunctionBody &body, base::Vector< const uint8_t > bytes, SourcePositionTable *source_position_table, int inlining_id)
constexpr IndependentHeapType AsNonNull() const
const WasmModule * module() const
base::Vector< const uint8_t > wire_bytes() const
static constexpr int ToTagged(int offset)
static constexpr int FlagsOffsetInSharedFunctionInfo()
static constexpr WasmEnabledFeatures All()
Zone * zone_
#define COMPRESS_POINTERS_BOOL
Definition globals.h:99
#define FOREACH_WASM_TRAPREASON(V)
Definition globals.h:2650
int start
int end
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
NodeOriginTable * origins
SourcePositionTable * source_positions
int32_t offset
TNode< Object > target
Node * node
ZoneVector< RpoNumber > & result
#define TRACE(...)
const compiler::NullCheckStrategy null_check_strategy_
CompilationEnv *const env_
int position
Definition liveedit.cc:290
const WasmEnabledFeatures enabled_features_
int r
Definition mul-fft.cc:298
STL namespace.
constexpr Vector< T > VectorOf(T *start, size_t size)
Definition vector.h:360
Node * BuildFastApiCall(Isolate *isolate, TFGraph *graph, GraphAssembler *graph_assembler, FastApiCallFunction c_function, Node *data_argument, const GetParameter &get_parameter, const ConvertReturnValue &convert_return_value, const InitializeOptions &initialize_options, const GenerateSlowApiCall &generate_slow_api_call)
AssemblerOptions WasmAssemblerOptions()
AssemblerOptions WasmStubAssemblerOptions()
Signature< MachineRepresentation > * CreateMachineSignature(Zone *zone, const Signature< T > *sig, wasm::CallOrigin origin)
bool IsFastCallSupportedSignature(const v8::CFunctionInfo *sig)
wasm::WasmCompilationResult CompileWasmCapiCallWrapper(const wasm::CanonicalSig *sig)
std::unique_ptr< OptimizedCompilationJob > NewJSToWasmCompilationJob(Isolate *isolate, const wasm::CanonicalSig *sig)
wasm::WasmCompilationResult CompileWasmImportCallWrapper(wasm::ImportCallKind kind, const wasm::CanonicalSig *sig, bool source_positions, int expected_arity, wasm::Suspend suspend)
void BuildInlinedJSToWasmWrapper(Zone *zone, MachineGraph *mcgraph, const wasm::CanonicalSig *signature, Isolate *isolate, compiler::SourcePositionTable *spt, Node *frame_state, bool set_in_wasm_flag)
CallDescriptor * GetWasmCallDescriptor(Zone *zone, const Signature< T > *fsig, WasmCallKind call_kind, bool need_frame_state)
wasm::WasmCompilationResult CompileWasmJSFastCallWrapper(const wasm::CanonicalSig *sig, DirectHandle< JSReceiver > callable)
Handle< Code > CompileCWasmEntry(Isolate *isolate, const wasm::CanonicalSig *sig)
static const Operator * IntPtrConstant(CommonOperatorBuilder *common, intptr_t value)
constexpr int kWasmInstanceDataParameterIndex
constexpr WasmCodePosition kNoCodePosition
constexpr IndependentHeapType kWasmExternRef
bool IsJSCompatibleSignature(const CanonicalSig *sig)
constexpr IndependentHeapType kWasmRefExternString
WasmEngine * GetWasmEngine()
constexpr IndependentValueType kWasmS128
constexpr IndependentValueType kWasmI64
constexpr int kMinParameterIndex
Definition globals.h:2790
switch(set_by_)
Definition flags.cc:3669
Tagged(T object) -> Tagged< T >
V8_INLINE DirectHandle< T > direct_handle(Tagged< T > object, Isolate *isolate)
kWasmInternalFunctionIndirectPointerTag kProtectedInstanceDataOffset sig
constexpr bool IsAnyTagged(MachineRepresentation rep)
Signature< MachineType > MachineSignature
Definition signature.h:151
static constexpr bool kCompressGraphZone
Definition globals.h:525
V8_EXPORT_PRIVATE FlagValues v8_flags
constexpr bool Is64()
JSArrayBuffer::IsDetachableBit is_shared
!IsContextMap !IsContextMap native_context
Definition map-inl.h:877
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define CHECK(condition)
Definition logging.h:124
#define DCHECK_NOT_NULL(val)
Definition logging.h:492
#define DCHECK_IMPLIES(v1, v2)
Definition logging.h:493
#define DCHECK_NE(v1, v2)
Definition logging.h:486
#define CHECK_NE(lhs, rhs)
#define DCHECK_GE(v1, v2)
Definition logging.h:488
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define DCHECK_GT(v1, v2)
Definition logging.h:487
#define arraysize(array)
Definition macros.h:67
static AssemblerOptions Default(Isolate *isolate)
Definition assembler.cc:53
bool function_was_validated(int func_index) const
#define TRACE_EVENT0(category_group, name)
#define TRACE_DISABLED_BY_DEFAULT(name)
#define V8_STATIC_ROOTS_BOOL
Definition v8config.h:1001
#define V8_UNLIKELY(condition)
Definition v8config.h:660
#define LOAD_ROOT(name)
Node * thread_in_wasm_flag_address_
SetOncePointer< const Operator > int32_to_heapnumber_operator_
#define TRAPREASON_TO_TRAPID(name)
SetOncePointer< const Operator > tagged_to_float64_operator_
SetOncePointer< const Operator > float64_to_number_operator_
SetOncePointer< const Operator > float32_to_number_operator_
SetOncePointer< const Operator > tagged_non_smi_to_int32_operator_
WasmWrapperGraphBuilder * wasm_wrapper_graph_builder_
MachineGraph * mcgraph_
SourcePositionTable * source_position_table_
WasmGraphAssembler gasm_
#define ZONE_NAME
Definition zone.h:22