Commit 956ac923 authored by Benedikt Meurer's avatar Benedikt Meurer Committed by Commit Bot

[turbofan] Connect non-returning runtime calls to end.

This changes the BytecodeGraphBuilder to connect runtime calls that
don't return normally, but always throw exceptions, to End (via a Throw
node), instead of inserting Phis on the return values. This unblocks
the new optimization approach for array iteration.

Bug: v8:7510, v8:7514
Change-Id: Ic78216cc27034f191c4850e476f24e598c17deca
Reviewed-on: https://chromium-review.googlesource.com/946250Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51702}
parent bc939300
...@@ -1862,14 +1862,20 @@ Node* BytecodeGraphBuilder::ProcessCallRuntimeArguments( ...@@ -1862,14 +1862,20 @@ Node* BytecodeGraphBuilder::ProcessCallRuntimeArguments(
void BytecodeGraphBuilder::VisitCallRuntime() { void BytecodeGraphBuilder::VisitCallRuntime() {
PrepareEagerCheckpoint(); PrepareEagerCheckpoint();
Runtime::FunctionId functionId = bytecode_iterator().GetRuntimeIdOperand(0); Runtime::FunctionId function_id = bytecode_iterator().GetRuntimeIdOperand(0);
interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1); interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1);
size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2);
// Create node to perform the runtime call. // Create node to perform the runtime call.
const Operator* call = javascript()->CallRuntime(functionId, reg_count); const Operator* call = javascript()->CallRuntime(function_id, reg_count);
Node* value = ProcessCallRuntimeArguments(call, receiver, reg_count); Node* value = ProcessCallRuntimeArguments(call, receiver, reg_count);
environment()->BindAccumulator(value, Environment::kAttachFrameState); environment()->BindAccumulator(value, Environment::kAttachFrameState);
// Connect to the end if {function_id} is non-returning.
if (Runtime::IsNonReturning(function_id)) {
Node* control = NewNode(common()->Throw());
MergeControlToLeaveFunction(control);
}
} }
void BytecodeGraphBuilder::VisitCallRuntimeForPair() { void BytecodeGraphBuilder::VisitCallRuntimeForPair() {
......
...@@ -98,6 +98,39 @@ void InitializeIntrinsicFunctionNames() { ...@@ -98,6 +98,39 @@ void InitializeIntrinsicFunctionNames() {
} // namespace } // namespace
bool Runtime::IsNonReturning(FunctionId id) {
switch (id) {
case Runtime::kThrowUnsupportedSuperError:
case Runtime::kThrowConstructorNonCallableError:
case Runtime::kThrowStaticPrototypeError:
case Runtime::kThrowSuperAlreadyCalledError:
case Runtime::kThrowSuperNotCalled:
case Runtime::kReThrow:
case Runtime::kThrow:
case Runtime::kThrowApplyNonFunction:
case Runtime::kThrowCalledNonCallable:
case Runtime::kThrowConstructedNonConstructable:
case Runtime::kThrowConstructorReturnedNonObject:
case Runtime::kThrowInvalidStringLength:
case Runtime::kThrowInvalidTypedArrayAlignment:
case Runtime::kThrowIteratorResultNotAnObject:
case Runtime::kThrowThrowMethodMissing:
case Runtime::kThrowSymbolIteratorInvalid:
case Runtime::kThrowNotConstructor:
case Runtime::kThrowRangeError:
case Runtime::kThrowReferenceError:
case Runtime::kThrowStackOverflow:
case Runtime::kThrowSymbolAsyncIteratorInvalid:
case Runtime::kThrowTypeError:
case Runtime::kThrowConstAssignError:
case Runtime::kThrowWasmError:
case Runtime::kThrowWasmStackOverflow:
return true;
default:
return false;
}
}
const Runtime::Function* Runtime::FunctionForName(const unsigned char* name, const Runtime::Function* Runtime::FunctionForName(const unsigned char* name,
int length) { int length) {
base::CallOnce(&initialize_function_name_map_once, base::CallOnce(&initialize_function_name_map_once,
......
...@@ -726,6 +726,12 @@ class Runtime : public AllStatic { ...@@ -726,6 +726,12 @@ class Runtime : public AllStatic {
static const int kNotFound = -1; static const int kNotFound = -1;
// Checks whether the runtime function with the given {id} never returns
// to it's caller normally, i.e. whether it'll always raise an exception.
// More specifically: The C++ implementation returns the Heap::exception
// sentinel, always.
static bool IsNonReturning(FunctionId id);
// Get the intrinsic function with the given name. // Get the intrinsic function with the given name.
static const Function* FunctionForName(const unsigned char* name, int length); static const Function* FunctionForName(const unsigned char* name, int length);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment