Commit 1b37ea71 authored by Georg Neis's avatar Georg Neis Committed by Commit Bot

[compiler] Remove error-prone GotoIfException

... in favor of CodeAssembler's ScopedExceptionHandler.

Also remove unused exception arguments from some iterator
related methods.

Bug: v8:10187
Change-Id: I8eb7dfd4eb339e4f566970efa5757c3771926ba6
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2060496
Commit-Queue: Georg Neis <neis@chromium.org>
Auto-Submit: Georg Neis <neis@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#66306}
parent 5d7f29ac
...@@ -13,8 +13,6 @@ ...@@ -13,8 +13,6 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
using compiler::Node;
namespace { namespace {
class AsyncFromSyncBuiltinsAssembler : public AsyncBuiltinsAssembler { class AsyncFromSyncBuiltinsAssembler : public AsyncBuiltinsAssembler {
public: public:
...@@ -130,9 +128,12 @@ void AsyncFromSyncBuiltinsAssembler::Generate_AsyncFromSyncIteratorMethod( ...@@ -130,9 +128,12 @@ void AsyncFromSyncBuiltinsAssembler::Generate_AsyncFromSyncIteratorMethod(
BIND(&if_isnotundefined); BIND(&if_isnotundefined);
} }
const TNode<Object> iter_result = CallJS( TNode<Object> iter_result;
CodeFactory::Call(isolate()), context, method, sync_iterator, sent_value); {
GotoIfException(iter_result, &reject_promise, &var_exception); ScopedExceptionHandler handler(this, &reject_promise, &var_exception);
iter_result = CallJS(CodeFactory::Call(isolate()), context, method,
sync_iterator, sent_value);
}
TNode<Object> value; TNode<Object> value;
TNode<Oddball> done; TNode<Oddball> done;
...@@ -144,10 +145,13 @@ void AsyncFromSyncBuiltinsAssembler::Generate_AsyncFromSyncIteratorMethod( ...@@ -144,10 +145,13 @@ void AsyncFromSyncBuiltinsAssembler::Generate_AsyncFromSyncIteratorMethod(
CSA_ASSERT(this, IsConstructor(promise_fun)); CSA_ASSERT(this, IsConstructor(promise_fun));
// Let valueWrapper be PromiseResolve(%Promise%, « value »). // Let valueWrapper be PromiseResolve(%Promise%, « value »).
const TNode<Object> value_wrapper = CallBuiltin(
Builtins::kPromiseResolve, native_context, promise_fun, value);
// IfAbruptRejectPromise(valueWrapper, promiseCapability). // IfAbruptRejectPromise(valueWrapper, promiseCapability).
GotoIfException(value_wrapper, &reject_promise, &var_exception); TNode<Object> value_wrapper;
{
ScopedExceptionHandler handler(this, &reject_promise, &var_exception);
value_wrapper = CallBuiltin(Builtins::kPromiseResolve, native_context,
promise_fun, value);
}
// Let onFulfilled be a new built-in function object as defined in // Let onFulfilled be a new built-in function object as defined in
// Async Iterator Value Unwrap Functions. // Async Iterator Value Unwrap Functions.
...@@ -200,17 +204,17 @@ AsyncFromSyncBuiltinsAssembler::LoadIteratorResult( ...@@ -200,17 +204,17 @@ AsyncFromSyncBuiltinsAssembler::LoadIteratorResult(
BIND(&if_slowpath); BIND(&if_slowpath);
{ {
ScopedExceptionHandler handler(this, if_exception, var_exception);
// Let nextDone be IteratorComplete(nextResult). // Let nextDone be IteratorComplete(nextResult).
// IfAbruptRejectPromise(nextDone, promiseCapability). // IfAbruptRejectPromise(nextDone, promiseCapability).
const TNode<Object> done = const TNode<Object> done =
GetProperty(context, iter_result, factory()->done_string()); GetProperty(context, iter_result, factory()->done_string());
GotoIfException(done, if_exception, var_exception);
// Let nextValue be IteratorValue(nextResult). // Let nextValue be IteratorValue(nextResult).
// IfAbruptRejectPromise(nextValue, promiseCapability). // IfAbruptRejectPromise(nextValue, promiseCapability).
const TNode<Object> value = const TNode<Object> value =
GetProperty(context, iter_result, factory()->value_string()); GetProperty(context, iter_result, factory()->value_string());
GotoIfException(value, if_exception, var_exception);
var_value = value; var_value = value;
var_done = done; var_done = done;
......
...@@ -150,8 +150,7 @@ void BaseCollectionsAssembler::AddConstructorEntry( ...@@ -150,8 +150,7 @@ void BaseCollectionsAssembler::AddConstructorEntry(
TNode<Object> add_function, TNode<Object> key_value, TNode<Object> add_function, TNode<Object> key_value,
Label* if_may_have_side_effects, Label* if_exception, Label* if_may_have_side_effects, Label* if_exception,
TVariable<Object>* var_exception) { TVariable<Object>* var_exception) {
compiler::CodeAssemblerScopedExceptionHandler handler(this, if_exception, compiler::ScopedExceptionHandler handler(this, if_exception, var_exception);
var_exception);
CSA_ASSERT(this, Word32BinaryNot(IsTheHole(key_value))); CSA_ASSERT(this, Word32BinaryNot(IsTheHole(key_value)));
if (variant == kMap || variant == kWeakMap) { if (variant == kMap || variant == kWeakMap) {
TorqueStructKeyValuePair pair = TorqueStructKeyValuePair pair =
......
...@@ -56,12 +56,16 @@ void GeneratorBuiltinsAssembler::InnerResume( ...@@ -56,12 +56,16 @@ void GeneratorBuiltinsAssembler::InnerResume(
SmiConstant(resume_mode)); SmiConstant(resume_mode));
// Resume the {receiver} using our trampoline. // Resume the {receiver} using our trampoline.
// Close the generator if there was an exception.
TVARIABLE(Object, var_exception); TVARIABLE(Object, var_exception);
Label if_exception(this, Label::kDeferred), if_final_return(this); Label if_exception(this, Label::kDeferred), if_final_return(this);
TNode<Object> result = CallStub(CodeFactory::ResumeGenerator(isolate()), TNode<Object> result;
context, value, receiver); {
// Make sure we close the generator if there was an exception. compiler::ScopedExceptionHandler handler(this, &if_exception,
GotoIfException(result, &if_exception, &var_exception); &var_exception);
result = CallStub(CodeFactory::ResumeGenerator(isolate()), context, value,
receiver);
}
// If the generator is not suspended (i.e., its state is 'executing'), // If the generator is not suspended (i.e., its state is 'executing'),
// close it and wrap the return value in IteratorResult. // close it and wrap the return value in IteratorResult.
......
...@@ -23,53 +23,39 @@ TNode<Object> IteratorBuiltinsAssembler::GetIteratorMethod( ...@@ -23,53 +23,39 @@ TNode<Object> IteratorBuiltinsAssembler::GetIteratorMethod(
return GetProperty(context, object, factory()->iterator_symbol()); return GetProperty(context, object, factory()->iterator_symbol());
} }
IteratorRecord IteratorBuiltinsAssembler::GetIterator( IteratorRecord IteratorBuiltinsAssembler::GetIterator(TNode<Context> context,
TNode<Context> context, TNode<Object> object, Label* if_exception, TNode<Object> object) {
TVariable<Object>* exception) {
TNode<Object> method = GetIteratorMethod(context, object); TNode<Object> method = GetIteratorMethod(context, object);
return GetIterator(context, object, method, if_exception, exception); return GetIterator(context, object, method);
} }
IteratorRecord IteratorBuiltinsAssembler::GetIterator( IteratorRecord IteratorBuiltinsAssembler::GetIterator(TNode<Context> context,
TNode<Context> context, TNode<Object> object, TNode<Object> method, TNode<Object> object,
Label* if_exception, TVariable<Object>* exception) { TNode<Object> method) {
GotoIfException(method, if_exception, exception);
Label if_not_callable(this, Label::kDeferred), if_callable(this); Label if_not_callable(this, Label::kDeferred), if_callable(this);
GotoIf(TaggedIsSmi(method), &if_not_callable); GotoIf(TaggedIsSmi(method), &if_not_callable);
Branch(IsCallable(CAST(method)), &if_callable, &if_not_callable); Branch(IsCallable(CAST(method)), &if_callable, &if_not_callable);
BIND(&if_not_callable); BIND(&if_not_callable);
{ CallRuntime(Runtime::kThrowIteratorError, context, object);
TNode<Object> ret = Unreachable();
CallRuntime(Runtime::kThrowIteratorError, context, object);
GotoIfException(ret, if_exception, exception);
Unreachable();
}
BIND(&if_callable); BIND(&if_callable);
{ {
Callable callable = CodeFactory::Call(isolate()); TNode<Object> iterator =
TNode<Object> iterator = CallJS(callable, context, method, object); CallJS(CodeFactory::Call(isolate()), context, method, object);
GotoIfException(iterator, if_exception, exception);
Label get_next(this), if_notobject(this, Label::kDeferred); Label get_next(this), if_notobject(this, Label::kDeferred);
GotoIf(TaggedIsSmi(iterator), &if_notobject); GotoIf(TaggedIsSmi(iterator), &if_notobject);
Branch(IsJSReceiver(CAST(iterator)), &get_next, &if_notobject); Branch(IsJSReceiver(CAST(iterator)), &get_next, &if_notobject);
BIND(&if_notobject); BIND(&if_notobject);
{ CallRuntime(Runtime::kThrowSymbolIteratorInvalid, context);
TNode<Object> ret = Unreachable();
CallRuntime(Runtime::kThrowSymbolIteratorInvalid, context);
GotoIfException(ret, if_exception, exception);
Unreachable();
}
BIND(&get_next); BIND(&get_next);
const TNode<Object> next = TNode<Object> next =
GetProperty(context, iterator, factory()->next_string()); GetProperty(context, iterator, factory()->next_string());
GotoIfException(next, if_exception, exception);
return IteratorRecord{TNode<JSReceiver>::UncheckedCast(iterator), return IteratorRecord{TNode<JSReceiver>::UncheckedCast(iterator),
TNode<Object>::UncheckedCast(next)}; TNode<Object>::UncheckedCast(next)};
} }
...@@ -77,14 +63,12 @@ IteratorRecord IteratorBuiltinsAssembler::GetIterator( ...@@ -77,14 +63,12 @@ IteratorRecord IteratorBuiltinsAssembler::GetIterator(
TNode<JSReceiver> IteratorBuiltinsAssembler::IteratorStep( TNode<JSReceiver> IteratorBuiltinsAssembler::IteratorStep(
TNode<Context> context, const IteratorRecord& iterator, Label* if_done, TNode<Context> context, const IteratorRecord& iterator, Label* if_done,
base::Optional<TNode<Map>> fast_iterator_result_map, Label* if_exception, base::Optional<TNode<Map>> fast_iterator_result_map) {
TVariable<Object>* exception) {
DCHECK_NOT_NULL(if_done); DCHECK_NOT_NULL(if_done);
// 1. a. Let result be ? Invoke(iterator, "next", « »). // 1. a. Let result be ? Invoke(iterator, "next", « »).
Callable callable = CodeFactory::Call(isolate()); Callable callable = CodeFactory::Call(isolate());
TNode<Object> result = TNode<Object> result =
CallJS(callable, context, iterator.next, iterator.object); CallJS(callable, context, iterator.next, iterator.object);
GotoIfException(result, if_exception, exception);
// 3. If Type(result) is not Object, throw a TypeError exception. // 3. If Type(result) is not Object, throw a TypeError exception.
Label if_notobject(this, Label::kDeferred), return_result(this); Label if_notobject(this, Label::kDeferred), return_result(this);
...@@ -117,17 +101,12 @@ TNode<JSReceiver> IteratorBuiltinsAssembler::IteratorStep( ...@@ -117,17 +101,12 @@ TNode<JSReceiver> IteratorBuiltinsAssembler::IteratorStep(
// 2. Return ToBoolean(? Get(iterResult, "done")). // 2. Return ToBoolean(? Get(iterResult, "done")).
TNode<Object> done = TNode<Object> done =
GetProperty(context, heap_object_result, factory()->done_string()); GetProperty(context, heap_object_result, factory()->done_string());
GotoIfException(done, if_exception, exception);
BranchIfToBooleanIsTrue(done, if_done, &return_result); BranchIfToBooleanIsTrue(done, if_done, &return_result);
} }
BIND(&if_notobject); BIND(&if_notobject);
{ CallRuntime(Runtime::kThrowIteratorResultNotAnObject, context, result);
TNode<Object> ret = Unreachable();
CallRuntime(Runtime::kThrowIteratorResultNotAnObject, context, result);
GotoIfException(ret, if_exception, exception);
Unreachable();
}
BIND(&return_result); BIND(&return_result);
return CAST(heap_object_result); return CAST(heap_object_result);
...@@ -135,8 +114,7 @@ TNode<JSReceiver> IteratorBuiltinsAssembler::IteratorStep( ...@@ -135,8 +114,7 @@ TNode<JSReceiver> IteratorBuiltinsAssembler::IteratorStep(
TNode<Object> IteratorBuiltinsAssembler::IteratorValue( TNode<Object> IteratorBuiltinsAssembler::IteratorValue(
TNode<Context> context, TNode<JSReceiver> result, TNode<Context> context, TNode<JSReceiver> result,
base::Optional<TNode<Map>> fast_iterator_result_map, Label* if_exception, base::Optional<TNode<Map>> fast_iterator_result_map) {
TVariable<Object>* exception) {
Label exit(this); Label exit(this);
TVARIABLE(Object, var_value); TVARIABLE(Object, var_value);
if (fast_iterator_result_map) { if (fast_iterator_result_map) {
...@@ -151,13 +129,8 @@ TNode<Object> IteratorBuiltinsAssembler::IteratorValue( ...@@ -151,13 +129,8 @@ TNode<Object> IteratorBuiltinsAssembler::IteratorValue(
} }
// Generic iterator result case: // Generic iterator result case:
{ var_value = GetProperty(context, result, factory()->value_string());
TNode<Object> value = Goto(&exit);
GetProperty(context, result, factory()->value_string());
GotoIfException(value, if_exception, exception);
var_value = value;
Goto(&exit);
}
BIND(&exit); BIND(&exit);
return var_value.value(); return var_value.value();
...@@ -174,23 +147,24 @@ void IteratorBuiltinsAssembler::IteratorCloseOnException( ...@@ -174,23 +147,24 @@ void IteratorBuiltinsAssembler::IteratorCloseOnException(
CSA_ASSERT(this, IsJSReceiver(iterator.object)); CSA_ASSERT(this, IsJSReceiver(iterator.object));
// Let return be ? GetMethod(iterator, "return"). // Let return be ? GetMethod(iterator, "return").
TNode<Object> method = TNode<Object> method;
GetProperty(context, iterator.object, factory()->return_string()); {
GotoIfException(method, if_exception, exception); compiler::ScopedExceptionHandler handler(this, if_exception, exception);
method = GetProperty(context, iterator.object, factory()->return_string());
}
// If return is undefined, return Completion(completion). // If return is undefined, return Completion(completion).
GotoIf(Word32Or(IsUndefined(method), IsNull(method)), if_exception); GotoIf(Word32Or(IsUndefined(method), IsNull(method)), if_exception);
{ {
// Let innerResult be Call(return, iterator, « »). // Let innerResult be Call(return, iterator, « »).
// If an exception occurs, the original exception remains bound // If an exception occurs, the original exception remains bound.
TNode<Object> inner_result = compiler::ScopedExceptionHandler handler(this, if_exception, nullptr);
CallJS(CodeFactory::Call(isolate()), context, method, iterator.object); CallJS(CodeFactory::Call(isolate()), context, method, iterator.object);
GotoIfException(inner_result, if_exception, nullptr);
// (If completion.[[Type]] is throw) return Completion(completion).
Goto(if_exception);
} }
// (If completion.[[Type]] is throw) return Completion(completion).
Goto(if_exception);
} }
void IteratorBuiltinsAssembler::IteratorCloseOnException( void IteratorBuiltinsAssembler::IteratorCloseOnException(
...@@ -317,10 +291,13 @@ TNode<JSArray> IteratorBuiltinsAssembler::StringListFromIterable( ...@@ -317,10 +291,13 @@ TNode<JSArray> IteratorBuiltinsAssembler::StringListFromIterable(
{ {
// 1. Let error be ThrowCompletion(a newly created TypeError object). // 1. Let error be ThrowCompletion(a newly created TypeError object).
TVARIABLE(Object, var_exception); TVARIABLE(Object, var_exception);
TNode<Object> ret = CallRuntime( {
Runtime::kThrowTypeError, context, compiler::ScopedExceptionHandler handler(this, &if_exception,
SmiConstant(MessageTemplate::kIterableYieldedNonString), next_value); &var_exception);
GotoIfException(ret, &if_exception, &var_exception); CallRuntime(Runtime::kThrowTypeError, context,
SmiConstant(MessageTemplate::kIterableYieldedNonString),
next_value);
}
Unreachable(); Unreachable();
// 2. Return ? IteratorClose(iteratorRecord, error). // 2. Return ? IteratorClose(iteratorRecord, error).
......
...@@ -24,13 +24,9 @@ class IteratorBuiltinsAssembler : public CodeStubAssembler { ...@@ -24,13 +24,9 @@ class IteratorBuiltinsAssembler : public CodeStubAssembler {
// https://tc39.github.io/ecma262/#sec-getiterator --- never used for // https://tc39.github.io/ecma262/#sec-getiterator --- never used for
// @@asyncIterator. // @@asyncIterator.
IteratorRecord GetIterator(TNode<Context> context, TNode<Object> object);
IteratorRecord GetIterator(TNode<Context> context, TNode<Object> object, IteratorRecord GetIterator(TNode<Context> context, TNode<Object> object,
Label* if_exception = nullptr, TNode<Object> method);
TVariable<Object>* exception = nullptr);
IteratorRecord GetIterator(TNode<Context> context, TNode<Object> object,
TNode<Object> method,
Label* if_exception = nullptr,
TVariable<Object>* exception = nullptr);
// https://tc39.github.io/ecma262/#sec-iteratorstep // https://tc39.github.io/ecma262/#sec-iteratorstep
// If the iterator is done, goto {if_done}, otherwise returns an iterator // If the iterator is done, goto {if_done}, otherwise returns an iterator
...@@ -39,9 +35,7 @@ class IteratorBuiltinsAssembler : public CodeStubAssembler { ...@@ -39,9 +35,7 @@ class IteratorBuiltinsAssembler : public CodeStubAssembler {
// object, loaded from the native context. // object, loaded from the native context.
TNode<JSReceiver> IteratorStep( TNode<JSReceiver> IteratorStep(
TNode<Context> context, const IteratorRecord& iterator, Label* if_done, TNode<Context> context, const IteratorRecord& iterator, Label* if_done,
base::Optional<TNode<Map>> fast_iterator_result_map = base::nullopt, base::Optional<TNode<Map>> fast_iterator_result_map = base::nullopt);
Label* if_exception = nullptr, TVariable<Object>* exception = nullptr);
TNode<JSReceiver> IteratorStep( TNode<JSReceiver> IteratorStep(
TNode<Context> context, const IteratorRecord& iterator, TNode<Context> context, const IteratorRecord& iterator,
base::Optional<TNode<Map>> fast_iterator_result_map, Label* if_done) { base::Optional<TNode<Map>> fast_iterator_result_map, Label* if_done) {
...@@ -54,8 +48,7 @@ class IteratorBuiltinsAssembler : public CodeStubAssembler { ...@@ -54,8 +48,7 @@ class IteratorBuiltinsAssembler : public CodeStubAssembler {
// object, loaded from the native context. // object, loaded from the native context.
TNode<Object> IteratorValue( TNode<Object> IteratorValue(
TNode<Context> context, TNode<JSReceiver> result, TNode<Context> context, TNode<JSReceiver> result,
base::Optional<TNode<Map>> fast_iterator_result_map = base::nullopt, base::Optional<TNode<Map>> fast_iterator_result_map = base::nullopt);
Label* if_exception = nullptr, TVariable<Object>* exception = nullptr);
// https://tc39.github.io/ecma262/#sec-iteratorclose // https://tc39.github.io/ecma262/#sec-iteratorclose
void IteratorCloseOnException(TNode<Context> context, void IteratorCloseOnException(TNode<Context> context,
......
...@@ -118,7 +118,7 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask( ...@@ -118,7 +118,7 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask(
TNode<Map> microtask_map = LoadMap(microtask); TNode<Map> microtask_map = LoadMap(microtask);
TNode<Uint16T> microtask_type = LoadMapInstanceType(microtask_map); TNode<Uint16T> microtask_type = LoadMapInstanceType(microtask_map);
TVARIABLE(HeapObject, var_exception, TheHoleConstant()); TVARIABLE(Object, var_exception);
Label if_exception(this, Label::kDeferred); Label if_exception(this, Label::kDeferred);
Label is_callable(this), is_callback(this), Label is_callable(this), is_callback(this),
is_promise_fulfill_reaction_job(this), is_promise_fulfill_reaction_job(this),
...@@ -147,10 +147,12 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask( ...@@ -147,10 +147,12 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask(
TNode<JSReceiver> callable = TNode<JSReceiver> callable =
LoadObjectField<JSReceiver>(microtask, CallableTask::kCallableOffset); LoadObjectField<JSReceiver>(microtask, CallableTask::kCallableOffset);
const TNode<Object> result = CallJS( {
CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined), ScopedExceptionHandler handler(this, &if_exception, &var_exception);
microtask_context, callable, UndefinedConstant()); CallJS(
GotoIfException(result, &if_exception, &var_exception); CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined),
microtask_context, callable, UndefinedConstant());
}
RewindEnteredContext(saved_entered_context_count); RewindEnteredContext(saved_entered_context_count);
SetCurrentContext(current_context); SetCurrentContext(current_context);
Goto(&done); Goto(&done);
...@@ -173,10 +175,11 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask( ...@@ -173,10 +175,11 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask(
// But from our current measurements it doesn't seem to be a // But from our current measurements it doesn't seem to be a
// serious performance problem, even if the microtask is full // serious performance problem, even if the microtask is full
// of CallHandlerTasks (which is not a realistic use case anyways). // of CallHandlerTasks (which is not a realistic use case anyways).
const TNode<Object> result = {
CallRuntime(Runtime::kRunMicrotaskCallback, current_context, ScopedExceptionHandler handler(this, &if_exception, &var_exception);
microtask_callback, microtask_data); CallRuntime(Runtime::kRunMicrotaskCallback, current_context,
GotoIfException(result, &if_exception, &var_exception); microtask_callback, microtask_data);
}
Goto(&done); Goto(&done);
} }
...@@ -195,10 +198,11 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask( ...@@ -195,10 +198,11 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask(
const TNode<Object> thenable = LoadObjectField( const TNode<Object> thenable = LoadObjectField(
microtask, PromiseResolveThenableJobTask::kThenableOffset); microtask, PromiseResolveThenableJobTask::kThenableOffset);
const TNode<Object> result = {
CallBuiltin(Builtins::kPromiseResolveThenableJob, native_context, ScopedExceptionHandler handler(this, &if_exception, &var_exception);
promise_to_resolve, thenable, then); CallBuiltin(Builtins::kPromiseResolveThenableJob, native_context,
GotoIfException(result, &if_exception, &var_exception); promise_to_resolve, thenable, then);
}
RewindEnteredContext(saved_entered_context_count); RewindEnteredContext(saved_entered_context_count);
SetCurrentContext(current_context); SetCurrentContext(current_context);
Goto(&done); Goto(&done);
...@@ -214,7 +218,7 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask( ...@@ -214,7 +218,7 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask(
const TNode<Object> argument = const TNode<Object> argument =
LoadObjectField(microtask, PromiseReactionJobTask::kArgumentOffset); LoadObjectField(microtask, PromiseReactionJobTask::kArgumentOffset);
const TNode<Object> handler = const TNode<Object> job_handler =
LoadObjectField(microtask, PromiseReactionJobTask::kHandlerOffset); LoadObjectField(microtask, PromiseReactionJobTask::kHandlerOffset);
const TNode<HeapObject> promise_or_capability = CAST(LoadObjectField( const TNode<HeapObject> promise_or_capability = CAST(LoadObjectField(
microtask, PromiseReactionJobTask::kPromiseOrCapabilityOffset)); microtask, PromiseReactionJobTask::kPromiseOrCapabilityOffset));
...@@ -223,10 +227,11 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask( ...@@ -223,10 +227,11 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask(
RunPromiseHook(Runtime::kPromiseHookBefore, microtask_context, RunPromiseHook(Runtime::kPromiseHookBefore, microtask_context,
promise_or_capability); promise_or_capability);
const TNode<Object> result = {
CallBuiltin(Builtins::kPromiseFulfillReactionJob, microtask_context, ScopedExceptionHandler handler(this, &if_exception, &var_exception);
argument, handler, promise_or_capability); CallBuiltin(Builtins::kPromiseFulfillReactionJob, microtask_context,
GotoIfException(result, &if_exception, &var_exception); argument, job_handler, promise_or_capability);
}
// Run the promise after/debug hook if enabled. // Run the promise after/debug hook if enabled.
RunPromiseHook(Runtime::kPromiseHookAfter, microtask_context, RunPromiseHook(Runtime::kPromiseHookAfter, microtask_context,
...@@ -247,7 +252,7 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask( ...@@ -247,7 +252,7 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask(
const TNode<Object> argument = const TNode<Object> argument =
LoadObjectField(microtask, PromiseReactionJobTask::kArgumentOffset); LoadObjectField(microtask, PromiseReactionJobTask::kArgumentOffset);
const TNode<Object> handler = const TNode<Object> job_handler =
LoadObjectField(microtask, PromiseReactionJobTask::kHandlerOffset); LoadObjectField(microtask, PromiseReactionJobTask::kHandlerOffset);
const TNode<HeapObject> promise_or_capability = CAST(LoadObjectField( const TNode<HeapObject> promise_or_capability = CAST(LoadObjectField(
microtask, PromiseReactionJobTask::kPromiseOrCapabilityOffset)); microtask, PromiseReactionJobTask::kPromiseOrCapabilityOffset));
...@@ -256,10 +261,11 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask( ...@@ -256,10 +261,11 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask(
RunPromiseHook(Runtime::kPromiseHookBefore, microtask_context, RunPromiseHook(Runtime::kPromiseHookBefore, microtask_context,
promise_or_capability); promise_or_capability);
const TNode<Object> result = {
CallBuiltin(Builtins::kPromiseRejectReactionJob, microtask_context, ScopedExceptionHandler handler(this, &if_exception, &var_exception);
argument, handler, promise_or_capability); CallBuiltin(Builtins::kPromiseRejectReactionJob, microtask_context,
GotoIfException(result, &if_exception, &var_exception); argument, job_handler, promise_or_capability);
}
// Run the promise after/debug hook if enabled. // Run the promise after/debug hook if enabled.
RunPromiseHook(Runtime::kPromiseHookAfter, microtask_context, RunPromiseHook(Runtime::kPromiseHookAfter, microtask_context,
......
...@@ -274,6 +274,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler ...@@ -274,6 +274,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
public TorqueGeneratedExportedMacrosAssembler { public TorqueGeneratedExportedMacrosAssembler {
public: public:
using Node = compiler::Node; using Node = compiler::Node;
using ScopedExceptionHandler = compiler::ScopedExceptionHandler;
template <typename T> template <typename T>
using LazyNode = std::function<TNode<T>()>; using LazyNode = std::function<TNode<T>()>;
......
...@@ -811,35 +811,6 @@ Node* CodeAssembler::Projection(int index, Node* value) { ...@@ -811,35 +811,6 @@ Node* CodeAssembler::Projection(int index, Node* value) {
return raw_assembler()->Projection(index, value); return raw_assembler()->Projection(index, value);
} }
void CodeAssembler::GotoIfException(Node* node, Label* if_exception,
Variable* exception_var) {
if (if_exception == nullptr) {
// If no handler is supplied, don't add continuations
return;
}
// No catch handlers should be active if we're using catch labels
DCHECK_EQ(state()->exception_handler_labels_.size(), 0);
DCHECK(!node->op()->HasProperty(Operator::kNoThrow));
Label success(this), exception(this, Label::kDeferred);
success.MergeVariables();
exception.MergeVariables();
raw_assembler()->Continuations(node, success.label_, exception.label_);
Bind(&exception);
const Operator* op = raw_assembler()->common()->IfException();
Node* exception_value = raw_assembler()->AddNode(op, node, node);
if (exception_var != nullptr) {
exception_var->Bind(exception_value);
}
Goto(if_exception);
Bind(&success);
raw_assembler()->AddNode(raw_assembler()->common()->IfSuccess(), node);
}
TNode<HeapObject> CodeAssembler::OptimizedAllocate( TNode<HeapObject> CodeAssembler::OptimizedAllocate(
TNode<IntPtrT> size, AllocationType allocation, TNode<IntPtrT> size, AllocationType allocation,
AllowLargeObjects allow_large_objects) { AllowLargeObjects allow_large_objects) {
...@@ -1558,7 +1529,7 @@ void CodeAssemblerState::PopExceptionHandler() { ...@@ -1558,7 +1529,7 @@ void CodeAssemblerState::PopExceptionHandler() {
exception_handler_labels_.pop_back(); exception_handler_labels_.pop_back();
} }
CodeAssemblerScopedExceptionHandler::CodeAssemblerScopedExceptionHandler( ScopedExceptionHandler::ScopedExceptionHandler(
CodeAssembler* assembler, CodeAssemblerExceptionHandlerLabel* label) CodeAssembler* assembler, CodeAssemblerExceptionHandlerLabel* label)
: has_handler_(label != nullptr), : has_handler_(label != nullptr),
assembler_(assembler), assembler_(assembler),
...@@ -1569,7 +1540,7 @@ CodeAssemblerScopedExceptionHandler::CodeAssemblerScopedExceptionHandler( ...@@ -1569,7 +1540,7 @@ CodeAssemblerScopedExceptionHandler::CodeAssemblerScopedExceptionHandler(
} }
} }
CodeAssemblerScopedExceptionHandler::CodeAssemblerScopedExceptionHandler( ScopedExceptionHandler::ScopedExceptionHandler(
CodeAssembler* assembler, CodeAssemblerLabel* label, CodeAssembler* assembler, CodeAssemblerLabel* label,
TypedCodeAssemblerVariable<Object>* exception) TypedCodeAssemblerVariable<Object>* exception)
: has_handler_(label != nullptr), : has_handler_(label != nullptr),
...@@ -1583,7 +1554,7 @@ CodeAssemblerScopedExceptionHandler::CodeAssemblerScopedExceptionHandler( ...@@ -1583,7 +1554,7 @@ CodeAssemblerScopedExceptionHandler::CodeAssemblerScopedExceptionHandler(
} }
} }
CodeAssemblerScopedExceptionHandler::~CodeAssemblerScopedExceptionHandler() { ScopedExceptionHandler::~ScopedExceptionHandler() {
if (has_handler_) { if (has_handler_) {
assembler_->state()->PopExceptionHandler(); assembler_->state()->PopExceptionHandler();
} }
...@@ -1595,7 +1566,7 @@ CodeAssemblerScopedExceptionHandler::~CodeAssemblerScopedExceptionHandler() { ...@@ -1595,7 +1566,7 @@ CodeAssemblerScopedExceptionHandler::~CodeAssemblerScopedExceptionHandler() {
} }
TNode<Object> e; TNode<Object> e;
assembler_->Bind(label_.get(), &e); assembler_->Bind(label_.get(), &e);
*exception_ = e; if (exception_ != nullptr) *exception_ = e;
assembler_->Goto(compatibility_label_); assembler_->Goto(compatibility_label_);
if (inside_block) { if (inside_block) {
assembler_->Bind(&skip); assembler_->Bind(&skip);
......
...@@ -1113,10 +1113,6 @@ class V8_EXPORT_PRIVATE CodeAssembler { ...@@ -1113,10 +1113,6 @@ class V8_EXPORT_PRIVATE CodeAssembler {
{cargs...}); {cargs...});
} }
// Exception handling support.
void GotoIfException(Node* node, Label* if_exception,
Variable* exception_var = nullptr);
// Helpers which delegate to RawMachineAssembler. // Helpers which delegate to RawMachineAssembler.
Factory* factory() const; Factory* factory() const;
Isolate* isolate() const; Isolate* isolate() const;
...@@ -1419,7 +1415,7 @@ class V8_EXPORT_PRIVATE CodeAssemblerState { ...@@ -1419,7 +1415,7 @@ class V8_EXPORT_PRIVATE CodeAssemblerState {
friend class CodeAssemblerVariable; friend class CodeAssemblerVariable;
friend class CodeAssemblerTester; friend class CodeAssemblerTester;
friend class CodeAssemblerParameterizedLabelBase; friend class CodeAssemblerParameterizedLabelBase;
friend class CodeAssemblerScopedExceptionHandler; friend class ScopedExceptionHandler;
CodeAssemblerState(Isolate* isolate, Zone* zone, CodeAssemblerState(Isolate* isolate, Zone* zone,
CallDescriptor* call_descriptor, Code::Kind kind, CallDescriptor* call_descriptor, Code::Kind kind,
...@@ -1448,18 +1444,17 @@ class V8_EXPORT_PRIVATE CodeAssemblerState { ...@@ -1448,18 +1444,17 @@ class V8_EXPORT_PRIVATE CodeAssemblerState {
DISALLOW_COPY_AND_ASSIGN(CodeAssemblerState); DISALLOW_COPY_AND_ASSIGN(CodeAssemblerState);
}; };
class V8_EXPORT_PRIVATE CodeAssemblerScopedExceptionHandler { class V8_EXPORT_PRIVATE ScopedExceptionHandler {
public: public:
CodeAssemblerScopedExceptionHandler( ScopedExceptionHandler(CodeAssembler* assembler,
CodeAssembler* assembler, CodeAssemblerExceptionHandlerLabel* label); CodeAssemblerExceptionHandlerLabel* label);
// Use this constructor for compatability/ports of old CSA code only. New code // Use this constructor for compatability/ports of old CSA code only. New code
// should use the CodeAssemblerExceptionHandlerLabel version. // should use the CodeAssemblerExceptionHandlerLabel version.
CodeAssemblerScopedExceptionHandler( ScopedExceptionHandler(CodeAssembler* assembler, CodeAssemblerLabel* label,
CodeAssembler* assembler, CodeAssemblerLabel* label, TypedCodeAssemblerVariable<Object>* exception);
TypedCodeAssemblerVariable<Object>* exception);
~CodeAssemblerScopedExceptionHandler(); ~ScopedExceptionHandler();
private: private:
bool has_handler_; bool has_handler_;
......
...@@ -587,8 +587,8 @@ std::string CSAGenerator::PreCallableExceptionPreparation( ...@@ -587,8 +587,8 @@ std::string CSAGenerator::PreCallableExceptionPreparation(
catch_name = FreshCatchName(); catch_name = FreshCatchName();
out() << " compiler::CodeAssemblerExceptionHandlerLabel " << catch_name out() << " compiler::CodeAssemblerExceptionHandlerLabel " << catch_name
<< "__label(&ca_, compiler::CodeAssemblerLabel::kDeferred);\n"; << "__label(&ca_, compiler::CodeAssemblerLabel::kDeferred);\n";
out() << " { compiler::CodeAssemblerScopedExceptionHandler s(&ca_, &" out() << " { compiler::ScopedExceptionHandler s(&ca_, &" << catch_name
<< catch_name << "__label);\n"; << "__label);\n";
} }
return catch_name; return catch_name;
} }
......
...@@ -34,11 +34,6 @@ Node* UndefinedConstant(CodeAssembler* m) { ...@@ -34,11 +34,6 @@ Node* UndefinedConstant(CodeAssembler* m) {
return m->LoadRoot(RootIndex::kUndefinedValue); return m->LoadRoot(RootIndex::kUndefinedValue);
} }
TNode<Smi> SmiFromInt32(CodeAssembler* m, TNode<Int32T> value) {
return m->BitcastWordToTaggedSigned(
m->WordShl(m->ChangeInt32ToIntPtr(value), kSmiShiftSize + kSmiTagSize));
}
Node* LoadObjectField(CodeAssembler* m, Node* object, int offset, Node* LoadObjectField(CodeAssembler* m, Node* object, int offset,
MachineType type = MachineType::AnyTagged()) { MachineType type = MachineType::AnyTagged()) {
return m->Load(type, object, m->IntPtrConstant(offset - kHeapObjectTag)); return m->Load(type, object, m->IntPtrConstant(offset - kHeapObjectTag));
...@@ -445,128 +440,6 @@ TEST(TestOutOfScopeVariable) { ...@@ -445,128 +440,6 @@ TEST(TestOutOfScopeVariable) {
CHECK(!asm_tester.GenerateCode().is_null()); CHECK(!asm_tester.GenerateCode().is_null());
} }
TEST(GotoIfException) {
Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 1;
CodeAssemblerTester asm_tester(isolate, kNumParams);
CodeAssembler m(asm_tester.state());
TNode<Context> context =
m.HeapConstant(Handle<Context>(isolate->native_context()));
TNode<Symbol> to_string_tag =
m.HeapConstant(isolate->factory()->to_string_tag_symbol());
Variable exception(&m, MachineRepresentation::kTagged);
CodeAssemblerLabel exception_handler(&m);
Callable to_string = Builtins::CallableFor(isolate, Builtins::kToString);
TNode<Object> string = m.CallStub(to_string, context, to_string_tag);
m.GotoIfException(string, &exception_handler, &exception);
m.Return(string);
m.Bind(&exception_handler);
m.Return(m.UncheckedCast<Object>(exception.value()));
FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
Handle<Object> result = ft.Call().ToHandleChecked();
// Should be a TypeError.
CHECK(result->IsJSObject());
Handle<Object> constructor =
Object::GetPropertyOrElement(isolate, result,
isolate->factory()->constructor_string())
.ToHandleChecked();
CHECK(constructor->SameValue(*isolate->type_error_function()));
}
TEST(GotoIfExceptionMultiple) {
Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 4; // receiver, first, second, third
CodeAssemblerTester asm_tester(isolate, kNumParams);
CodeAssembler m(asm_tester.state());
TNode<Context> context =
m.HeapConstant(Handle<Context>(isolate->native_context()));
Node* first_value = m.Parameter(0);
Node* second_value = m.Parameter(1);
Node* third_value = m.Parameter(2);
CodeAssemblerLabel exception_handler1(&m);
CodeAssemblerLabel exception_handler2(&m);
CodeAssemblerLabel exception_handler3(&m);
Variable return_value(&m, MachineRepresentation::kWord32);
Variable error(&m, MachineRepresentation::kTagged);
return_value.Bind(m.Int32Constant(0));
// try { return ToString(param1) } catch (e) { ... }
Callable to_string = Builtins::CallableFor(isolate, Builtins::kToString);
TNode<Object> string = m.CallStub(to_string, context, first_value);
m.GotoIfException(string, &exception_handler1, &error);
m.Return(string);
// try { ToString(param2); return 7 } catch (e) { ... }
m.Bind(&exception_handler1);
return_value.Bind(m.Int32Constant(7));
error.Bind(UndefinedConstant(&m));
string = m.CallStub(to_string, context, second_value);
m.GotoIfException(string, &exception_handler2, &error);
m.Return(SmiFromInt32(&m, m.UncheckedCast<Int32T>(return_value.value())));
// try { ToString(param3); return 7 & ~2; } catch (e) { return e; }
m.Bind(&exception_handler2);
// Return returnValue & ~2
error.Bind(UndefinedConstant(&m));
string = m.CallStub(to_string, context, third_value);
m.GotoIfException(string, &exception_handler3, &error);
m.Return(SmiFromInt32(
&m, m.UncheckedCast<Int32T>(m.Word32And(
return_value.value(),
m.Word32Xor(m.Int32Constant(2), m.Int32Constant(-1))))));
m.Bind(&exception_handler3);
m.Return(m.UncheckedCast<Object>(error.value()));
FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
Handle<Object> result;
// First handler does not throw, returns result of first value.
result = ft.Call(isolate->factory()->undefined_value(),
isolate->factory()->to_string_tag_symbol())
.ToHandleChecked();
CHECK(String::cast(*result).IsOneByteEqualTo(OneByteVector("undefined")));
// First handler returns a number.
result = ft.Call(isolate->factory()->to_string_tag_symbol(),
isolate->factory()->undefined_value())
.ToHandleChecked();
CHECK_EQ(7, Smi::ToInt(*result));
// First handler throws, second handler returns a number.
result = ft.Call(isolate->factory()->to_string_tag_symbol(),
isolate->factory()->to_primitive_symbol())
.ToHandleChecked();
CHECK_EQ(7 & ~2, Smi::ToInt(*result));
// First handler throws, second handler throws, third handler returns thrown
// value.
result = ft.Call(isolate->factory()->to_string_tag_symbol(),
isolate->factory()->to_primitive_symbol(),
isolate->factory()->unscopables_symbol())
.ToHandleChecked();
// Should be a TypeError.
CHECK(result->IsJSObject());
Handle<Object> constructor =
Object::GetPropertyOrElement(isolate, result,
isolate->factory()->constructor_string())
.ToHandleChecked();
CHECK(constructor->SameValue(*isolate->type_error_function()));
}
TEST(ExceptionHandler) { TEST(ExceptionHandler) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 0; const int kNumParams = 0;
...@@ -576,7 +449,7 @@ TEST(ExceptionHandler) { ...@@ -576,7 +449,7 @@ TEST(ExceptionHandler) {
CodeAssembler::TVariable<Object> var(m.SmiConstant(0), &m); CodeAssembler::TVariable<Object> var(m.SmiConstant(0), &m);
CodeAssemblerLabel exception(&m, {&var}, CodeAssemblerLabel::kDeferred); CodeAssemblerLabel exception(&m, {&var}, CodeAssemblerLabel::kDeferred);
{ {
CodeAssemblerScopedExceptionHandler handler(&m, &exception, &var); ScopedExceptionHandler handler(&m, &exception, &var);
TNode<Context> context = TNode<Context> context =
m.HeapConstant(Handle<Context>(isolate->native_context())); m.HeapConstant(Handle<Context>(isolate->native_context()));
m.CallRuntime(Runtime::kThrow, context, m.SmiConstant(2)); m.CallRuntime(Runtime::kThrow, context, m.SmiConstant(2));
......
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