Commit 52ff3ae4 authored by Caitlin Potter's avatar Caitlin Potter Committed by Commit Bot

[builtins] implement RunMicrotasks pump as a code stub

- Implement RunMicrotasks in CSA to prevent a potentially large number
  of jumps between C++ and JS code while consuming te queue. Appears to
  provide a ~60% speedup in microtask-heavy code, which from limited
  testing appears to scale linearly.

  The code-stub microtask pump bails out to the old C++ microtask pump
  if it encounters a CallHandlerInfo microtask, and remains in C++ for
  the remainder of the queue (returning to the JS/stub implementation
  after the bailed out queue is exhausted).

- Add a variation of JSEntryStub which enters the new RunMicrotasks code
  stub.

- Add a new RunMicrotasks helper to Execution, which uses the
  RunMicrotasks entry stub.

Bug: 
Change-Id: I4667d4dd633d24455ea5d7cef239da0af1a7365e
Reviewed-on: https://chromium-review.googlesource.com/650486
Commit-Queue: Caitlin Potter <caitp@igalia.com>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#49842}
parent fd554885
......@@ -405,6 +405,7 @@ class HandleScopeImplementer {
call_depth_(0),
microtasks_depth_(0),
microtasks_suppressions_(0),
entered_contexts_count_(0),
entered_context_count_during_microtasks_(0),
#ifdef DEBUG
debug_microtasks_depth_(0),
......@@ -531,6 +532,7 @@ class HandleScopeImplementer {
int call_depth_;
int microtasks_depth_;
int microtasks_suppressions_;
size_t entered_contexts_count_;
size_t entered_context_count_during_microtasks_;
#ifdef DEBUG
int debug_microtasks_depth_;
......@@ -546,10 +548,25 @@ class HandleScopeImplementer {
friend class DeferredHandles;
friend class DeferredHandleScope;
friend class HandleScopeImplementerOffsets;
DISALLOW_COPY_AND_ASSIGN(HandleScopeImplementer);
};
class HandleScopeImplementerOffsets {
public:
enum Offsets {
kMicrotaskContext = offsetof(HandleScopeImplementer, microtask_context_),
kEnteredContexts = offsetof(HandleScopeImplementer, entered_contexts_),
kEnteredContextsCount =
offsetof(HandleScopeImplementer, entered_contexts_count_),
kEnteredContextCountDuringMicrotasks = offsetof(
HandleScopeImplementer, entered_context_count_during_microtasks_)
};
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(HandleScopeImplementerOffsets);
};
const int kHandleBlockSize = v8::internal::KB - 2; // fit in one page
......@@ -584,9 +601,13 @@ bool HandleScopeImplementer::HasSavedContexts() {
void HandleScopeImplementer::EnterContext(Handle<Context> context) {
entered_contexts_.push_back(*context);
entered_contexts_count_ = entered_contexts_.size();
}
void HandleScopeImplementer::LeaveContext() { entered_contexts_.pop_back(); }
void HandleScopeImplementer::LeaveContext() {
entered_contexts_.pop_back();
entered_contexts_count_ = entered_contexts_.size();
}
bool HandleScopeImplementer::LastEnteredContextWas(Handle<Context> context) {
return !entered_contexts_.empty() && entered_contexts_.back() == *context;
......
......@@ -414,6 +414,8 @@ void JSEntryStub::Generate(MacroAssembler* masm) {
// Set up the reserved register for 0.0.
__ vmov(kDoubleRegZero, Double(0.0));
__ InitializeRootRegister();
// Get address of argv, see stm above.
// r0: code entry
// r1: function
......@@ -509,12 +511,7 @@ void JSEntryStub::Generate(MacroAssembler* masm) {
// r2: receiver
// r3: argc
// r4: argv
if (type() == StackFrame::CONSTRUCT_ENTRY) {
__ Call(BUILTIN_CODE(isolate(), JSConstructEntryTrampoline),
RelocInfo::CODE_TARGET);
} else {
__ Call(BUILTIN_CODE(isolate(), JSEntryTrampoline), RelocInfo::CODE_TARGET);
}
__ Call(EntryTrampoline(), RelocInfo::CODE_TARGET);
// Unlink this frame from the handler chain.
__ PopStackHandler();
......
......@@ -517,6 +517,9 @@ void JSEntryStub::Generate(MacroAssembler* masm) {
// Set up the reserved register for 0.0.
__ Fmov(fp_zero, 0.0);
// Initialize the root array register
__ InitializeRootRegister();
// Build an entry frame (see layout below).
StackFrame::Type marker = type();
int64_t bad_frame_pointer = -1L; // Bad frame pointer to fail if it is used.
......@@ -612,13 +615,7 @@ void JSEntryStub::Generate(MacroAssembler* masm) {
// x2: receiver.
// x3: argc.
// x4: argv.
if (type() == StackFrame::CONSTRUCT_ENTRY) {
__ Call(BUILTIN_CODE(isolate(), JSConstructEntryTrampoline),
RelocInfo::CODE_TARGET);
} else {
__ Call(BUILTIN_CODE(isolate(), JSEntryTrampoline), RelocInfo::CODE_TARGET);
}
__ Call(EntryTrampoline(), RelocInfo::CODE_TARGET);
// Pop the stack handler and unlink this frame from the handler chain.
static_assert(StackHandlerConstants::kNextOffset == 0 * kPointerSize,
......
......@@ -801,6 +801,16 @@ ExternalReference ExternalReference::builtins_address(Isolate* isolate) {
return ExternalReference(isolate->builtins()->builtins_table_address());
}
ExternalReference ExternalReference::handle_scope_implementer_address(
Isolate* isolate) {
return ExternalReference(isolate->handle_scope_implementer_address());
}
ExternalReference ExternalReference::pending_microtask_count_address(
Isolate* isolate) {
return ExternalReference(isolate->pending_microtask_count_address());
}
ExternalReference ExternalReference::interpreter_dispatch_table_address(
Isolate* isolate) {
return ExternalReference(isolate->interpreter()->dispatch_table_address());
......
......@@ -824,6 +824,9 @@ class ExternalReference BASE_EMBEDDED {
// The builtins table as an external reference, used by lazy deserialization.
static ExternalReference builtins_address(Isolate* isolate);
static ExternalReference handle_scope_implementer_address(Isolate* isolate);
static ExternalReference pending_microtask_count_address(Isolate* isolate);
// One-of-a-kind references. These references are not part of a general
// pattern. This means that they have to be added to the
// ExternalReferenceTable in serialize.cc manually.
......
......@@ -2410,8 +2410,9 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
}
{ // Internal: PromiseHandle
Handle<JSFunction> function = SimpleCreateFunction(
isolate, factory->empty_string(), Builtins::kPromiseHandle, 5, false);
Handle<JSFunction> function =
SimpleCreateFunction(isolate, factory->empty_string(),
Builtins::kPromiseHandleJS, 5, false);
native_context()->set_promise_handle(*function);
}
......
......@@ -629,8 +629,6 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
__ mov(cp, Operand(context_address));
__ ldr(cp, MemOperand(cp));
__ InitializeRootRegister();
// Push the function and the receiver onto the stack.
__ Push(r1, r2);
......
......@@ -226,6 +226,8 @@ namespace internal {
TFS(RejectNativePromise, kPromise, kValue, kDebugEvent) \
TFS(PerformNativePromiseThen, kPromise, kResolveReaction, kRejectReaction, \
kResultPromise) \
TFC(RunMicrotasks, RunMicrotasks, 1) \
TFS(PromiseResolveThenableJob, kMicrotask) \
\
/* Object property helpers */ \
TFS(HasProperty, kKey, kObject) \
......@@ -777,7 +779,9 @@ namespace internal {
/* ES #sec-fulfillpromise */ \
TFJ(ResolvePromise, 2, kPromise, kValue) \
TFS(PromiseHandleReject, kPromise, kOnReject, kException) \
TFJ(PromiseHandle, 5, kValue, kHandler, kDeferredPromise, \
TFS(PromiseHandle, kValue, kHandler, kDeferredPromise, kDeferredOnResolve, \
kDeferredOnReject) \
TFJ(PromiseHandleJS, 5, kValue, kHandler, kDeferredPromise, \
kDeferredOnResolve, kDeferredOnReject) \
/* ES #sec-promise.resolve */ \
TFJ(PromiseResolveWrapper, 1, kValue) \
......
This diff is collapsed.
......@@ -1183,7 +1183,14 @@ TF_BUILTIN(PromiseHandleReject, PromiseBuiltinsAssembler) {
BIND(&if_customhandler);
{
CallJS(call_callable, context, on_reject, UndefinedConstant(), exception);
VARIABLE(var_exception, MachineRepresentation::kTagged, TheHoleConstant());
Label if_exception(this);
Node* const ret = CallJS(call_callable, context, on_reject,
UndefinedConstant(), exception);
GotoIfException(ret, &if_exception, &var_exception);
Return(UndefinedConstant());
BIND(&if_exception);
CallRuntime(Runtime::kReportMessage, context, var_exception.value());
Return(UndefinedConstant());
}
}
......@@ -1297,6 +1304,20 @@ TF_BUILTIN(PromiseHandle, PromiseBuiltinsAssembler) {
}
}
TF_BUILTIN(PromiseHandleJS, PromiseBuiltinsAssembler) {
Node* const value = Parameter(Descriptor::kValue);
Node* const handler = Parameter(Descriptor::kHandler);
Node* const deferred_promise = Parameter(Descriptor::kDeferredPromise);
Node* const deferred_on_resolve = Parameter(Descriptor::kDeferredOnResolve);
Node* const deferred_on_reject = Parameter(Descriptor::kDeferredOnReject);
Node* const context = Parameter(Descriptor::kContext);
Node* const result =
CallBuiltin(Builtins::kPromiseHandle, context, value, handler,
deferred_promise, deferred_on_resolve, deferred_on_reject);
Return(result);
}
// ES#sec-promise.prototype.catch
// Promise.prototype.catch ( onRejected )
TF_BUILTIN(PromiseCatch, PromiseBuiltinsAssembler) {
......
......@@ -697,10 +697,18 @@ class CEntryStub : public PlatformCodeStub {
class JSEntryStub : public PlatformCodeStub {
public:
enum class SpecialTarget { kNone, kRunMicrotasks };
JSEntryStub(Isolate* isolate, StackFrame::Type type)
: PlatformCodeStub(isolate) {
DCHECK(type == StackFrame::ENTRY || type == StackFrame::CONSTRUCT_ENTRY);
minor_key_ = StackFrameTypeBits::encode(type);
minor_key_ = StackFrameTypeBits::encode(type) |
SpecialTargetBits::encode(SpecialTarget::kNone);
}
JSEntryStub(Isolate* isolate, SpecialTarget target)
: PlatformCodeStub(isolate) {
minor_key_ = StackFrameTypeBits::encode(StackFrame::ENTRY) |
SpecialTargetBits::encode(target);
}
private:
......@@ -715,7 +723,26 @@ class JSEntryStub : public PlatformCodeStub {
return StackFrameTypeBits::decode(minor_key_);
}
SpecialTarget special_target() const {
return SpecialTargetBits::decode(minor_key_);
}
Handle<Code> EntryTrampoline() {
switch (special_target()) {
case SpecialTarget::kNone:
return (type() == StackFrame::CONSTRUCT_ENTRY)
? BUILTIN_CODE(isolate(), JSConstructEntryTrampoline)
: BUILTIN_CODE(isolate(), JSEntryTrampoline);
case SpecialTarget::kRunMicrotasks:
return BUILTIN_CODE(isolate(), RunMicrotasks);
}
UNREACHABLE();
return Handle<Code>();
}
class StackFrameTypeBits : public BitField<StackFrame::Type, 0, 5> {};
class SpecialTargetBits
: public BitField<SpecialTarget, StackFrameTypeBits::kNext, 1> {};
int handler_offset_;
......
......@@ -55,7 +55,8 @@ namespace {
MUST_USE_RESULT MaybeHandle<Object> Invoke(
Isolate* isolate, bool is_construct, Handle<Object> target,
Handle<Object> receiver, int argc, Handle<Object> args[],
Handle<Object> new_target, Execution::MessageHandling message_handling) {
Handle<Object> new_target, Execution::MessageHandling message_handling,
Execution::Target execution_target) {
DCHECK(!receiver->IsJSGlobalObject());
#ifdef USE_SIMULATOR
......@@ -117,9 +118,18 @@ MUST_USE_RESULT MaybeHandle<Object> Invoke(
Object* receiver, int argc,
Object*** args);
Handle<Code> code = is_construct
? isolate->factory()->js_construct_entry_code()
: isolate->factory()->js_entry_code();
Handle<Code> code;
switch (execution_target) {
case Execution::Target::kCallable:
code = is_construct ? isolate->factory()->js_construct_entry_code()
: isolate->factory()->js_entry_code();
break;
case Execution::Target::kRunMicrotasks:
code = isolate->factory()->js_run_microtasks_entry_code();
break;
default:
UNREACHABLE();
}
{
// Save and restore context around invocation and block the
......@@ -167,7 +177,8 @@ MUST_USE_RESULT MaybeHandle<Object> Invoke(
MaybeHandle<Object> CallInternal(Isolate* isolate, Handle<Object> callable,
Handle<Object> receiver, int argc,
Handle<Object> argv[],
Execution::MessageHandling message_handling) {
Execution::MessageHandling message_handling,
Execution::Target target) {
// Convert calls on global objects to be calls on the global
// receiver instead to avoid having a 'this' pointer which refers
// directly to a global object.
......@@ -176,7 +187,8 @@ MaybeHandle<Object> CallInternal(Isolate* isolate, Handle<Object> callable,
handle(Handle<JSGlobalObject>::cast(receiver)->global_proxy(), isolate);
}
return Invoke(isolate, false, callable, receiver, argc, argv,
isolate->factory()->undefined_value(), message_handling);
isolate->factory()->undefined_value(), message_handling,
target);
}
} // namespace
......@@ -186,7 +198,7 @@ MaybeHandle<Object> Execution::Call(Isolate* isolate, Handle<Object> callable,
Handle<Object> receiver, int argc,
Handle<Object> argv[]) {
return CallInternal(isolate, callable, receiver, argc, argv,
MessageHandling::kReport);
MessageHandling::kReport, Execution::Target::kCallable);
}
......@@ -203,15 +215,13 @@ MaybeHandle<Object> Execution::New(Isolate* isolate, Handle<Object> constructor,
Handle<Object> argv[]) {
return Invoke(isolate, true, constructor,
isolate->factory()->undefined_value(), argc, argv, new_target,
MessageHandling::kReport);
MessageHandling::kReport, Execution::Target::kCallable);
}
MaybeHandle<Object> Execution::TryCall(Isolate* isolate,
Handle<Object> callable,
Handle<Object> receiver, int argc,
Handle<Object> args[],
MessageHandling message_handling,
MaybeHandle<Object>* exception_out) {
MaybeHandle<Object> Execution::TryCall(
Isolate* isolate, Handle<Object> callable, Handle<Object> receiver,
int argc, Handle<Object> args[], MessageHandling message_handling,
MaybeHandle<Object>* exception_out, Target target) {
bool is_termination = false;
MaybeHandle<Object> maybe_result;
if (exception_out != nullptr) *exception_out = MaybeHandle<Object>();
......@@ -226,8 +236,8 @@ MaybeHandle<Object> Execution::TryCall(Isolate* isolate,
catcher.SetVerbose(false);
catcher.SetCaptureMessage(false);
maybe_result =
CallInternal(isolate, callable, receiver, argc, args, message_handling);
maybe_result = CallInternal(isolate, callable, receiver, argc, args,
message_handling, target);
if (maybe_result.is_null()) {
DCHECK(isolate->has_pending_exception());
......@@ -253,6 +263,13 @@ MaybeHandle<Object> Execution::TryCall(Isolate* isolate,
return maybe_result;
}
MaybeHandle<Object> Execution::RunMicrotasks(
Isolate* isolate, MessageHandling message_handling,
MaybeHandle<Object>* exception_out) {
auto undefined = isolate->factory()->undefined_value();
return TryCall(isolate, undefined, undefined, 0, {}, message_handling,
exception_out, Target::kRunMicrotasks);
}
void StackGuard::SetStackLimit(uintptr_t limit) {
ExecutionAccess access(isolate_);
......
......@@ -20,6 +20,7 @@ class Execution final : public AllStatic {
public:
// Whether to report pending messages, or keep them pending on the isolate.
enum class MessageHandling { kReport, kKeepPending };
enum class Target { kCallable, kRunMicrotasks };
// Call a function, the caller supplies a receiver and an array
// of arguments.
......@@ -54,7 +55,12 @@ class Execution final : public AllStatic {
Handle<Object> receiver, int argc,
Handle<Object> argv[],
MessageHandling message_handling,
MaybeHandle<Object>* exception_out);
MaybeHandle<Object>* exception_out,
Target target = Target::kCallable);
// Convenience method for performing RunMicrotasks
static MaybeHandle<Object> RunMicrotasks(Isolate* isolate,
MessageHandling message_handling,
MaybeHandle<Object>* exception_out);
};
......
......@@ -92,6 +92,10 @@ void ExternalReferenceTable::AddReferences(Isolate* isolate) {
"LDoubleConstant::one_half");
Add(ExternalReference::isolate_address(isolate).address(), "isolate");
Add(ExternalReference::builtins_address(isolate).address(), "builtins");
Add(ExternalReference::handle_scope_implementer_address(isolate).address(),
"Isolate::handle_scope_implementer_address");
Add(ExternalReference::pending_microtask_count_address(isolate).address(),
"Isolate::pending_microtask_count_address()");
Add(ExternalReference::interpreter_dispatch_table_address(isolate).address(),
"Interpreter::dispatch_table_address");
Add(ExternalReference::bytecode_size_table_address(isolate).address(),
......
......@@ -1459,7 +1459,9 @@ enum class ConcurrencyMode { kNotConcurrent, kConcurrent };
C(PendingHandlerFP, pending_handler_fp) \
C(PendingHandlerSP, pending_handler_sp) \
C(ExternalCaughtException, external_caught_exception) \
C(JSEntrySP, js_entry_sp)
C(JSEntrySP, js_entry_sp) \
C(MicrotaskQueueBailoutIndex, microtask_queue_bailout_index) \
C(MicrotaskQueueBailoutCount, microtask_queue_bailout_count)
enum IsolateAddressId {
#define DECLARE_ENUM(CamelName, hacker_name) k##CamelName##Address,
......
......@@ -2629,6 +2629,10 @@ void Heap::CreateJSConstructEntryStub() {
set_js_construct_entry_code(*stub.GetCode());
}
void Heap::CreateJSRunMicrotasksEntryStub() {
JSEntryStub stub(isolate(), JSEntryStub::SpecialTarget::kRunMicrotasks);
set_js_run_microtasks_entry_code(*stub.GetCode());
}
void Heap::CreateFixedStubs() {
// Here we create roots for fixed stubs. They are needed at GC
......@@ -2660,6 +2664,7 @@ void Heap::CreateFixedStubs() {
// To workaround the problem, make separate functions without inlining.
Heap::CreateJSEntryStub();
Heap::CreateJSConstructEntryStub();
Heap::CreateJSRunMicrotasksEntryStub();
}
bool Heap::RootCanBeWrittenAfterInitialization(Heap::RootListIndex root_index) {
......
......@@ -256,7 +256,8 @@ using v8::MemoryPressureLevel;
DeserializeLazyHandlerExtraWide) \
/* JS Entries */ \
V(Code, js_entry_code, JsEntryCode) \
V(Code, js_construct_entry_code, JsConstructEntryCode)
V(Code, js_construct_entry_code, JsConstructEntryCode) \
V(Code, js_run_microtasks_entry_code, JsRunMicrotasksEntryCode)
// Entries in this list are limited to Smis and are not visited during GC.
#define SMI_ROOT_LIST(V) \
......@@ -1830,6 +1831,7 @@ class Heap {
// because of a gcc-4.4 bug that assigns wrong vtable entries.
NO_INLINE(void CreateJSEntryStub());
NO_INLINE(void CreateJSConstructEntryStub());
NO_INLINE(void CreateJSRunMicrotasksEntryStub());
void CreateFixedStubs();
......
......@@ -486,12 +486,7 @@ void JSEntryStub::Generate(MacroAssembler* masm) {
// pop the faked function when we return. Notice that we cannot store a
// reference to the trampoline code directly in this stub, because the
// builtin stubs may not have been generated yet.
if (type() == StackFrame::CONSTRUCT_ENTRY) {
__ Call(BUILTIN_CODE(isolate(), JSConstructEntryTrampoline),
RelocInfo::CODE_TARGET);
} else {
__ Call(BUILTIN_CODE(isolate(), JSEntryTrampoline), RelocInfo::CODE_TARGET);
}
__ Call(EntryTrampoline(), RelocInfo::CODE_TARGET);
// Unlink this frame from the handler chain.
__ PopStackHandler();
......
......@@ -78,6 +78,7 @@ class PlatformInterfaceDescriptor;
V(ResumeGenerator) \
V(FrameDropperTrampoline) \
V(WasmRuntimeCall) \
V(RunMicrotasks) \
BUILTIN_LIST_TFS(V)
class V8_EXPORT_PRIVATE CallInterfaceDescriptorData {
......@@ -846,6 +847,13 @@ class WasmRuntimeCallDescriptor final : public CallInterfaceDescriptor {
0)
};
class RunMicrotasksDescriptor final : public CallInterfaceDescriptor {
public:
DEFINE_EMPTY_PARAMETERS()
DECLARE_DEFAULT_DESCRIPTOR(RunMicrotasksDescriptor, CallInterfaceDescriptor,
0)
};
#define DEFINE_TFS_BUILTIN_DESCRIPTOR(Name, ...) \
class Name##Descriptor : public CallInterfaceDescriptor { \
public: \
......
This diff is collapsed.
......@@ -373,6 +373,9 @@ class ThreadLocalTop BASE_EMBEDDED {
// Call back function to report unsafe JS accesses.
v8::FailedAccessCheckCallback failed_access_check_callback_;
int microtask_queue_bailout_index_;
int microtask_queue_bailout_count_;
private:
void InitializeInternal();
......@@ -675,6 +678,18 @@ class Isolate {
return &thread_local_top_.js_entry_sp_;
}
THREAD_LOCAL_TOP_ACCESSOR(int, microtask_queue_bailout_index)
Address microtask_queue_bailout_index_address() {
return reinterpret_cast<Address>(
&thread_local_top_.microtask_queue_bailout_index_);
}
THREAD_LOCAL_TOP_ACCESSOR(int, microtask_queue_bailout_count)
Address microtask_queue_bailout_count_address() {
return reinterpret_cast<Address>(
&thread_local_top_.microtask_queue_bailout_count_);
}
// Returns the global object of the current context. It could be
// a builtin object, or a JS global object.
inline Handle<JSGlobalObject> global_object();
......@@ -808,6 +823,11 @@ class Isolate {
// Un-schedule an exception that was caught by a TryCatch handler.
void CancelScheduledExceptionFromTryCatch(v8::TryCatch* handler);
void ReportPendingMessages();
void ReportPendingMessagesFromJavaScript();
// Implements code shared between the two above methods
void ReportPendingMessagesImpl(bool report_externally);
// Return pending location if any or unfilled structure.
MessageLocation GetMessageLocation();
......@@ -1210,6 +1230,7 @@ class Isolate {
void PromiseResolveThenableJob(Handle<PromiseResolveThenableJobInfo> info,
MaybeHandle<Object>* result,
MaybeHandle<Object>* maybe_exception);
void EnqueueMicrotask(Handle<Object> microtask);
void RunMicrotasks();
bool IsRunningMicrotasks() const { return is_running_microtasks_; }
......@@ -1233,6 +1254,14 @@ class Isolate {
return reinterpret_cast<Address>(&promise_hook_or_debug_is_active_);
}
Address pending_microtask_count_address() {
return reinterpret_cast<Address>(&pending_microtask_count_);
}
Address handle_scope_implementer_address() {
return reinterpret_cast<Address>(&handle_scope_implementer_);
}
void DebugStateUpdated();
void SetPromiseHook(PromiseHook hook);
......
......@@ -589,13 +589,7 @@ void JSEntryStub::Generate(MacroAssembler* masm) {
// callee saved registers + ra
// 4 args slots
// args
if (type() == StackFrame::CONSTRUCT_ENTRY) {
__ Call(BUILTIN_CODE(isolate, JSConstructEntryTrampoline),
RelocInfo::CODE_TARGET);
} else {
__ Call(BUILTIN_CODE(isolate, JSEntryTrampoline), RelocInfo::CODE_TARGET);
}
__ Call(EntryTrampoline(), RelocInfo::CODE_TARGET);
// Unlink this frame from the handler chain.
__ PopStackHandler();
......
......@@ -587,13 +587,7 @@ void JSEntryStub::Generate(MacroAssembler* masm) {
// callee saved registers + ra
// [ O32: 4 args slots]
// args
if (type() == StackFrame::CONSTRUCT_ENTRY) {
__ Call(BUILTIN_CODE(isolate, JSConstructEntryTrampoline),
RelocInfo::CODE_TARGET);
} else {
__ Call(BUILTIN_CODE(isolate, JSEntryTrampoline), RelocInfo::CODE_TARGET);
}
__ Call(EntryTrampoline(), RelocInfo::CODE_TARGET);
// Unlink this frame from the handler chain.
__ PopStackHandler();
......
......@@ -6,6 +6,7 @@
#include <memory>
#include "src/api.h"
#include "src/arguments.h"
#include "src/ast/prettyprinter.h"
#include "src/bootstrapper.h"
......@@ -650,5 +651,22 @@ RUNTIME_FUNCTION(Runtime_GetTemplateObject) {
description, isolate->native_context());
}
RUNTIME_FUNCTION(Runtime_ReportMessage) {
// Helper to report messages and continue JS execution. This is intended to
// behave similarly to reporting exceptions which reach the top-level in
// Execution.cc, but allow the JS code to continue. This is useful for
// implementing algorithms such as RunMicrotasks in JS.
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, message_obj, 0);
DCHECK(!isolate->has_pending_exception());
isolate->set_pending_exception(*message_obj);
isolate->ReportPendingMessagesFromJavaScript();
isolate->clear_pending_exception();
return isolate->heap()->undefined_value();
}
} // namespace internal
} // namespace v8
......@@ -339,7 +339,8 @@ namespace internal {
F(Typeof, 1, 1) \
F(UnwindAndFindExceptionHandler, 0, 1) \
F(AllowDynamicFunction, 1, 1) \
F(GetTemplateObject, 1, 1)
F(GetTemplateObject, 1, 1) \
F(ReportMessage, 1, 1)
#define FOR_EACH_INTRINSIC_LITERALS(F) \
F(CreateRegExpLiteral, 4, 1) \
......
......@@ -523,12 +523,7 @@ void JSEntryStub::Generate(MacroAssembler* masm) {
// external reference instead of inlining the call target address directly
// in the code, because the builtin stubs may not have been generated yet
// at the time this code is generated.
if (type() == StackFrame::CONSTRUCT_ENTRY) {
__ Call(BUILTIN_CODE(isolate(), JSConstructEntryTrampoline),
RelocInfo::CODE_TARGET);
} else {
__ Call(BUILTIN_CODE(isolate(), JSEntryTrampoline), RelocInfo::CODE_TARGET);
}
__ Call(EntryTrampoline(), RelocInfo::CODE_TARGET);
// Unlink this frame from the handler chain.
__ PopStackHandler();
......
......@@ -43,7 +43,7 @@ Running test: testRejectedPromiseWithError
columnNumber : 11
exception : {
className : Error
description : Error: MyError at foo (<anonymous>:13:11) at throwError (<anonymous>:15:3) at <anonymous>
description : Error: MyError at foo (<anonymous>:13:11) at throwError (<anonymous>:15:3)
objectId : <objectId>
subtype : error
type : object
......@@ -58,14 +58,14 @@ Running test: testRejectedPromiseWithError
functionName : foo
lineNumber : 12
scriptId : <scriptId>
url :
url :
}
[1] : {
columnNumber : 2
functionName : throwError
lineNumber : 14
scriptId : <scriptId>
url :
url :
}
]
}
......@@ -73,7 +73,7 @@ Running test: testRejectedPromiseWithError
}
result : {
className : Error
description : Error: MyError at foo (<anonymous>:13:11) at throwError (<anonymous>:15:3) at <anonymous>
description : Error: MyError at foo (<anonymous>:13:11) at throwError (<anonymous>:15:3)
objectId : <objectId>
subtype : error
type : object
......@@ -89,7 +89,7 @@ Running test: testRejectedPromiseWithSyntaxError
columnNumber : 5
exception : {
className : SyntaxError
description : SyntaxError: Unexpected token } at foo (<anonymous>:21:5) at throwSyntaxError (<anonymous>:23:3) at <anonymous>
description : SyntaxError: Unexpected token } at foo (<anonymous>:21:5) at throwSyntaxError (<anonymous>:23:3)
objectId : <objectId>
subtype : error
type : object
......@@ -104,14 +104,14 @@ Running test: testRejectedPromiseWithSyntaxError
functionName : foo
lineNumber : 20
scriptId : <scriptId>
url :
url :
}
[1] : {
columnNumber : 2
functionName : throwSyntaxError
lineNumber : 22
scriptId : <scriptId>
url :
url :
}
]
}
......@@ -119,7 +119,7 @@ Running test: testRejectedPromiseWithSyntaxError
}
result : {
className : SyntaxError
description : SyntaxError: Unexpected token } at foo (<anonymous>:21:5) at throwSyntaxError (<anonymous>:23:3) at <anonymous>
description : SyntaxError: Unexpected token } at foo (<anonymous>:21:5) at throwSyntaxError (<anonymous>:23:3)
objectId : <objectId>
subtype : error
type : object
......
......@@ -86,7 +86,7 @@ let buffer = builder.toBuffer();
// Test async compilation and instantiation.
assertPromiseResult(WebAssembly.instantiate(buffer), pair => {
testTrapLocations(pair.instance, 6);
testTrapLocations(pair.instance, 5);
});
// Test sync compilation and instantiation.
......
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