deps: upgrade v8 to 4.1.0.21
PR-URL: https://github.com/iojs/io.js/pull/952 Reviewed-By: Fedor Indutny <fedor@indutny.com> Reviewed-By: Rod Vagg <rod@vagg.org>
This commit is contained in:
Родитель
739fda16a9
Коммит
78f4837926
|
@ -3899,6 +3899,9 @@ class V8_EXPORT FunctionTemplate : public Template {
|
|||
};
|
||||
|
||||
|
||||
enum class PropertyHandlerFlags { kNone = 0, kAllCanRead = 1 };
|
||||
|
||||
|
||||
struct NamedPropertyHandlerConfiguration {
|
||||
NamedPropertyHandlerConfiguration(
|
||||
/** Note: getter is required **/
|
||||
|
@ -3907,13 +3910,15 @@ struct NamedPropertyHandlerConfiguration {
|
|||
GenericNamedPropertyQueryCallback query = 0,
|
||||
GenericNamedPropertyDeleterCallback deleter = 0,
|
||||
GenericNamedPropertyEnumeratorCallback enumerator = 0,
|
||||
Handle<Value> data = Handle<Value>())
|
||||
Handle<Value> data = Handle<Value>(),
|
||||
PropertyHandlerFlags flags = PropertyHandlerFlags::kNone)
|
||||
: getter(getter),
|
||||
setter(setter),
|
||||
query(query),
|
||||
deleter(deleter),
|
||||
enumerator(enumerator),
|
||||
data(data) {}
|
||||
data(data),
|
||||
flags(flags) {}
|
||||
|
||||
GenericNamedPropertyGetterCallback getter;
|
||||
GenericNamedPropertySetterCallback setter;
|
||||
|
@ -3921,6 +3926,7 @@ struct NamedPropertyHandlerConfiguration {
|
|||
GenericNamedPropertyDeleterCallback deleter;
|
||||
GenericNamedPropertyEnumeratorCallback enumerator;
|
||||
Handle<Value> data;
|
||||
PropertyHandlerFlags flags;
|
||||
};
|
||||
|
||||
|
||||
|
@ -3932,13 +3938,15 @@ struct IndexedPropertyHandlerConfiguration {
|
|||
IndexedPropertyQueryCallback query = 0,
|
||||
IndexedPropertyDeleterCallback deleter = 0,
|
||||
IndexedPropertyEnumeratorCallback enumerator = 0,
|
||||
Handle<Value> data = Handle<Value>())
|
||||
Handle<Value> data = Handle<Value>(),
|
||||
PropertyHandlerFlags flags = PropertyHandlerFlags::kNone)
|
||||
: getter(getter),
|
||||
setter(setter),
|
||||
query(query),
|
||||
deleter(deleter),
|
||||
enumerator(enumerator),
|
||||
data(data) {}
|
||||
data(data),
|
||||
flags(flags) {}
|
||||
|
||||
IndexedPropertyGetterCallback getter;
|
||||
IndexedPropertySetterCallback setter;
|
||||
|
@ -3946,6 +3954,7 @@ struct IndexedPropertyHandlerConfiguration {
|
|||
IndexedPropertyDeleterCallback deleter;
|
||||
IndexedPropertyEnumeratorCallback enumerator;
|
||||
Handle<Value> data;
|
||||
PropertyHandlerFlags flags;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1306,12 +1306,10 @@ void ObjectTemplate::SetAccessor(v8::Handle<Name> name,
|
|||
|
||||
template <typename Getter, typename Setter, typename Query, typename Deleter,
|
||||
typename Enumerator>
|
||||
static void ObjectTemplateSetNamedPropertyHandler(ObjectTemplate* templ,
|
||||
Getter getter, Setter setter,
|
||||
Query query, Deleter remover,
|
||||
Enumerator enumerator,
|
||||
Handle<Value> data,
|
||||
bool can_intercept_symbols) {
|
||||
static void ObjectTemplateSetNamedPropertyHandler(
|
||||
ObjectTemplate* templ, Getter getter, Setter setter, Query query,
|
||||
Deleter remover, Enumerator enumerator, Handle<Value> data,
|
||||
bool can_intercept_symbols, PropertyHandlerFlags flags) {
|
||||
i::Isolate* isolate = Utils::OpenHandle(templ)->GetIsolate();
|
||||
ENTER_V8(isolate);
|
||||
i::HandleScope scope(isolate);
|
||||
|
@ -1319,10 +1317,8 @@ static void ObjectTemplateSetNamedPropertyHandler(ObjectTemplate* templ,
|
|||
i::FunctionTemplateInfo* constructor =
|
||||
i::FunctionTemplateInfo::cast(Utils::OpenHandle(templ)->constructor());
|
||||
i::Handle<i::FunctionTemplateInfo> cons(constructor);
|
||||
i::Handle<i::Struct> struct_obj =
|
||||
isolate->factory()->NewStruct(i::INTERCEPTOR_INFO_TYPE);
|
||||
i::Handle<i::InterceptorInfo> obj =
|
||||
i::Handle<i::InterceptorInfo>::cast(struct_obj);
|
||||
auto obj = i::Handle<i::InterceptorInfo>::cast(
|
||||
isolate->factory()->NewStruct(i::INTERCEPTOR_INFO_TYPE));
|
||||
|
||||
if (getter != 0) SET_FIELD_WRAPPED(obj, set_getter, getter);
|
||||
if (setter != 0) SET_FIELD_WRAPPED(obj, set_setter, setter);
|
||||
|
@ -1331,6 +1327,8 @@ static void ObjectTemplateSetNamedPropertyHandler(ObjectTemplate* templ,
|
|||
if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator);
|
||||
obj->set_flags(0);
|
||||
obj->set_can_intercept_symbols(can_intercept_symbols);
|
||||
obj->set_all_can_read(static_cast<int>(flags) &
|
||||
static_cast<int>(PropertyHandlerFlags::kAllCanRead));
|
||||
|
||||
if (data.IsEmpty()) {
|
||||
data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
|
||||
|
@ -1345,15 +1343,16 @@ void ObjectTemplate::SetNamedPropertyHandler(
|
|||
NamedPropertyQueryCallback query, NamedPropertyDeleterCallback remover,
|
||||
NamedPropertyEnumeratorCallback enumerator, Handle<Value> data) {
|
||||
ObjectTemplateSetNamedPropertyHandler(this, getter, setter, query, remover,
|
||||
enumerator, data, false);
|
||||
enumerator, data, false,
|
||||
PropertyHandlerFlags::kNone);
|
||||
}
|
||||
|
||||
|
||||
void ObjectTemplate::SetHandler(
|
||||
const NamedPropertyHandlerConfiguration& config) {
|
||||
ObjectTemplateSetNamedPropertyHandler(this, config.getter, config.setter,
|
||||
config.query, config.deleter,
|
||||
config.enumerator, config.data, true);
|
||||
ObjectTemplateSetNamedPropertyHandler(
|
||||
this, config.getter, config.setter, config.query, config.deleter,
|
||||
config.enumerator, config.data, true, config.flags);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1409,10 +1408,8 @@ void ObjectTemplate::SetHandler(
|
|||
i::FunctionTemplateInfo* constructor = i::FunctionTemplateInfo::cast(
|
||||
Utils::OpenHandle(this)->constructor());
|
||||
i::Handle<i::FunctionTemplateInfo> cons(constructor);
|
||||
i::Handle<i::Struct> struct_obj =
|
||||
isolate->factory()->NewStruct(i::INTERCEPTOR_INFO_TYPE);
|
||||
i::Handle<i::InterceptorInfo> obj =
|
||||
i::Handle<i::InterceptorInfo>::cast(struct_obj);
|
||||
auto obj = i::Handle<i::InterceptorInfo>::cast(
|
||||
isolate->factory()->NewStruct(i::INTERCEPTOR_INFO_TYPE));
|
||||
|
||||
if (config.getter != 0) SET_FIELD_WRAPPED(obj, set_getter, config.getter);
|
||||
if (config.setter != 0) SET_FIELD_WRAPPED(obj, set_setter, config.setter);
|
||||
|
@ -1422,6 +1419,8 @@ void ObjectTemplate::SetHandler(
|
|||
SET_FIELD_WRAPPED(obj, set_enumerator, config.enumerator);
|
||||
}
|
||||
obj->set_flags(0);
|
||||
obj->set_all_can_read(static_cast<int>(config.flags) &
|
||||
static_cast<int>(PropertyHandlerFlags::kAllCanRead));
|
||||
|
||||
v8::Local<v8::Value> data = config.data;
|
||||
if (data.IsEmpty()) {
|
||||
|
|
|
@ -556,6 +556,7 @@ uint32_t FlagList::Hash() {
|
|||
for (size_t i = 0; i < num_flags; ++i) {
|
||||
Flag* current = &flags[i];
|
||||
if (!current->IsDefault()) {
|
||||
modified_args_as_string << i;
|
||||
modified_args_as_string << *current;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,7 +97,7 @@ function SetUpGenerators() {
|
|||
%AddNamedProperty(GeneratorObjectPrototype, symbolIterator,
|
||||
GeneratorObjectIterator, DONT_ENUM | DONT_DELETE | READ_ONLY);
|
||||
%AddNamedProperty(GeneratorObjectPrototype, "constructor",
|
||||
GeneratorFunctionPrototype, DONT_ENUM | DONT_DELETE | READ_ONLY);
|
||||
GeneratorFunctionPrototype, DONT_ENUM | READ_ONLY);
|
||||
%AddNamedProperty(GeneratorObjectPrototype,
|
||||
symbolToStringTag, "Generator", DONT_ENUM | READ_ONLY);
|
||||
%InternalSetPrototype(GeneratorFunctionPrototype, $Function.prototype);
|
||||
|
@ -105,7 +105,7 @@ function SetUpGenerators() {
|
|||
symbolToStringTag, "GeneratorFunction", DONT_ENUM | READ_ONLY);
|
||||
%SetCode(GeneratorFunctionPrototype, GeneratorFunctionPrototypeConstructor);
|
||||
%AddNamedProperty(GeneratorFunctionPrototype, "constructor",
|
||||
GeneratorFunction, DONT_ENUM | DONT_DELETE | READ_ONLY);
|
||||
GeneratorFunction, DONT_ENUM | READ_ONLY);
|
||||
%InternalSetPrototype(GeneratorFunction, $Function);
|
||||
%SetCode(GeneratorFunction, GeneratorFunctionConstructor);
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@ namespace internal {
|
|||
|
||||
// Determine whether double field unboxing feature is enabled.
|
||||
#if (V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64)
|
||||
#define V8_DOUBLE_FIELDS_UNBOXING 1
|
||||
#define V8_DOUBLE_FIELDS_UNBOXING 0
|
||||
#else
|
||||
#define V8_DOUBLE_FIELDS_UNBOXING 0
|
||||
#endif
|
||||
|
|
|
@ -3052,6 +3052,11 @@ void MarkCompactCollector::EvacuatePages() {
|
|||
// have an emergency page and the space still has room for that.
|
||||
if (space->HasEmergencyMemory() && space->CanExpand()) {
|
||||
EvacuateLiveObjectsFromPage(p);
|
||||
// Unlink the page from the list of pages here. We must not iterate
|
||||
// over that page later (e.g. when scan on scavenge pages are
|
||||
// processed). The page itself will be freed later and is still
|
||||
// reachable from the evacuation candidates list.
|
||||
p->Unlink();
|
||||
} else {
|
||||
// Without room for expansion evacuation is not guaranteed to succeed.
|
||||
// Pessimistically abandon unevacuated pages.
|
||||
|
|
|
@ -1142,7 +1142,12 @@ void PagedSpace::ReleasePage(Page* page) {
|
|||
allocation_info_.set_limit(NULL);
|
||||
}
|
||||
|
||||
page->Unlink();
|
||||
// If page is still in a list, unlink it from that list.
|
||||
if (page->next_chunk() != NULL) {
|
||||
DCHECK(page->prev_chunk() != NULL);
|
||||
page->Unlink();
|
||||
}
|
||||
|
||||
if (page->IsFlagSet(MemoryChunk::CONTAINS_ONLY_DATA)) {
|
||||
heap()->isolate()->memory_allocator()->Free(page);
|
||||
} else {
|
||||
|
|
|
@ -2924,7 +2924,7 @@ RUNTIME_FUNCTION(LoadElementWithInterceptor) {
|
|||
Handle<Object> result;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
||||
isolate, result,
|
||||
JSObject::GetElementWithInterceptor(receiver, receiver, index));
|
||||
JSObject::GetElementWithInterceptor(receiver, receiver, index, true));
|
||||
return *result;
|
||||
}
|
||||
|
||||
|
|
|
@ -5517,6 +5517,7 @@ ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
|
|||
SMI_ACCESSORS(InterceptorInfo, flags, kFlagsOffset)
|
||||
BOOL_ACCESSORS(InterceptorInfo, flags, can_intercept_symbols,
|
||||
kCanInterceptSymbolsBit)
|
||||
BOOL_ACCESSORS(InterceptorInfo, flags, all_can_read, kAllCanReadBit)
|
||||
|
||||
ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
|
||||
ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
|
||||
|
|
|
@ -572,12 +572,19 @@ MaybeHandle<Object> Object::SetPropertyWithDefinedSetter(
|
|||
|
||||
|
||||
static bool FindAllCanReadHolder(LookupIterator* it) {
|
||||
for (; it->IsFound(); it->Next()) {
|
||||
// Skip current iteration, it's in state ACCESS_CHECK or INTERCEPTOR, both of
|
||||
// which have already been checked.
|
||||
DCHECK(it->state() == LookupIterator::ACCESS_CHECK ||
|
||||
it->state() == LookupIterator::INTERCEPTOR);
|
||||
for (it->Next(); it->IsFound(); it->Next()) {
|
||||
if (it->state() == LookupIterator::ACCESSOR) {
|
||||
Handle<Object> accessors = it->GetAccessors();
|
||||
auto accessors = it->GetAccessors();
|
||||
if (accessors->IsAccessorInfo()) {
|
||||
if (AccessorInfo::cast(*accessors)->all_can_read()) return true;
|
||||
}
|
||||
} else if (it->state() == LookupIterator::INTERCEPTOR) {
|
||||
auto holder = it->GetHolder<JSObject>();
|
||||
if (holder->GetNamedInterceptor()->all_can_read()) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -587,10 +594,18 @@ static bool FindAllCanReadHolder(LookupIterator* it) {
|
|||
MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck(
|
||||
LookupIterator* it) {
|
||||
Handle<JSObject> checked = it->GetHolder<JSObject>();
|
||||
if (FindAllCanReadHolder(it)) {
|
||||
return GetPropertyWithAccessor(it->GetReceiver(), it->name(),
|
||||
it->GetHolder<JSObject>(),
|
||||
it->GetAccessors());
|
||||
while (FindAllCanReadHolder(it)) {
|
||||
if (it->state() == LookupIterator::ACCESSOR) {
|
||||
return GetPropertyWithAccessor(it->GetReceiver(), it->name(),
|
||||
it->GetHolder<JSObject>(),
|
||||
it->GetAccessors());
|
||||
}
|
||||
DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
|
||||
auto receiver = Handle<JSObject>::cast(it->GetReceiver());
|
||||
auto result = GetPropertyWithInterceptor(it->GetHolder<JSObject>(),
|
||||
receiver, it->name());
|
||||
if (it->isolate()->has_scheduled_exception()) break;
|
||||
if (!result.is_null()) return result;
|
||||
}
|
||||
it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_GET);
|
||||
RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
|
||||
|
@ -601,8 +616,16 @@ MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck(
|
|||
Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithFailedAccessCheck(
|
||||
LookupIterator* it) {
|
||||
Handle<JSObject> checked = it->GetHolder<JSObject>();
|
||||
if (FindAllCanReadHolder(it))
|
||||
return maybe(it->property_details().attributes());
|
||||
while (FindAllCanReadHolder(it)) {
|
||||
if (it->state() == LookupIterator::ACCESSOR) {
|
||||
return maybe(it->property_details().attributes());
|
||||
}
|
||||
DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
|
||||
auto result = GetPropertyAttributesWithInterceptor(
|
||||
it->GetHolder<JSObject>(), it->GetReceiver(), it->name());
|
||||
if (it->isolate()->has_scheduled_exception()) break;
|
||||
if (result.has_value && result.value != ABSENT) return result;
|
||||
}
|
||||
it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_HAS);
|
||||
RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(),
|
||||
Maybe<PropertyAttributes>());
|
||||
|
@ -736,6 +759,65 @@ Handle<Object> JSObject::DeleteNormalizedProperty(Handle<JSObject> object,
|
|||
}
|
||||
|
||||
|
||||
static MaybeHandle<JSObject> FindIndexedAllCanReadHolder(
|
||||
Isolate* isolate, Handle<JSObject> js_object,
|
||||
PrototypeIterator::WhereToStart where_to_start) {
|
||||
for (PrototypeIterator iter(isolate, js_object, where_to_start);
|
||||
!iter.IsAtEnd(); iter.Advance()) {
|
||||
auto curr = PrototypeIterator::GetCurrent(iter);
|
||||
if (!curr->IsJSObject()) break;
|
||||
auto obj = Handle<JSObject>::cast(curr);
|
||||
if (!obj->HasIndexedInterceptor()) continue;
|
||||
if (obj->GetIndexedInterceptor()->all_can_read()) return obj;
|
||||
}
|
||||
return MaybeHandle<JSObject>();
|
||||
}
|
||||
|
||||
|
||||
MaybeHandle<Object> JSObject::GetElementWithFailedAccessCheck(
|
||||
Isolate* isolate, Handle<JSObject> object, Handle<Object> receiver,
|
||||
uint32_t index) {
|
||||
Handle<JSObject> holder = object;
|
||||
PrototypeIterator::WhereToStart where_to_start =
|
||||
PrototypeIterator::START_AT_RECEIVER;
|
||||
while (true) {
|
||||
auto all_can_read_holder =
|
||||
FindIndexedAllCanReadHolder(isolate, holder, where_to_start);
|
||||
if (!all_can_read_holder.ToHandle(&holder)) break;
|
||||
auto result =
|
||||
JSObject::GetElementWithInterceptor(holder, receiver, index, false);
|
||||
if (isolate->has_scheduled_exception()) break;
|
||||
if (!result.is_null()) return result;
|
||||
where_to_start = PrototypeIterator::START_AT_PROTOTYPE;
|
||||
}
|
||||
isolate->ReportFailedAccessCheck(object, v8::ACCESS_GET);
|
||||
RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
||||
return isolate->factory()->undefined_value();
|
||||
}
|
||||
|
||||
|
||||
Maybe<PropertyAttributes> JSObject::GetElementAttributesWithFailedAccessCheck(
|
||||
Isolate* isolate, Handle<JSObject> object, Handle<Object> receiver,
|
||||
uint32_t index) {
|
||||
Handle<JSObject> holder = object;
|
||||
PrototypeIterator::WhereToStart where_to_start =
|
||||
PrototypeIterator::START_AT_RECEIVER;
|
||||
while (true) {
|
||||
auto all_can_read_holder =
|
||||
FindIndexedAllCanReadHolder(isolate, holder, where_to_start);
|
||||
if (!all_can_read_holder.ToHandle(&holder)) break;
|
||||
auto result =
|
||||
JSObject::GetElementAttributeFromInterceptor(object, receiver, index);
|
||||
if (isolate->has_scheduled_exception()) break;
|
||||
if (result.has_value && result.value != ABSENT) return result;
|
||||
where_to_start = PrototypeIterator::START_AT_PROTOTYPE;
|
||||
}
|
||||
isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS);
|
||||
RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe<PropertyAttributes>());
|
||||
return maybe(ABSENT);
|
||||
}
|
||||
|
||||
|
||||
MaybeHandle<Object> Object::GetElementWithReceiver(Isolate* isolate,
|
||||
Handle<Object> object,
|
||||
Handle<Object> receiver,
|
||||
|
@ -768,14 +850,14 @@ MaybeHandle<Object> Object::GetElementWithReceiver(Isolate* isolate,
|
|||
// Check access rights if needed.
|
||||
if (js_object->IsAccessCheckNeeded()) {
|
||||
if (!isolate->MayIndexedAccess(js_object, index, v8::ACCESS_GET)) {
|
||||
isolate->ReportFailedAccessCheck(js_object, v8::ACCESS_GET);
|
||||
RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
||||
return isolate->factory()->undefined_value();
|
||||
return JSObject::GetElementWithFailedAccessCheck(isolate, js_object,
|
||||
receiver, index);
|
||||
}
|
||||
}
|
||||
|
||||
if (js_object->HasIndexedInterceptor()) {
|
||||
return JSObject::GetElementWithInterceptor(js_object, receiver, index);
|
||||
return JSObject::GetElementWithInterceptor(js_object, receiver, index,
|
||||
true);
|
||||
}
|
||||
|
||||
if (js_object->elements() != isolate->heap()->empty_fixed_array()) {
|
||||
|
@ -4184,9 +4266,8 @@ Maybe<PropertyAttributes> JSObject::GetElementAttributeWithReceiver(
|
|||
// Check access rights if needed.
|
||||
if (object->IsAccessCheckNeeded()) {
|
||||
if (!isolate->MayIndexedAccess(object, index, v8::ACCESS_HAS)) {
|
||||
isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS);
|
||||
RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe<PropertyAttributes>());
|
||||
return maybe(ABSENT);
|
||||
return GetElementAttributesWithFailedAccessCheck(isolate, object,
|
||||
receiver, index);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13383,10 +13464,10 @@ MaybeHandle<Object> JSArray::ReadOnlyLengthError(Handle<JSArray> array) {
|
|||
}
|
||||
|
||||
|
||||
MaybeHandle<Object> JSObject::GetElementWithInterceptor(
|
||||
Handle<JSObject> object,
|
||||
Handle<Object> receiver,
|
||||
uint32_t index) {
|
||||
MaybeHandle<Object> JSObject::GetElementWithInterceptor(Handle<JSObject> object,
|
||||
Handle<Object> receiver,
|
||||
uint32_t index,
|
||||
bool check_prototype) {
|
||||
Isolate* isolate = object->GetIsolate();
|
||||
|
||||
// Make sure that the top context does not change when doing
|
||||
|
@ -13411,6 +13492,8 @@ MaybeHandle<Object> JSObject::GetElementWithInterceptor(
|
|||
}
|
||||
}
|
||||
|
||||
if (!check_prototype) return MaybeHandle<Object>();
|
||||
|
||||
ElementsAccessor* handler = object->GetElementsAccessor();
|
||||
Handle<Object> result;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
|
|
|
@ -1971,9 +1971,8 @@ class JSObject: public JSReceiver {
|
|||
// Returns the index'th element.
|
||||
// The undefined object if index is out of bounds.
|
||||
MUST_USE_RESULT static MaybeHandle<Object> GetElementWithInterceptor(
|
||||
Handle<JSObject> object,
|
||||
Handle<Object> receiver,
|
||||
uint32_t index);
|
||||
Handle<JSObject> object, Handle<Object> receiver, uint32_t index,
|
||||
bool check_prototype);
|
||||
|
||||
enum SetFastElementsCapacitySmiMode {
|
||||
kAllowSmiElements,
|
||||
|
@ -2336,6 +2335,14 @@ class JSObject: public JSReceiver {
|
|||
Handle<Object> value,
|
||||
StrictMode strict_mode,
|
||||
bool check_prototype = true);
|
||||
MUST_USE_RESULT static MaybeHandle<Object> GetElementWithFailedAccessCheck(
|
||||
Isolate* isolate, Handle<JSObject> object, Handle<Object> receiver,
|
||||
uint32_t index);
|
||||
MUST_USE_RESULT static Maybe<PropertyAttributes>
|
||||
GetElementAttributesWithFailedAccessCheck(Isolate* isolate,
|
||||
Handle<JSObject> object,
|
||||
Handle<Object> receiver,
|
||||
uint32_t index);
|
||||
|
||||
MUST_USE_RESULT static MaybeHandle<Object> SetPropertyWithFailedAccessCheck(
|
||||
LookupIterator* it, Handle<Object> value, StrictMode strict_mode);
|
||||
|
@ -7062,8 +7069,6 @@ class SharedFunctionInfo: public HeapObject {
|
|||
static const int kUniqueIdOffset = kFeedbackVectorOffset + kPointerSize;
|
||||
static const int kLastPointerFieldOffset = kUniqueIdOffset;
|
||||
#else
|
||||
// Just to not break the postmortem support with conditional offsets
|
||||
static const int kUniqueIdOffset = kFeedbackVectorOffset;
|
||||
static const int kLastPointerFieldOffset = kFeedbackVectorOffset;
|
||||
#endif
|
||||
|
||||
|
@ -10642,6 +10647,7 @@ class InterceptorInfo: public Struct {
|
|||
DECL_ACCESSORS(enumerator, Object)
|
||||
DECL_ACCESSORS(data, Object)
|
||||
DECL_BOOLEAN_ACCESSORS(can_intercept_symbols)
|
||||
DECL_BOOLEAN_ACCESSORS(all_can_read)
|
||||
|
||||
inline int flags() const;
|
||||
inline void set_flags(int flags);
|
||||
|
@ -10662,6 +10668,7 @@ class InterceptorInfo: public Struct {
|
|||
static const int kSize = kFlagsOffset + kPointerSize;
|
||||
|
||||
static const int kCanInterceptSymbolsBit = 0;
|
||||
static const int kAllCanReadBit = 1;
|
||||
|
||||
private:
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(InterceptorInfo);
|
||||
|
|
|
@ -246,7 +246,8 @@ RUNTIME_FUNCTION(Runtime_DebugIndexedInterceptorElementValue) {
|
|||
CONVERT_NUMBER_CHECKED(uint32_t, index, Uint32, args[1]);
|
||||
Handle<Object> result;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
||||
isolate, result, JSObject::GetElementWithInterceptor(obj, obj, index));
|
||||
isolate, result,
|
||||
JSObject::GetElementWithInterceptor(obj, obj, index, true));
|
||||
return *result;
|
||||
}
|
||||
|
||||
|
|
|
@ -278,7 +278,7 @@ void CompiledReplacement::Apply(ReplacementStringBuilder* builder,
|
|||
}
|
||||
|
||||
|
||||
void FindOneByteStringIndices(Vector<const uint8_t> subject, char pattern,
|
||||
void FindOneByteStringIndices(Vector<const uint8_t> subject, uint8_t pattern,
|
||||
ZoneList<int>* indices, unsigned int limit,
|
||||
Zone* zone) {
|
||||
DCHECK(limit > 0);
|
||||
|
|
|
@ -2054,6 +2054,10 @@ void Serializer::Pad() {
|
|||
for (unsigned i = 0; i < sizeof(int32_t) - 1; i++) {
|
||||
sink_->Put(kNop, "Padding");
|
||||
}
|
||||
// Pad up to pointer size for checksum.
|
||||
while (!IsAligned(sink_->Position(), kPointerAlignment)) {
|
||||
sink_->Put(kNop, "Padding");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -2394,6 +2398,41 @@ Vector<const byte> SnapshotData::Payload() const {
|
|||
}
|
||||
|
||||
|
||||
class Checksum {
|
||||
public:
|
||||
explicit Checksum(Vector<const byte> payload) {
|
||||
// Fletcher's checksum. Modified to reduce 64-bit sums to 32-bit.
|
||||
uintptr_t a = 1;
|
||||
uintptr_t b = 0;
|
||||
const uintptr_t* cur = reinterpret_cast<const uintptr_t*>(payload.start());
|
||||
DCHECK(IsAligned(payload.length(), kIntptrSize));
|
||||
const uintptr_t* end = cur + payload.length() / kIntptrSize;
|
||||
while (cur < end) {
|
||||
// Unsigned overflow expected and intended.
|
||||
a += *cur++;
|
||||
b += a;
|
||||
}
|
||||
#if V8_HOST_ARCH_64_BIT
|
||||
a ^= a >> 32;
|
||||
b ^= b >> 32;
|
||||
#endif // V8_HOST_ARCH_64_BIT
|
||||
a_ = static_cast<uint32_t>(a);
|
||||
b_ = static_cast<uint32_t>(b);
|
||||
}
|
||||
|
||||
bool Check(uint32_t a, uint32_t b) const { return a == a_ && b == b_; }
|
||||
|
||||
uint32_t a() const { return a_; }
|
||||
uint32_t b() const { return b_; }
|
||||
|
||||
private:
|
||||
uint32_t a_;
|
||||
uint32_t b_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Checksum);
|
||||
};
|
||||
|
||||
|
||||
SerializedCodeData::SerializedCodeData(const List<byte>& payload,
|
||||
const CodeSerializer& cs) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
|
@ -2412,12 +2451,20 @@ SerializedCodeData::SerializedCodeData(const List<byte>& payload,
|
|||
AllocateData(size);
|
||||
|
||||
// Set header values.
|
||||
SetHeaderValue(kCheckSumOffset, CheckSum(cs.source()));
|
||||
SetHeaderValue(kVersionHashOffset, Version::Hash());
|
||||
SetHeaderValue(kSourceHashOffset, SourceHash(cs.source()));
|
||||
SetHeaderValue(kCpuFeaturesOffset,
|
||||
static_cast<uint32_t>(CpuFeatures::SupportedFeatures()));
|
||||
SetHeaderValue(kFlagHashOffset, FlagList::Hash());
|
||||
SetHeaderValue(kNumInternalizedStringsOffset, cs.num_internalized_strings());
|
||||
SetHeaderValue(kReservationsOffset, reservations.length());
|
||||
SetHeaderValue(kNumCodeStubKeysOffset, num_stub_keys);
|
||||
SetHeaderValue(kPayloadLengthOffset, payload.length());
|
||||
|
||||
Checksum checksum(payload.ToConstVector());
|
||||
SetHeaderValue(kChecksum1Offset, checksum.a());
|
||||
SetHeaderValue(kChecksum2Offset, checksum.b());
|
||||
|
||||
// Copy reservation chunk sizes.
|
||||
CopyBytes(data_ + kHeaderSize, reinterpret_cast<byte*>(reservations.begin()),
|
||||
reservation_size);
|
||||
|
@ -2432,14 +2479,14 @@ SerializedCodeData::SerializedCodeData(const List<byte>& payload,
|
|||
}
|
||||
|
||||
|
||||
bool SerializedCodeData::IsSane(String* source) {
|
||||
return GetHeaderValue(kCheckSumOffset) == CheckSum(source) &&
|
||||
Payload().length() >= SharedFunctionInfo::kSize;
|
||||
}
|
||||
|
||||
|
||||
int SerializedCodeData::CheckSum(String* string) {
|
||||
return Version::Hash() ^ string->length();
|
||||
bool SerializedCodeData::IsSane(String* source) const {
|
||||
return GetHeaderValue(kVersionHashOffset) == Version::Hash() &&
|
||||
GetHeaderValue(kSourceHashOffset) == SourceHash(source) &&
|
||||
GetHeaderValue(kCpuFeaturesOffset) ==
|
||||
static_cast<uint32_t>(CpuFeatures::SupportedFeatures()) &&
|
||||
GetHeaderValue(kFlagHashOffset) == FlagList::Hash() &&
|
||||
Checksum(Payload()).Check(GetHeaderValue(kChecksum1Offset),
|
||||
GetHeaderValue(kChecksum2Offset));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -481,12 +481,14 @@ class SerializedData {
|
|||
class IsLastChunkBits : public BitField<bool, 31, 1> {};
|
||||
|
||||
protected:
|
||||
void SetHeaderValue(int offset, int value) {
|
||||
reinterpret_cast<int*>(data_)[offset] = value;
|
||||
void SetHeaderValue(int offset, uint32_t value) {
|
||||
memcpy(reinterpret_cast<uint32_t*>(data_) + offset, &value, sizeof(value));
|
||||
}
|
||||
|
||||
int GetHeaderValue(int offset) const {
|
||||
return reinterpret_cast<const int*>(data_)[offset];
|
||||
uint32_t GetHeaderValue(int offset) const {
|
||||
uint32_t value;
|
||||
memcpy(&value, reinterpret_cast<int*>(data_) + offset, sizeof(value));
|
||||
return value;
|
||||
}
|
||||
|
||||
void AllocateData(int size);
|
||||
|
@ -920,22 +922,32 @@ class SerializedCodeData : public SerializedData {
|
|||
explicit SerializedCodeData(ScriptData* data)
|
||||
: SerializedData(const_cast<byte*>(data->data()), data->length()) {}
|
||||
|
||||
bool IsSane(String* source);
|
||||
bool IsSane(String* source) const;
|
||||
|
||||
int CheckSum(String* source);
|
||||
static uint32_t SourceHash(String* source) { return source->length(); }
|
||||
|
||||
// The data header consists of int-sized entries:
|
||||
// [0] version hash
|
||||
// [1] number of internalized strings
|
||||
// [2] number of code stub keys
|
||||
// [3] number of reservation size entries
|
||||
// [4] payload length
|
||||
static const int kCheckSumOffset = 0;
|
||||
static const int kNumInternalizedStringsOffset = 1;
|
||||
static const int kReservationsOffset = 2;
|
||||
static const int kNumCodeStubKeysOffset = 3;
|
||||
static const int kPayloadLengthOffset = 4;
|
||||
static const int kHeaderSize = (kPayloadLengthOffset + 1) * kIntSize;
|
||||
// [1] source hash
|
||||
// [2] cpu features
|
||||
// [3] flag hash
|
||||
// [4] number of internalized strings
|
||||
// [5] number of code stub keys
|
||||
// [6] number of reservation size entries
|
||||
// [7] payload length
|
||||
// [8] checksum 1
|
||||
// [9] checksum 2
|
||||
static const int kVersionHashOffset = 0;
|
||||
static const int kSourceHashOffset = 1;
|
||||
static const int kCpuFeaturesOffset = 2;
|
||||
static const int kFlagHashOffset = 3;
|
||||
static const int kNumInternalizedStringsOffset = 4;
|
||||
static const int kReservationsOffset = 5;
|
||||
static const int kNumCodeStubKeysOffset = 6;
|
||||
static const int kPayloadLengthOffset = 7;
|
||||
static const int kChecksum1Offset = 8;
|
||||
static const int kChecksum2Offset = 9;
|
||||
static const int kHeaderSize = (kChecksum2Offset + 1) * kIntSize;
|
||||
};
|
||||
} } // namespace v8::internal
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#define MAJOR_VERSION 4
|
||||
#define MINOR_VERSION 1
|
||||
#define BUILD_NUMBER 0
|
||||
#define PATCH_LEVEL 14
|
||||
#define PATCH_LEVEL 21
|
||||
// Use 1 for candidates and 0 otherwise.
|
||||
// (Boolean macro values are not supported by all preprocessors.)
|
||||
#define IS_CANDIDATE_VERSION 0
|
||||
|
|
|
@ -18,8 +18,9 @@ class Version {
|
|||
static int GetBuild() { return build_; }
|
||||
static int GetPatch() { return patch_; }
|
||||
static bool IsCandidate() { return candidate_; }
|
||||
static int Hash() {
|
||||
return static_cast<int>(base::hash_combine(major_, minor_, build_, patch_));
|
||||
static uint32_t Hash() {
|
||||
return static_cast<uint32_t>(
|
||||
base::hash_combine(major_, minor_, build_, patch_));
|
||||
}
|
||||
|
||||
// Calculate the V8 version string.
|
||||
|
|
|
@ -24540,7 +24540,7 @@ TEST(StreamingUtf8ScriptWithMultipleMultibyteCharactersSomeSplit2) {
|
|||
|
||||
|
||||
void TestInvalidCacheData(v8::ScriptCompiler::CompileOptions option) {
|
||||
const char* garbage = "garbage garbage garbage garbage.";
|
||||
const char* garbage = "garbage garbage garbage garbage garbage garbage";
|
||||
const uint8_t* data = reinterpret_cast<const uint8_t*>(garbage);
|
||||
int length = 16;
|
||||
v8::ScriptCompiler::CachedData* cached_data =
|
||||
|
|
|
@ -1156,6 +1156,56 @@ TEST(SerializeToplevelIsolates) {
|
|||
}
|
||||
|
||||
|
||||
TEST(SerializeToplevelFlagChange) {
|
||||
FLAG_serialize_toplevel = true;
|
||||
|
||||
const char* source = "function f() { return 'abc'; }; f() + 'def'";
|
||||
v8::ScriptCompiler::CachedData* cache;
|
||||
|
||||
v8::Isolate* isolate1 = v8::Isolate::New();
|
||||
{
|
||||
v8::Isolate::Scope iscope(isolate1);
|
||||
v8::HandleScope scope(isolate1);
|
||||
v8::Local<v8::Context> context = v8::Context::New(isolate1);
|
||||
v8::Context::Scope context_scope(context);
|
||||
|
||||
v8::Local<v8::String> source_str = v8_str(source);
|
||||
v8::ScriptOrigin origin(v8_str("test"));
|
||||
v8::ScriptCompiler::Source source(source_str, origin);
|
||||
v8::Local<v8::UnboundScript> script = v8::ScriptCompiler::CompileUnbound(
|
||||
isolate1, &source, v8::ScriptCompiler::kProduceCodeCache);
|
||||
const v8::ScriptCompiler::CachedData* data = source.GetCachedData();
|
||||
CHECK(data);
|
||||
// Persist cached data.
|
||||
uint8_t* buffer = NewArray<uint8_t>(data->length);
|
||||
MemCopy(buffer, data->data, data->length);
|
||||
cache = new v8::ScriptCompiler::CachedData(
|
||||
buffer, data->length, v8::ScriptCompiler::CachedData::BufferOwned);
|
||||
|
||||
v8::Local<v8::Value> result = script->BindToCurrentContext()->Run();
|
||||
CHECK(result->ToString(isolate1)->Equals(v8_str("abcdef")));
|
||||
}
|
||||
isolate1->Dispose();
|
||||
|
||||
v8::Isolate* isolate2 = v8::Isolate::New();
|
||||
FLAG_allow_natives_syntax = true; // Flag change should trigger cache reject.
|
||||
{
|
||||
v8::Isolate::Scope iscope(isolate2);
|
||||
v8::HandleScope scope(isolate2);
|
||||
v8::Local<v8::Context> context = v8::Context::New(isolate2);
|
||||
v8::Context::Scope context_scope(context);
|
||||
|
||||
v8::Local<v8::String> source_str = v8_str(source);
|
||||
v8::ScriptOrigin origin(v8_str("test"));
|
||||
v8::ScriptCompiler::Source source(source_str, origin, cache);
|
||||
v8::ScriptCompiler::CompileUnbound(isolate2, &source,
|
||||
v8::ScriptCompiler::kConsumeCodeCache);
|
||||
CHECK(cache->rejected);
|
||||
}
|
||||
isolate2->Dispose();
|
||||
}
|
||||
|
||||
|
||||
TEST(SerializeWithHarmonyScoping) {
|
||||
FLAG_serialize_toplevel = true;
|
||||
FLAG_harmony_scoping = true;
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright 2015 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
function* g() {}
|
||||
assertTrue(Object.getOwnPropertyDescriptor(g.__proto__, "constructor").configurable);
|
||||
assertTrue(Object.getOwnPropertyDescriptor(g.prototype.__proto__, "constructor").configurable);
|
||||
|
||||
function FakeGeneratorFunctionConstructor() {}
|
||||
Object.defineProperty(g.__proto__, "constructor", {value: FakeGeneratorFunctionConstructor});
|
||||
assertSame(g.__proto__.constructor, FakeGeneratorFunctionConstructor);
|
||||
|
||||
function FakeGeneratorObjectConstructor() {}
|
||||
Object.defineProperty(g.prototype.__proto__, "constructor", {value: FakeGeneratorObjectConstructor});
|
||||
assertSame(g.prototype.__proto__.constructor, FakeGeneratorObjectConstructor);
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Flags: --allow-natives-syntax --expose-gc
|
||||
|
||||
var array_1 = [];
|
||||
|
||||
%SetFlags("--stress-compaction");
|
||||
for (var a = 0; a < 10000; a++) { array_1[a * 100] = 0; }
|
||||
|
||||
gc();
|
||||
gc();
|
||||
|
||||
var array_2 = [];
|
||||
for (var i = 0; i < 321361; i++) {
|
||||
array_2[i] = String.fromCharCode(i)[0];
|
||||
}
|
|
@ -70,6 +70,8 @@ consts_misc = [
|
|||
{ 'name': 'ExternalStringTag', 'value': 'kExternalStringTag' },
|
||||
{ 'name': 'SlicedStringTag', 'value': 'kSlicedStringTag' },
|
||||
|
||||
{ 'name': 'FailureTag', 'value': 'kFailureTag' },
|
||||
{ 'name': 'FailureTagMask', 'value': 'kFailureTagMask' },
|
||||
{ 'name': 'HeapObjectTag', 'value': 'kHeapObjectTag' },
|
||||
{ 'name': 'HeapObjectTagMask', 'value': 'kHeapObjectTagMask' },
|
||||
{ 'name': 'SmiTag', 'value': 'kSmiTag' },
|
||||
|
@ -92,6 +94,8 @@ consts_misc = [
|
|||
'value': 'DescriptorArray::kFirstIndex' },
|
||||
{ 'name': 'prop_type_field',
|
||||
'value': 'FIELD' },
|
||||
{ 'name': 'prop_type_first_phantom',
|
||||
'value': 'TRANSITION' },
|
||||
{ 'name': 'prop_type_mask',
|
||||
'value': 'PropertyDetails::TypeField::kMask' },
|
||||
{ 'name': 'prop_index_mask',
|
||||
|
@ -116,9 +120,9 @@ consts_misc = [
|
|||
'value': 'DICTIONARY_ELEMENTS' },
|
||||
|
||||
{ 'name': 'bit_field2_elements_kind_mask',
|
||||
'value': 'Map::ElementsKindBits::kMask' },
|
||||
'value': 'Map::kElementsKindMask' },
|
||||
{ 'name': 'bit_field2_elements_kind_shift',
|
||||
'value': 'Map::ElementsKindBits::kShift' },
|
||||
'value': 'Map::kElementsKindShift' },
|
||||
{ 'name': 'bit_field3_dictionary_map_shift',
|
||||
'value': 'Map::DictionaryMap::kShift' },
|
||||
|
||||
|
@ -192,9 +196,9 @@ header = '''
|
|||
* This file is generated by %s. Do not edit directly.
|
||||
*/
|
||||
|
||||
#include "src/v8.h"
|
||||
#include "src/frames.h"
|
||||
#include "src/frames-inl.h" /* for architecture-specific frame constants */
|
||||
#include "v8.h"
|
||||
#include "frames.h"
|
||||
#include "frames-inl.h" /* for architecture-specific frame constants */
|
||||
|
||||
using namespace v8::internal;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче