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();
|
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
|
* Methods below this point require holding a lock (using Locker) in
|
||||||
* a multi-threaded environment.
|
* 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();
|
Isolate* isolate = name->GetIsolate();
|
||||||
|
|
||||||
switch (map->instance_type()) {
|
switch (map->instance_type()) {
|
||||||
case JS_TYPED_ARRAY_TYPE:
|
case JS_TYPED_ARRAY_TYPE: {
|
||||||
// %TypedArray%.prototype is non-configurable, and so are the following
|
if (!CheckForName(name, isolate->factory()->length_string(),
|
||||||
// named properties on %TypedArray%.prototype, so we can directly inline
|
JSTypedArray::kLengthOffset, object_offset) &&
|
||||||
// the field-load for typed array maps that still use their
|
!CheckForName(name, isolate->factory()->byte_length_string(),
|
||||||
// %TypedArray%.prototype.
|
JSTypedArray::kByteLengthOffset, object_offset) &&
|
||||||
if (JSFunction::cast(map->GetConstructor())->prototype() !=
|
!CheckForName(name, isolate->factory()->byte_offset_string(),
|
||||||
map->prototype()) {
|
JSTypedArray::kByteOffsetOffset, object_offset)) {
|
||||||
return false;
|
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:
|
case JS_DATA_VIEW_TYPE:
|
||||||
return CheckForName(name, isolate->factory()->byte_length_string(),
|
return CheckForName(name, isolate->factory()->byte_length_string(),
|
||||||
JSDataView::kByteLengthOffset, object_offset) ||
|
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::DisallowJavascriptExecutionScope::DisallowJavascriptExecutionScope(
|
||||||
Isolate* isolate,
|
Isolate* isolate,
|
||||||
Isolate::DisallowJavascriptExecutionScope::OnFailure on_failure)
|
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);
|
Handle<Object> message_obj = CreateMessage(exception_handle, location);
|
||||||
thread_local_top()->pending_message_obj_ = *message_obj;
|
thread_local_top()->pending_message_obj_ = *message_obj;
|
||||||
|
|
||||||
// If the abort-on-uncaught-exception flag is specified, abort on any
|
// For any exception not caught by JavaScript, even when an external
|
||||||
// exception not caught by JavaScript, even when an external handler is
|
// handler is present:
|
||||||
// present. This flag is intended for use by JavaScript developers, so
|
// If the abort-on-uncaught-exception flag is specified, and if the
|
||||||
// print a user-friendly stack trace (not an internal one).
|
// 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 &&
|
if (FLAG_abort_on_uncaught_exception &&
|
||||||
PredictExceptionCatcher() != CAUGHT_BY_JAVASCRIPT) {
|
PredictExceptionCatcher() != CAUGHT_BY_JAVASCRIPT &&
|
||||||
FLAG_abort_on_uncaught_exception = false; // Prevent endless recursion.
|
(!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",
|
PrintF(stderr, "%s\n\nFROM\n",
|
||||||
MessageHandler::GetLocalizedMessage(this, message_obj).get());
|
MessageHandler::GetLocalizedMessage(this, message_obj).get());
|
||||||
PrintCurrentStackTrace(stderr);
|
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() {
|
Handle<Context> Isolate::native_context() {
|
||||||
return handle(context()->native_context());
|
return handle(context()->native_context());
|
||||||
}
|
}
|
||||||
@ -1774,7 +1788,8 @@ Isolate::Isolate(bool enable_serializer)
|
|||||||
next_unique_sfi_id_(0),
|
next_unique_sfi_id_(0),
|
||||||
#endif
|
#endif
|
||||||
use_counter_callback_(NULL),
|
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());
|
base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer());
|
||||||
CHECK(thread_data_table_);
|
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,
|
int frame_limit,
|
||||||
StackTrace::StackTraceOptions options);
|
StackTrace::StackTraceOptions options);
|
||||||
|
|
||||||
|
void SetAbortOnUncaughtExceptionCallback(
|
||||||
|
v8::Isolate::AbortOnUncaughtExceptionCallback callback);
|
||||||
|
|
||||||
enum PrintStackMode { kPrintStackConcise, kPrintStackVerbose };
|
enum PrintStackMode { kPrintStackConcise, kPrintStackVerbose };
|
||||||
void PrintCurrentStackTrace(FILE* out);
|
void PrintCurrentStackTrace(FILE* out);
|
||||||
void PrintStack(StringStream* accumulator,
|
void PrintStack(StringStream* accumulator,
|
||||||
@ -1366,6 +1369,9 @@ class Isolate {
|
|||||||
|
|
||||||
std::set<Cancelable*> cancelable_tasks_;
|
std::set<Cancelable*> cancelable_tasks_;
|
||||||
|
|
||||||
|
v8::Isolate::AbortOnUncaughtExceptionCallback
|
||||||
|
abort_on_uncaught_exception_callback_;
|
||||||
|
|
||||||
friend class ExecutionAccess;
|
friend class ExecutionAccess;
|
||||||
friend class HandleScopeImplementer;
|
friend class HandleScopeImplementer;
|
||||||
friend class OptimizingCompileDispatcher;
|
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)
|
FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(FIELD_ACCESSORS)
|
||||||
#undef FIELD_ACCESSORS
|
#undef FIELD_ACCESSORS
|
||||||
|
|
||||||
private:
|
|
||||||
enum {
|
enum {
|
||||||
#define DECL_INDEX(name) k##name,
|
#define DECL_INDEX(name) k##name,
|
||||||
FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(DECL_INDEX)
|
FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(DECL_INDEX)
|
||||||
@ -3940,6 +3939,7 @@ class ScopeInfo : public FixedArray {
|
|||||||
kVariablePartIndex
|
kVariablePartIndex
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
// The layout of the variable part of a ScopeInfo is as follows:
|
// The layout of the variable part of a ScopeInfo is as follows:
|
||||||
// 1. ParameterEntries:
|
// 1. ParameterEntries:
|
||||||
// This part stores the names of the parameters for function scopes. One
|
// 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);
|
v8::HandleScope scope(isolate);
|
||||||
LocalContext env;
|
LocalContext env;
|
||||||
CHECK(50000 < env->EstimatedSize());
|
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));
|
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.
|
// Ensure we cannot delete length, byteOffset, byteLength.
|
||||||
assertTrue(Int32Array.prototype.hasOwnProperty("length"));
|
assertTrue(Int32Array.prototype.hasOwnProperty("length"));
|
||||||
assertTrue(Int32Array.prototype.hasOwnProperty("byteOffset"));
|
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' },
|
'value': 'JavaScriptFrameConstants::kFunctionOffset' },
|
||||||
{ 'name': 'off_fp_args',
|
{ 'name': 'off_fp_args',
|
||||||
'value': 'JavaScriptFrameConstants::kLastParameterOffset' },
|
'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',
|
'HeapObject, map, Map, kMapOffset',
|
||||||
'JSObject, elements, Object, kElementsOffset',
|
'JSObject, elements, Object, kElementsOffset',
|
||||||
'FixedArray, data, uintptr_t, kHeaderSize',
|
'FixedArray, data, uintptr_t, kHeaderSize',
|
||||||
|
'JSTypedArray, length, Object, kLengthOffset',
|
||||||
'Map, instance_attributes, int, kInstanceAttributesOffset',
|
'Map, instance_attributes, int, kInstanceAttributesOffset',
|
||||||
'Map, inobject_properties_of_constructor_function_index_offset, int, kInObjectPropertiesOrConstructorFunctionIndexOffset',
|
'Map, inobject_properties_of_constructor_function_index_offset, int, kInObjectPropertiesOrConstructorFunctionIndexOffset',
|
||||||
'Map, instance_size, int, kInstanceSizeOffset',
|
'Map, instance_size, int, kInstanceSizeOffset',
|
||||||
'Map, bit_field, char, kBitFieldOffset',
|
'Map, bit_field, char, kBitFieldOffset',
|
||||||
'Map, bit_field2, char, kBitField2Offset',
|
'Map, bit_field2, char, kBitField2Offset',
|
||||||
'Map, bit_field3, SMI, kBitField3Offset',
|
'Map, bit_field3, int, kBitField3Offset',
|
||||||
'Map, prototype, Object, kPrototypeOffset',
|
'Map, prototype, Object, kPrototypeOffset',
|
||||||
'NameDictionaryShape, prefix_size, int, kPrefixSize',
|
'NameDictionaryShape, prefix_size, int, kPrefixSize',
|
||||||
'NameDictionaryShape, entry_size, int, kEntrySize',
|
'NameDictionaryShape, entry_size, int, kEntrySize',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user