deps: cherry-pick backports to V8
Included acb6779c19abf248a4c6d5c3d3389805e7ee8b8d 4e028bd34d25ddff4e3507f1c051426bb68ebd9a 75fe7739e6d3dc669435f9148a025ab39f507a21 c22bcd31f082747522dad355f987845cd7b9f5e8 49dec1afd8c310d6995a62893d59b171e2f021cc Not included (cannot be applied cleanly) 31450fce7c8fe6804c84a7875d2f85a78b309125 2b8a06b32347ac16eaac820227a4672dbe05c134 PR-URL: https://github.com/nodejs/node/pull/3351 Reviewed-By: indutny - Fedor Indutny <fedor.indutny@gmail.com> Reviewed-By: bnoordhuis - Ben Noordhuis <info@bnoordhuis.nl>
This commit is contained in:
parent
d8011d1683
commit
7fb128d8df
13
deps/v8/include/v8.h
vendored
13
deps/v8/include/v8.h
vendored
@ -5370,6 +5370,19 @@ class V8_EXPORT Isolate {
|
||||
*/
|
||||
static Isolate* GetCurrent();
|
||||
|
||||
/**
|
||||
* Custom callback used by embedders to help V8 determine if it should abort
|
||||
* when it throws and no internal handler is predicted to catch the
|
||||
* exception. If --abort-on-uncaught-exception is used on the command line,
|
||||
* then V8 will abort if either:
|
||||
* - no custom callback is set.
|
||||
* - the custom callback set returns true.
|
||||
* Otherwise, the custom callback will not be called and V8 will not abort.
|
||||
*/
|
||||
typedef bool (*AbortOnUncaughtExceptionCallback)(Isolate*);
|
||||
void SetAbortOnUncaughtExceptionCallback(
|
||||
AbortOnUncaughtExceptionCallback callback);
|
||||
|
||||
/**
|
||||
* Methods below this point require holding a lock (using Locker) in
|
||||
* a multi-threaded environment.
|
||||
|
41
deps/v8/src/accessors.cc
vendored
41
deps/v8/src/accessors.cc
vendored
@ -99,22 +99,37 @@ bool Accessors::IsJSArrayBufferViewFieldAccessor(Handle<Map> map,
|
||||
Isolate* isolate = name->GetIsolate();
|
||||
|
||||
switch (map->instance_type()) {
|
||||
case JS_TYPED_ARRAY_TYPE:
|
||||
// %TypedArray%.prototype is non-configurable, and so are the following
|
||||
// named properties on %TypedArray%.prototype, so we can directly inline
|
||||
// the field-load for typed array maps that still use their
|
||||
// %TypedArray%.prototype.
|
||||
if (JSFunction::cast(map->GetConstructor())->prototype() !=
|
||||
map->prototype()) {
|
||||
case JS_TYPED_ARRAY_TYPE: {
|
||||
if (!CheckForName(name, isolate->factory()->length_string(),
|
||||
JSTypedArray::kLengthOffset, object_offset) &&
|
||||
!CheckForName(name, isolate->factory()->byte_length_string(),
|
||||
JSTypedArray::kByteLengthOffset, object_offset) &&
|
||||
!CheckForName(name, isolate->factory()->byte_offset_string(),
|
||||
JSTypedArray::kByteOffsetOffset, object_offset)) {
|
||||
return false;
|
||||
}
|
||||
return CheckForName(name, isolate->factory()->length_string(),
|
||||
JSTypedArray::kLengthOffset, object_offset) ||
|
||||
CheckForName(name, isolate->factory()->byte_length_string(),
|
||||
JSTypedArray::kByteLengthOffset, object_offset) ||
|
||||
CheckForName(name, isolate->factory()->byte_offset_string(),
|
||||
JSTypedArray::kByteOffsetOffset, object_offset);
|
||||
|
||||
if (map->is_dictionary_map()) return false;
|
||||
|
||||
// Check if the property is overridden on the instance.
|
||||
DescriptorArray* descriptors = map->instance_descriptors();
|
||||
int descriptor = descriptors->SearchWithCache(*name, *map);
|
||||
if (descriptor != DescriptorArray::kNotFound) return false;
|
||||
|
||||
Handle<Object> proto = Handle<Object>(map->prototype(), isolate);
|
||||
if (!proto->IsJSReceiver()) return false;
|
||||
|
||||
// Check if the property is defined in the prototype chain.
|
||||
LookupIterator it(proto, name);
|
||||
if (!it.IsFound()) return false;
|
||||
|
||||
Object* original_proto =
|
||||
JSFunction::cast(map->GetConstructor())->prototype();
|
||||
|
||||
// Property is not configurable. It is enough to verify that
|
||||
// the holder is the same.
|
||||
return *it.GetHolder<Object>() == original_proto;
|
||||
}
|
||||
case JS_DATA_VIEW_TYPE:
|
||||
return CheckForName(name, isolate->factory()->byte_length_string(),
|
||||
JSDataView::kByteLengthOffset, object_offset) ||
|
||||
|
7
deps/v8/src/api.cc
vendored
7
deps/v8/src/api.cc
vendored
@ -7160,6 +7160,13 @@ void Isolate::Exit() {
|
||||
}
|
||||
|
||||
|
||||
void Isolate::SetAbortOnUncaughtExceptionCallback(
|
||||
AbortOnUncaughtExceptionCallback callback) {
|
||||
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
|
||||
isolate->SetAbortOnUncaughtExceptionCallback(callback);
|
||||
}
|
||||
|
||||
|
||||
Isolate::DisallowJavascriptExecutionScope::DisallowJavascriptExecutionScope(
|
||||
Isolate* isolate,
|
||||
Isolate::DisallowJavascriptExecutionScope::OnFailure on_failure)
|
||||
|
29
deps/v8/src/isolate.cc
vendored
29
deps/v8/src/isolate.cc
vendored
@ -1013,13 +1013,21 @@ Object* Isolate::Throw(Object* exception, MessageLocation* location) {
|
||||
Handle<Object> message_obj = CreateMessage(exception_handle, location);
|
||||
thread_local_top()->pending_message_obj_ = *message_obj;
|
||||
|
||||
// If the abort-on-uncaught-exception flag is specified, abort on any
|
||||
// exception not caught by JavaScript, even when an external handler is
|
||||
// present. This flag is intended for use by JavaScript developers, so
|
||||
// print a user-friendly stack trace (not an internal one).
|
||||
// For any exception not caught by JavaScript, even when an external
|
||||
// handler is present:
|
||||
// If the abort-on-uncaught-exception flag is specified, and if the
|
||||
// embedder didn't specify a custom uncaught exception callback,
|
||||
// or if the custom callback determined that V8 should abort, then
|
||||
// abort.
|
||||
if (FLAG_abort_on_uncaught_exception &&
|
||||
PredictExceptionCatcher() != CAUGHT_BY_JAVASCRIPT) {
|
||||
FLAG_abort_on_uncaught_exception = false; // Prevent endless recursion.
|
||||
PredictExceptionCatcher() != CAUGHT_BY_JAVASCRIPT &&
|
||||
(!abort_on_uncaught_exception_callback_ ||
|
||||
abort_on_uncaught_exception_callback_(
|
||||
reinterpret_cast<v8::Isolate*>(this)))) {
|
||||
// Prevent endless recursion.
|
||||
FLAG_abort_on_uncaught_exception = false;
|
||||
// This flag is intended for use by JavaScript developers, so
|
||||
// print a user-friendly stack trace (not an internal one).
|
||||
PrintF(stderr, "%s\n\nFROM\n",
|
||||
MessageHandler::GetLocalizedMessage(this, message_obj).get());
|
||||
PrintCurrentStackTrace(stderr);
|
||||
@ -1607,6 +1615,12 @@ void Isolate::SetCaptureStackTraceForUncaughtExceptions(
|
||||
}
|
||||
|
||||
|
||||
void Isolate::SetAbortOnUncaughtExceptionCallback(
|
||||
v8::Isolate::AbortOnUncaughtExceptionCallback callback) {
|
||||
abort_on_uncaught_exception_callback_ = callback;
|
||||
}
|
||||
|
||||
|
||||
Handle<Context> Isolate::native_context() {
|
||||
return handle(context()->native_context());
|
||||
}
|
||||
@ -1774,7 +1788,8 @@ Isolate::Isolate(bool enable_serializer)
|
||||
next_unique_sfi_id_(0),
|
||||
#endif
|
||||
use_counter_callback_(NULL),
|
||||
basic_block_profiler_(NULL) {
|
||||
basic_block_profiler_(NULL),
|
||||
abort_on_uncaught_exception_callback_(NULL) {
|
||||
{
|
||||
base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer());
|
||||
CHECK(thread_data_table_);
|
||||
|
6
deps/v8/src/isolate.h
vendored
6
deps/v8/src/isolate.h
vendored
@ -698,6 +698,9 @@ class Isolate {
|
||||
int frame_limit,
|
||||
StackTrace::StackTraceOptions options);
|
||||
|
||||
void SetAbortOnUncaughtExceptionCallback(
|
||||
v8::Isolate::AbortOnUncaughtExceptionCallback callback);
|
||||
|
||||
enum PrintStackMode { kPrintStackConcise, kPrintStackVerbose };
|
||||
void PrintCurrentStackTrace(FILE* out);
|
||||
void PrintStack(StringStream* accumulator,
|
||||
@ -1366,6 +1369,9 @@ class Isolate {
|
||||
|
||||
std::set<Cancelable*> cancelable_tasks_;
|
||||
|
||||
v8::Isolate::AbortOnUncaughtExceptionCallback
|
||||
abort_on_uncaught_exception_callback_;
|
||||
|
||||
friend class ExecutionAccess;
|
||||
friend class HandleScopeImplementer;
|
||||
friend class OptimizingCompileDispatcher;
|
||||
|
2
deps/v8/src/objects.h
vendored
2
deps/v8/src/objects.h
vendored
@ -3932,7 +3932,6 @@ class ScopeInfo : public FixedArray {
|
||||
FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(FIELD_ACCESSORS)
|
||||
#undef FIELD_ACCESSORS
|
||||
|
||||
private:
|
||||
enum {
|
||||
#define DECL_INDEX(name) k##name,
|
||||
FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(DECL_INDEX)
|
||||
@ -3940,6 +3939,7 @@ class ScopeInfo : public FixedArray {
|
||||
kVariablePartIndex
|
||||
};
|
||||
|
||||
private:
|
||||
// The layout of the variable part of a ScopeInfo is as follows:
|
||||
// 1. ParameterEntries:
|
||||
// This part stores the names of the parameters for function scopes. One
|
||||
|
30
deps/v8/test/cctest/test-api.cc
vendored
30
deps/v8/test/cctest/test-api.cc
vendored
@ -21826,4 +21826,34 @@ TEST(EstimatedContextSize) {
|
||||
v8::HandleScope scope(isolate);
|
||||
LocalContext env;
|
||||
CHECK(50000 < env->EstimatedSize());
|
||||
|
||||
|
||||
static int nb_uncaught_exception_callback_calls = 0;
|
||||
|
||||
|
||||
bool NoAbortOnUncaughtException(v8::Isolate* isolate) {
|
||||
++nb_uncaught_exception_callback_calls;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
TEST(AbortOnUncaughtExceptionNoAbort) {
|
||||
v8::Isolate* isolate = CcTest::isolate();
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
v8::Handle<v8::ObjectTemplate> global_template =
|
||||
v8::ObjectTemplate::New(isolate);
|
||||
LocalContext env(NULL, global_template);
|
||||
|
||||
i::FLAG_abort_on_uncaught_exception = true;
|
||||
isolate->SetAbortOnUncaughtExceptionCallback(NoAbortOnUncaughtException);
|
||||
|
||||
CompileRun("function boom() { throw new Error(\"boom\") }");
|
||||
|
||||
v8::Local<v8::Object> global_object = env->Global();
|
||||
v8::Local<v8::Function> foo =
|
||||
v8::Local<v8::Function>::Cast(global_object->Get(v8_str("boom")));
|
||||
|
||||
foo->Call(global_object, 0, NULL);
|
||||
|
||||
CHECK_EQ(1, nb_uncaught_exception_callback_calls);
|
||||
}
|
||||
|
@ -71,6 +71,43 @@ assertEquals(undefined, get(a));
|
||||
assertEquals(undefined, get(a));
|
||||
})();
|
||||
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
class MyTypedArray extends Int32Array {
|
||||
constructor(length) {
|
||||
super(length);
|
||||
}
|
||||
}
|
||||
|
||||
a = new MyTypedArray(1024);
|
||||
|
||||
get = function(a) {
|
||||
return a.length;
|
||||
}
|
||||
|
||||
assertEquals(1024, get(a));
|
||||
assertEquals(1024, get(a));
|
||||
assertEquals(1024, get(a));
|
||||
%OptimizeFunctionOnNextCall(get);
|
||||
assertEquals(1024, get(a));
|
||||
})();
|
||||
|
||||
(function() {
|
||||
"use strict";
|
||||
var a = new Uint8Array(4);
|
||||
Object.defineProperty(a, "length", {get: function() { return "blah"; }});
|
||||
get = function(a) {
|
||||
return a.length;
|
||||
}
|
||||
|
||||
assertEquals("blah", get(a));
|
||||
assertEquals("blah", get(a));
|
||||
assertEquals("blah", get(a));
|
||||
%OptimizeFunctionOnNextCall(get);
|
||||
assertEquals("blah", get(a));
|
||||
})();
|
||||
|
||||
// Ensure we cannot delete length, byteOffset, byteLength.
|
||||
assertTrue(Int32Array.prototype.hasOwnProperty("length"));
|
||||
assertTrue(Int32Array.prototype.hasOwnProperty("byteOffset"));
|
||||
|
12
deps/v8/tools/gen-postmortem-metadata.py
vendored
12
deps/v8/tools/gen-postmortem-metadata.py
vendored
@ -132,6 +132,15 @@ consts_misc = [
|
||||
'value': 'JavaScriptFrameConstants::kFunctionOffset' },
|
||||
{ 'name': 'off_fp_args',
|
||||
'value': 'JavaScriptFrameConstants::kLastParameterOffset' },
|
||||
|
||||
{ 'name': 'scopeinfo_idx_nparams',
|
||||
'value': 'ScopeInfo::kParameterCount' },
|
||||
{ 'name': 'scopeinfo_idx_nstacklocals',
|
||||
'value': 'ScopeInfo::kStackLocalCount' },
|
||||
{ 'name': 'scopeinfo_idx_ncontextlocals',
|
||||
'value': 'ScopeInfo::kContextLocalCount' },
|
||||
{ 'name': 'scopeinfo_idx_first_vars',
|
||||
'value': 'ScopeInfo::kVariablePartIndex' },
|
||||
];
|
||||
|
||||
#
|
||||
@ -141,12 +150,13 @@ extras_accessors = [
|
||||
'HeapObject, map, Map, kMapOffset',
|
||||
'JSObject, elements, Object, kElementsOffset',
|
||||
'FixedArray, data, uintptr_t, kHeaderSize',
|
||||
'JSTypedArray, length, Object, kLengthOffset',
|
||||
'Map, instance_attributes, int, kInstanceAttributesOffset',
|
||||
'Map, inobject_properties_of_constructor_function_index_offset, int, kInObjectPropertiesOrConstructorFunctionIndexOffset',
|
||||
'Map, instance_size, int, kInstanceSizeOffset',
|
||||
'Map, bit_field, char, kBitFieldOffset',
|
||||
'Map, bit_field2, char, kBitField2Offset',
|
||||
'Map, bit_field3, SMI, kBitField3Offset',
|
||||
'Map, bit_field3, int, kBitField3Offset',
|
||||
'Map, prototype, Object, kPrototypeOffset',
|
||||
'NameDictionaryShape, prefix_size, int, kPrefixSize',
|
||||
'NameDictionaryShape, entry_size, int, kEntrySize',
|
||||
|
Loading…
x
Reference in New Issue
Block a user