[torque] Stricter object field verification, part 2

This change removes the special case in the Torque compiler for types
that descend from JSObject: they will no longer get implicit
"| Undefined" appended to their types for verification purposes. It
removes any additional custom verification steps in objects-debug that
are made redundant by that change.

In order to do so safely, I categorized all cases where we were
implicitly adding "| Undefined" to the field type, as follows:

1. Classes that aren't using the generated verifier function (we should
   probably revisit these, but for now we at least know they're safe):
   - JSGlobalObject
   - JSFinalizationGroup
   - JSFinalizationGroupCleanupIterator

2. Classes where the existing verifier is already at least as strict as
   what we would get after removing the implicit "| Undefined":
   - JSDate
   - JSPromise
   - JSRegExp
   - JSRegExpStringIterator
   - WasmMemoryObject
   - JSWeakRef
   - JSStringIterator
   - WasmExceptionObject
   - JSListFormat (fixed in part 1)
   - JSPluralRules (fixed in part 1)
   - JSRelativeTimeFormat (fixed in part 1)
   - JSSegmenter (fixed in part 1)
   - JSArrayBufferView (fixed in part 1)
   - JSTypedArray (fixed in part 1)

3. Classes where, to the best of my knowledge based on code inspection,
   we already initialize the object correctly to pass the new stricter
   generated verifier:
   - JSFunction
   - JSArrayIterator
   - JSMessageObject
   - JSBoundFunction
   - JSAsyncFromSyncIterator
   - WasmModuleObject
   - JSAsyncFunctionObject

4. Classes that needed some adjustment to their initialization order to
   avoid exposing uninitialized state to the GC:
   - JSArray (only in Factory::NewJSArray; Runtime_NewArray and
              CodeStubAssembler::AllocateJSArray already behave fine)
   - WasmTableObject
   - JSDateTimeFormat
   - JSNumberFormat
   - JSCollator
   - JSV8BreakIterator
   - JSLocale
   - JSSegmentIterator
   - JSModuleNamespace

5. Classes that had incorrect type definitions in Torque:
   - WasmGlobalObject (category 4 after correction)

6. Classes that weren't fully initialized due to bugs:
   - JSGeneratorObject
   - JSAsyncGeneratorObject

Bug: v8:9311
Change-Id: I99ab303d3352423f50a3d0abb6eb0c9b463e7552
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1654980
Commit-Queue: Seth Brenith <seth.brenith@microsoft.com>
Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Sigurd Schneider <sigurds@chromium.org>
Cr-Commit-Position: refs/heads/master@{#62228}
This commit is contained in:
Seth Brenith 2019-06-17 10:56:48 -07:00 committed by Commit Bot
parent f021c622a9
commit 15ea19dbca
25 changed files with 221 additions and 240 deletions

View File

@ -565,7 +565,7 @@ extern class SharedFunctionInfo extends HeapObject {
}
extern class JSBoundFunction extends JSObject {
bound_target_function: JSReceiver;
bound_target_function: Callable;
bound_this: Object;
bound_arguments: FixedArray;
}
@ -1313,8 +1313,8 @@ extern class WasmMemoryObject extends JSObject {
}
extern class WasmGlobalObject extends JSObject {
untagged_buffer: JSArrayBuffer;
tagged_buffer: FixedArray;
untagged_buffer: JSArrayBuffer | Undefined;
tagged_buffer: FixedArray | Undefined;
offset: Smi;
flags: Smi;
}

View File

@ -276,15 +276,14 @@ Object LegacyFormatConstructor(BuiltinArguments args, Isolate* isolate,
// 2. Let format be ? OrdinaryCreateFromConstructor(newTarget,
// "%<T>Prototype%", ...).
Handle<JSObject> obj;
Handle<Map> map;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, obj,
JSObject::New(target, new_target, Handle<AllocationSite>::null()));
Handle<T> format = Handle<T>::cast(obj);
isolate, map, JSFunction::GetDerivedMap(isolate, target, new_target));
// 3. Perform ? Initialize<T>(Format, locales, options).
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, format, T::Initialize(isolate, format, locales, options));
Handle<T> format;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, format,
T::New(isolate, map, locales, options));
// 4. Let this be the this value.
Handle<Object> receiver = args.receiver();
@ -383,14 +382,11 @@ Object CallOrConstructConstructor(BuiltinArguments args, Isolate* isolate) {
Handle<Object> locales = args.atOrUndefined(isolate, 1);
Handle<Object> options = args.atOrUndefined(isolate, 2);
Handle<JSObject> obj;
Handle<Map> map;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, obj,
JSObject::New(target, new_target, Handle<AllocationSite>::null()));
Handle<T> result = Handle<T>::cast(obj);
isolate, map, JSFunction::GetDerivedMap(isolate, target, new_target));
RETURN_RESULT_OR_FAILURE(isolate,
T::Initialize(isolate, result, locales, options));
RETURN_RESULT_OR_FAILURE(isolate, T::New(isolate, map, locales, options));
}
} // namespace
@ -587,12 +583,11 @@ MaybeHandle<JSLocale> CreateLocale(Isolate* isolate,
Handle<JSFunction> constructor,
Handle<JSReceiver> new_target,
Handle<Object> tag, Handle<Object> options) {
Handle<JSObject> locale;
Handle<Map> map;
// 6. Let locale be ? OrdinaryCreateFromConstructor(NewTarget,
// %LocalePrototype%, internalSlotsList).
ASSIGN_RETURN_ON_EXCEPTION(
isolate, locale,
JSObject::New(constructor, new_target, Handle<AllocationSite>::null()),
isolate, map, JSFunction::GetDerivedMap(isolate, constructor, new_target),
JSLocale);
// 7. If Type(tag) is not String or Object, throw a TypeError exception.
@ -624,8 +619,7 @@ MaybeHandle<JSLocale> CreateLocale(Isolate* isolate,
Object::ToObject(isolate, options), JSLocale);
}
return JSLocale::Initialize(isolate, Handle<JSLocale>::cast(locale),
locale_string, options_object);
return JSLocale::New(isolate, map, locale_string, options_object);
}
} // namespace

View File

@ -1337,10 +1337,15 @@ TF_BUILTIN(CreateGeneratorObject, ObjectBuiltinsAssembler) {
StoreObjectFieldNoWriteBarrier(
result, JSGeneratorObject::kParametersAndRegistersOffset,
parameters_and_registers);
Node* resume_mode = SmiConstant(JSGeneratorObject::ResumeMode::kNext);
StoreObjectFieldNoWriteBarrier(result, JSGeneratorObject::kResumeModeOffset,
resume_mode);
Node* executing = SmiConstant(JSGeneratorObject::kGeneratorExecuting);
StoreObjectFieldNoWriteBarrier(result, JSGeneratorObject::kContinuationOffset,
executing);
GotoIfNot(HasInstanceType(maybe_map, JS_ASYNC_GENERATOR_OBJECT_TYPE), &done);
GotoIfNot(InstanceTypeEqual(LoadMapInstanceType(maybe_map),
JS_ASYNC_GENERATOR_OBJECT_TYPE),
&done);
StoreObjectFieldNoWriteBarrier(
result, JSAsyncGeneratorObject::kIsAwaitingOffset, SmiConstant(0));
Goto(&done);

View File

@ -837,7 +837,7 @@ Reduction JSCreateLowering::ReduceJSCreateCollectionIterator(Node* node) {
simplified()->LoadField(AccessBuilder::ForJSCollectionTable()),
iterated_object, effect, control);
// Create the JSArrayIterator result.
// Create the JSCollectionIterator result.
AllocationBuilder a(jsgraph(), effect, control);
a.Allocate(JSCollectionIterator::kSize, AllocationType::kYoung,
Type::OtherObject());

View File

@ -956,13 +956,7 @@ void JSDate::JSDateVerify(Isolate* isolate) {
}
}
void JSMessageObject::JSMessageObjectVerify(Isolate* isolate) {
TorqueGeneratedClassVerifiers::JSMessageObjectVerify(*this, isolate);
VerifySmiField(kMessageTypeOffset);
VerifySmiField(kStartPositionOffset);
VerifySmiField(kEndPositionOffset);
VerifySmiField(kErrorLevelOffset);
}
USE_TORQUE_VERIFIER(JSMessageObject)
USE_TORQUE_VERIFIER(Name)
@ -1007,16 +1001,11 @@ USE_TORQUE_VERIFIER(ExternalString)
void JSBoundFunction::JSBoundFunctionVerify(Isolate* isolate) {
TorqueGeneratedClassVerifiers::JSBoundFunctionVerify(*this, isolate);
CHECK(IsCallable());
if (!raw_bound_target_function().IsUndefined(isolate)) {
CHECK(bound_target_function().IsCallable());
CHECK_EQ(IsConstructor(), bound_target_function().IsConstructor());
}
CHECK_EQ(IsConstructor(), bound_target_function().IsConstructor());
}
void JSFunction::JSFunctionVerify(Isolate* isolate) {
TorqueGeneratedClassVerifiers::JSFunctionVerify(*this, isolate);
CHECK(raw_feedback_cell().IsFeedbackCell());
CHECK(code().IsCode());
CHECK(map().is_callable());
Handle<JSFunction> function(*this, isolate);
@ -1196,7 +1185,6 @@ void JSArray::JSArrayVerify(Isolate* isolate) {
if (elements().length() == 0) {
CHECK_EQ(elements(), ReadOnlyRoots(isolate).empty_fixed_array());
}
if (!length().IsNumber()) return;
// Verify that the length and the elements backing store are in sync.
if (length().IsSmi() && (HasFastElements() || HasFrozenOrSealedElements())) {
if (elements().length() > 0) {
@ -1327,7 +1315,6 @@ void JSWeakMap::JSWeakMapVerify(Isolate* isolate) {
void JSArrayIterator::JSArrayIteratorVerify(Isolate* isolate) {
TorqueGeneratedClassVerifiers::JSArrayIteratorVerify(*this, isolate);
CHECK(iterated_object().IsJSReceiver());
CHECK_GE(next_index().Number(), 0);
CHECK_LE(next_index().Number(), kMaxSafeInteger);
@ -1344,8 +1331,6 @@ void JSArrayIterator::JSArrayIteratorVerify(Isolate* isolate) {
void JSStringIterator::JSStringIteratorVerify(Isolate* isolate) {
TorqueGeneratedClassVerifiers::JSStringIteratorVerify(*this, isolate);
CHECK(string().IsString());
CHECK_GE(index(), 0);
CHECK_LE(index(), String::kMaxLength);
}
@ -1382,7 +1367,6 @@ USE_TORQUE_VERIFIER(PromiseReaction)
void JSPromise::JSPromiseVerify(Isolate* isolate) {
TorqueGeneratedClassVerifiers::JSPromiseVerify(*this, isolate);
VerifySmiField(kFlagsOffset);
if (status() == Promise::kPending) {
CHECK(reactions().IsSmi() || reactions().IsPromiseReaction());
}
@ -1498,11 +1482,7 @@ void JSRegExp::JSRegExpVerify(Isolate* isolate) {
}
}
void JSRegExpStringIterator::JSRegExpStringIteratorVerify(Isolate* isolate) {
TorqueGeneratedClassVerifiers::JSRegExpStringIteratorVerify(*this, isolate);
CHECK(iterating_string().IsString());
VerifySmiField(kFlagsOffset);
}
USE_TORQUE_VERIFIER(JSRegExpStringIterator)
void JSProxy::JSProxyVerify(Isolate* isolate) {
TorqueGeneratedClassVerifiers::JSProxyVerify(*this, isolate);
@ -1527,7 +1507,6 @@ void JSArrayBuffer::JSArrayBufferVerify(Isolate* isolate) {
void JSArrayBufferView::JSArrayBufferViewVerify(Isolate* isolate) {
TorqueGeneratedClassVerifiers::JSArrayBufferViewVerify(*this, isolate);
CHECK(buffer().IsJSArrayBuffer());
CHECK_LE(byte_length(), JSArrayBuffer::kMaxByteLength);
CHECK_LE(byte_offset(), JSArrayBuffer::kMaxByteLength);
}
@ -1687,31 +1666,15 @@ void WasmExportedFunctionData::WasmExportedFunctionDataVerify(
wrapper_code().kind() == Code::C_WASM_ENTRY);
}
void WasmModuleObject::WasmModuleObjectVerify(Isolate* isolate) {
TorqueGeneratedClassVerifiers::WasmModuleObjectVerify(*this, isolate);
CHECK(managed_native_module().IsForeign());
CHECK(export_wrappers().IsFixedArray());
CHECK(script().IsScript());
}
USE_TORQUE_VERIFIER(WasmModuleObject)
void WasmTableObject::WasmTableObjectVerify(Isolate* isolate) {
TorqueGeneratedClassVerifiers::WasmTableObjectVerify(*this, isolate);
CHECK(elements().IsFixedArray());
VerifySmiField(kRawTypeOffset);
}
USE_TORQUE_VERIFIER(WasmTableObject)
void WasmMemoryObject::WasmMemoryObjectVerify(Isolate* isolate) {
TorqueGeneratedClassVerifiers::WasmMemoryObjectVerify(*this, isolate);
CHECK(array_buffer().IsJSArrayBuffer());
VerifySmiField(kMaximumPagesOffset);
}
USE_TORQUE_VERIFIER(WasmMemoryObject)
USE_TORQUE_VERIFIER(WasmGlobalObject)
void WasmExceptionObject::WasmExceptionObjectVerify(Isolate* isolate) {
TorqueGeneratedClassVerifiers::WasmExceptionObjectVerify(*this, isolate);
CHECK(serialized_signature().IsByteArray());
}
USE_TORQUE_VERIFIER(WasmExceptionObject)
void DataHandler::DataHandlerVerify(Isolate* isolate) {
TorqueGeneratedClassVerifiers::DataHandlerVerify(*this, isolate);
@ -1858,51 +1821,21 @@ USE_TORQUE_VERIFIER(JSV8BreakIterator)
USE_TORQUE_VERIFIER(JSCollator)
void JSDateTimeFormat::JSDateTimeFormatVerify(Isolate* isolate) {
TorqueGeneratedClassVerifiers::JSDateTimeFormatVerify(*this, isolate);
VerifySmiField(kFlagsOffset);
}
USE_TORQUE_VERIFIER(JSDateTimeFormat)
void JSListFormat::JSListFormatVerify(Isolate* isolate) {
TorqueGeneratedClassVerifiers::JSListFormatVerify(*this, isolate);
CHECK(locale().IsString());
CHECK(icu_formatter().IsForeign());
VerifySmiField(kFlagsOffset);
}
USE_TORQUE_VERIFIER(JSListFormat)
USE_TORQUE_VERIFIER(JSLocale)
void JSNumberFormat::JSNumberFormatVerify(Isolate* isolate) {
TorqueGeneratedClassVerifiers::JSNumberFormatVerify(*this, isolate);
VerifySmiField(kFlagsOffset);
}
USE_TORQUE_VERIFIER(JSNumberFormat)
void JSPluralRules::JSPluralRulesVerify(Isolate* isolate) {
TorqueGeneratedClassVerifiers::JSPluralRulesVerify(*this, isolate);
CHECK(locale().IsString());
VerifySmiField(kFlagsOffset);
CHECK(icu_plural_rules().IsForeign());
CHECK(icu_number_formatter().IsForeign());
}
USE_TORQUE_VERIFIER(JSPluralRules)
void JSRelativeTimeFormat::JSRelativeTimeFormatVerify(Isolate* isolate) {
TorqueGeneratedClassVerifiers::JSRelativeTimeFormatVerify(*this, isolate);
CHECK(locale().IsString());
CHECK(icu_formatter().IsForeign());
VerifySmiField(kFlagsOffset);
}
USE_TORQUE_VERIFIER(JSRelativeTimeFormat)
void JSSegmentIterator::JSSegmentIteratorVerify(Isolate* isolate) {
TorqueGeneratedClassVerifiers::JSSegmentIteratorVerify(*this, isolate);
VerifySmiField(kFlagsOffset);
}
USE_TORQUE_VERIFIER(JSSegmentIterator)
void JSSegmenter::JSSegmenterVerify(Isolate* isolate) {
TorqueGeneratedClassVerifiers::JSSegmenterVerify(*this, isolate);
CHECK(locale().IsString());
CHECK(icu_break_iterator().IsForeign());
VerifySmiField(kFlagsOffset);
}
USE_TORQUE_VERIFIER(JSSegmenter)
#endif // V8_INTL_SUPPORT

View File

@ -2925,37 +2925,48 @@ Handle<JSObject> Factory::NewSlowJSObjectWithPropertiesAndElements(
return object;
}
Handle<JSArray> Factory::NewJSArray(ElementsKind elements_kind,
AllocationType allocation) {
NativeContext native_context = isolate()->raw_native_context();
Map map = native_context.GetInitialJSArrayMap(elements_kind);
if (map.is_null()) {
JSFunction array_function = native_context.array_function();
map = array_function.initial_map();
}
return Handle<JSArray>::cast(
NewJSObjectFromMap(handle(map, isolate()), allocation));
}
Handle<JSArray> Factory::NewJSArray(ElementsKind elements_kind, int length,
int capacity,
ArrayStorageAllocationMode mode,
AllocationType allocation) {
Handle<JSArray> array = NewJSArray(elements_kind, allocation);
NewJSArrayStorage(array, length, capacity, mode);
return array;
DCHECK(capacity >= length);
if (capacity == 0) {
return NewJSArrayWithElements(empty_fixed_array(), elements_kind, length,
allocation);
}
HandleScope inner_scope(isolate());
Handle<FixedArrayBase> elms =
NewJSArrayStorage(elements_kind, capacity, mode);
return inner_scope.CloseAndEscape(NewJSArrayWithUnverifiedElements(
elms, elements_kind, length, allocation));
}
Handle<JSArray> Factory::NewJSArrayWithElements(Handle<FixedArrayBase> elements,
ElementsKind elements_kind,
int length,
AllocationType allocation) {
DCHECK(length <= elements->length());
Handle<JSArray> array = NewJSArray(elements_kind, allocation);
Handle<JSArray> array = NewJSArrayWithUnverifiedElements(
elements, elements_kind, length, allocation);
JSObject::ValidateElements(*array);
return array;
}
Handle<JSArray> Factory::NewJSArrayWithUnverifiedElements(
Handle<FixedArrayBase> elements, ElementsKind elements_kind, int length,
AllocationType allocation) {
DCHECK(length <= elements->length());
NativeContext native_context = isolate()->raw_native_context();
Map map = native_context.GetInitialJSArrayMap(elements_kind);
if (map.is_null()) {
JSFunction array_function = native_context.array_function();
map = array_function.initial_map();
}
Handle<JSArray> array = Handle<JSArray>::cast(
NewJSObjectFromMap(handle(map, isolate()), allocation));
DisallowHeapAllocation no_gc;
array->set_elements(*elements);
array->set_length(Smi::FromInt(length));
JSObject::ValidateElements(*array);
return array;
}
@ -2970,8 +2981,17 @@ void Factory::NewJSArrayStorage(Handle<JSArray> array, int length, int capacity,
}
HandleScope inner_scope(isolate());
Handle<FixedArrayBase> elms =
NewJSArrayStorage(array->GetElementsKind(), capacity, mode);
array->set_elements(*elms);
array->set_length(Smi::FromInt(length));
}
Handle<FixedArrayBase> Factory::NewJSArrayStorage(
ElementsKind elements_kind, int capacity, ArrayStorageAllocationMode mode) {
DCHECK_GT(capacity, 0);
Handle<FixedArrayBase> elms;
ElementsKind elements_kind = array->GetElementsKind();
if (IsDoubleElementsKind(elements_kind)) {
if (mode == DONT_INITIALIZE_ARRAY_ELEMENTS) {
elms = NewFixedDoubleArray(capacity);
@ -2988,9 +3008,7 @@ void Factory::NewJSArrayStorage(Handle<JSArray> array, int length, int capacity,
elms = NewFixedArrayWithHoles(capacity);
}
}
array->set_elements(*elms);
array->set_length(Smi::FromInt(length));
return elms;
}
Handle<JSWeakMap> Factory::NewJSWeakMap() {

View File

@ -1083,11 +1083,20 @@ class V8_EXPORT_PRIVATE Factory {
Handle<String> NumberToStringCacheSet(Handle<Object> number, int hash,
const char* string, bool check_cache);
// Create a JSArray with no elements and no length.
Handle<JSArray> NewJSArray(
ElementsKind elements_kind,
// Creates a new JSArray with the given backing storage. Performs no
// verification of the backing storage because it may not yet be filled.
Handle<JSArray> NewJSArrayWithUnverifiedElements(
Handle<FixedArrayBase> elements, ElementsKind elements_kind, int length,
AllocationType allocation = AllocationType::kYoung);
// Creates the backing storage for a JSArray. This handle must be discarded
// before returning the JSArray reference to code outside Factory, which might
// decide to left-trim the backing store. To avoid unnecessary HandleScopes,
// this method requires capacity greater than zero.
Handle<FixedArrayBase> NewJSArrayStorage(
ElementsKind elements_kind, int capacity,
ArrayStorageAllocationMode mode = DONT_INITIALIZE_ARRAY_ELEMENTS);
Handle<SharedFunctionInfo> NewSharedFunctionInfo(
MaybeHandle<String> name, MaybeHandle<HeapObject> maybe_function_data,
int maybe_builtin_index, FunctionKind kind = kNormalFunction);

View File

@ -177,12 +177,11 @@ const UChar* GetUCharBufferFromFlat(const String::FlatContent& flat,
template <typename T>
MaybeHandle<T> New(Isolate* isolate, Handle<JSFunction> constructor,
Handle<Object> locales, Handle<Object> options) {
Handle<JSObject> result;
Handle<Map> map;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, result,
JSObject::New(constructor, constructor, Handle<AllocationSite>::null()),
T);
return T::Initialize(isolate, Handle<T>::cast(result), locales, options);
isolate, map,
JSFunction::GetDerivedMap(isolate, constructor, constructor), T);
return T::New(isolate, map, locales, options);
}
} // namespace

View File

@ -15,9 +15,9 @@
namespace v8 {
namespace internal {
MaybeHandle<JSV8BreakIterator> JSV8BreakIterator::Initialize(
Isolate* isolate, Handle<JSV8BreakIterator> break_iterator_holder,
Handle<Object> locales, Handle<Object> options_obj) {
MaybeHandle<JSV8BreakIterator> JSV8BreakIterator::New(
Isolate* isolate, Handle<Map> map, Handle<Object> locales,
Handle<Object> options_obj) {
Factory* factory = isolate->factory();
// 1. Let requestedLocales be ? CanonicalizeLocaleList(locales).
@ -96,8 +96,13 @@ MaybeHandle<JSV8BreakIterator> JSV8BreakIterator::Initialize(
Handle<String> locale_str =
isolate->factory()->NewStringFromAsciiChecked(r.locale.c_str());
break_iterator_holder->set_locale(*locale_str);
// Now all properties are ready, so we can allocate the result object.
Handle<JSV8BreakIterator> break_iterator_holder =
Handle<JSV8BreakIterator>::cast(
isolate->factory()->NewFastOrSlowJSObjectFromMap(map));
DisallowHeapAllocation no_gc;
break_iterator_holder->set_locale(*locale_str);
break_iterator_holder->set_type(type_enum);
break_iterator_holder->set_break_iterator(*managed_break_iterator);
break_iterator_holder->set_unicode_string(*managed_unicode_string);

View File

@ -29,9 +29,9 @@ namespace internal {
class JSV8BreakIterator : public JSObject {
public:
V8_WARN_UNUSED_RESULT static MaybeHandle<JSV8BreakIterator> Initialize(
Isolate* isolate, Handle<JSV8BreakIterator> break_iterator,
Handle<Object> input_locales, Handle<Object> input_options);
V8_WARN_UNUSED_RESULT static MaybeHandle<JSV8BreakIterator> New(
Isolate* isolate, Handle<Map> map, Handle<Object> input_locales,
Handle<Object> input_options);
static Handle<JSObject> ResolvedOptions(
Isolate* isolate, Handle<JSV8BreakIterator> break_iterator);

View File

@ -239,10 +239,9 @@ void SetCaseFirstOption(icu::Collator* icu_collator,
} // anonymous namespace
// static
MaybeHandle<JSCollator> JSCollator::Initialize(Isolate* isolate,
Handle<JSCollator> collator,
Handle<Object> locales,
Handle<Object> options_obj) {
MaybeHandle<JSCollator> JSCollator::New(Isolate* isolate, Handle<Map> map,
Handle<Object> locales,
Handle<Object> options_obj) {
// 1. Let requestedLocales be ? CanonicalizeLocaleList(locales).
Maybe<std::vector<std::string>> maybe_requested_locales =
Intl::CanonicalizeLocaleList(isolate, locales);
@ -465,6 +464,11 @@ MaybeHandle<JSCollator> JSCollator::Initialize(Isolate* isolate,
Handle<Managed<icu::Collator>> managed_collator =
Managed<icu::Collator>::FromUniquePtr(isolate, 0,
std::move(icu_collator));
// Now all properties are ready, so we can allocate the result object.
Handle<JSCollator> collator = Handle<JSCollator>::cast(
isolate->factory()->NewFastOrSlowJSObjectFromMap(map));
DisallowHeapAllocation no_gc;
collator->set_icu_collator(*managed_collator);
// 29. Return collator.

View File

@ -32,8 +32,8 @@ namespace internal {
class JSCollator : public JSObject {
public:
// ecma402/#sec-initializecollator
V8_WARN_UNUSED_RESULT static MaybeHandle<JSCollator> Initialize(
Isolate* isolate, Handle<JSCollator> collator, Handle<Object> locales,
V8_WARN_UNUSED_RESULT static MaybeHandle<JSCollator> New(
Isolate* isolate, Handle<Map> map, Handle<Object> locales,
Handle<Object> options);
// ecma402/#sec-intl.collator.prototype.resolvedoptions

View File

@ -681,17 +681,14 @@ MaybeHandle<String> JSDateTimeFormat::ToLocaleDateTime(
JSFunction::cast(
isolate->context().native_context().intl_date_time_format_function()),
isolate);
Handle<JSObject> obj;
Handle<Map> map;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, obj,
JSObject::New(constructor, constructor, Handle<AllocationSite>::null()),
String);
isolate, map,
JSFunction::GetDerivedMap(isolate, constructor, constructor), String);
Handle<JSDateTimeFormat> date_time_format;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, date_time_format,
JSDateTimeFormat::Initialize(isolate, Handle<JSDateTimeFormat>::cast(obj),
locales, internal_options),
String);
JSDateTimeFormat::New(isolate, map, locales, internal_options), String);
if (can_cache) {
isolate->set_icu_object_in_cache(
@ -1207,10 +1204,9 @@ class DateTimePatternGeneratorCache {
enum FormatMatcherOption { kBestFit, kBasic };
// ecma402/#sec-initializedatetimeformat
MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::Initialize(
Isolate* isolate, Handle<JSDateTimeFormat> date_time_format,
Handle<Object> locales, Handle<Object> input_options) {
date_time_format->set_flags(0);
MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::New(
Isolate* isolate, Handle<Map> map, Handle<Object> locales,
Handle<Object> input_options) {
Factory* factory = isolate->factory();
// 1. Let requestedLocales be ? CanonicalizeLocaleList(locales).
Maybe<std::vector<std::string>> maybe_requested_locales =
@ -1398,7 +1394,6 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::Initialize(
}
}
}
date_time_format->set_hour_cycle(hc);
DateTimeStyle date_style = DateTimeStyle::kUndefined;
DateTimeStyle time_style = DateTimeStyle::kUndefined;
@ -1418,9 +1413,6 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::Initialize(
// 29. If dateStyle is not undefined, set dateTimeFormat.[[DateStyle]] to
// dateStyle.
date_style = maybe_date_style.FromJust();
if (date_style != DateTimeStyle::kUndefined) {
date_time_format->set_date_style(date_style);
}
// 30. Let timeStyle be ? GetOption(options, "timeStyle", "string", «
// "full", "long", "medium", "short" »).
@ -1436,9 +1428,6 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::Initialize(
// 31. If timeStyle is not undefined, set dateTimeFormat.[[TimeStyle]] to
// timeStyle.
time_style = maybe_time_style.FromJust();
if (time_style != DateTimeStyle::kUndefined) {
date_time_format->set_time_style(time_style);
}
// 32. If dateStyle or timeStyle are not undefined, then
if (date_style != DateTimeStyle::kUndefined ||
@ -1512,7 +1501,7 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::Initialize(
// g. If dateTimeFormat.[[Hour]] is not undefined, then
if (!has_hour_option) {
// h. Else, i. Set dateTimeFormat.[[HourCycle]] to undefined.
date_time_format->set_hour_cycle(Intl::HourCycle::kUndefined);
hc = Intl::HourCycle::kUndefined;
}
}
@ -1538,8 +1527,7 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::Initialize(
maybe_hour_cycle.FromJust() != Intl::HourCycle::kUndefined) {
auto hc_extension_it = r.extensions.find("hc");
if (hc_extension_it != r.extensions.end()) {
if (date_time_format->hour_cycle() !=
Intl::ToHourCycle(hc_extension_it->second.c_str())) {
if (hc != Intl::ToHourCycle(hc_extension_it->second.c_str())) {
// Remove -hc- if it does not agree with what we used.
UErrorCode status = U_ZERO_ERROR;
icu_locale.setUnicodeKeywordValue("hc", nullptr, status);
@ -1551,16 +1539,28 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::Initialize(
Handle<Managed<icu::Locale>> managed_locale =
Managed<icu::Locale>::FromRawPtr(isolate, 0, icu_locale.clone());
date_time_format->set_icu_locale(*managed_locale);
Handle<Managed<icu::SimpleDateFormat>> managed_format =
Managed<icu::SimpleDateFormat>::FromUniquePtr(isolate, 0,
std::move(icu_date_format));
date_time_format->set_icu_simple_date_format(*managed_format);
Handle<Managed<icu::DateIntervalFormat>> managed_interval_format =
Managed<icu::DateIntervalFormat>::FromRawPtr(isolate, 0, nullptr);
date_time_format->set_icu_date_interval_format(*managed_interval_format);
// Now all properties are ready, so we can allocate the result object.
Handle<JSDateTimeFormat> date_time_format = Handle<JSDateTimeFormat>::cast(
isolate->factory()->NewFastOrSlowJSObjectFromMap(map));
DisallowHeapAllocation no_gc;
date_time_format->set_flags(0);
date_time_format->set_hour_cycle(hc);
if (date_style != DateTimeStyle::kUndefined) {
date_time_format->set_date_style(date_style);
}
if (time_style != DateTimeStyle::kUndefined) {
date_time_format->set_time_style(time_style);
}
date_time_format->set_icu_locale(*managed_locale);
date_time_format->set_icu_simple_date_format(*managed_format);
date_time_format->set_icu_date_interval_format(*managed_interval_format);
return date_time_format;
}

View File

@ -32,9 +32,9 @@ namespace internal {
class JSDateTimeFormat : public JSObject {
public:
V8_WARN_UNUSED_RESULT static MaybeHandle<JSDateTimeFormat> Initialize(
Isolate* isolate, Handle<JSDateTimeFormat> date_time_format,
Handle<Object> locales, Handle<Object> options);
V8_WARN_UNUSED_RESULT static MaybeHandle<JSDateTimeFormat> New(
Isolate* isolate, Handle<Map> map, Handle<Object> locales,
Handle<Object> options);
V8_WARN_UNUSED_RESULT static MaybeHandle<JSObject> ResolvedOptions(
Isolate* isolate, Handle<JSDateTimeFormat> date_time_format);

View File

@ -313,10 +313,9 @@ Maybe<bool> ApplyOptionsToTag(Isolate* isolate, Handle<String> tag,
} // namespace
MaybeHandle<JSLocale> JSLocale::Initialize(Isolate* isolate,
Handle<JSLocale> locale,
Handle<String> locale_str,
Handle<JSReceiver> options) {
MaybeHandle<JSLocale> JSLocale::New(Isolate* isolate, Handle<Map> map,
Handle<String> locale_str,
Handle<JSReceiver> options) {
icu::LocaleBuilder builder;
Maybe<bool> maybe_apply =
ApplyOptionsToTag(isolate, locale_str, options, &builder);
@ -341,8 +340,12 @@ MaybeHandle<JSLocale> JSLocale::Initialize(Isolate* isolate,
// 31. Set locale.[[Locale]] to r.[[locale]].
Handle<Managed<icu::Locale>> managed_locale =
Managed<icu::Locale>::FromRawPtr(isolate, 0, icu_locale.clone());
locale->set_icu_locale(*managed_locale);
// Now all properties are ready, so we can allocate the result object.
Handle<JSLocale> locale = Handle<JSLocale>::cast(
isolate->factory()->NewFastOrSlowJSObjectFromMap(map));
DisallowHeapAllocation no_gc;
locale->set_icu_locale(*managed_locale);
return locale;
}

View File

@ -27,12 +27,11 @@ namespace internal {
class JSLocale : public JSObject {
public:
// Initializes locale object with properties derived from input locale string
// Creates locale object with properties derived from input locale string
// and options.
static MaybeHandle<JSLocale> Initialize(Isolate* isolate,
Handle<JSLocale> locale_holder,
Handle<String> locale,
Handle<JSReceiver> options);
static MaybeHandle<JSLocale> New(Isolate* isolate, Handle<Map> map,
Handle<String> locale,
Handle<JSReceiver> options);
static Handle<String> Maximize(Isolate* isolate, String locale);
static Handle<String> Minimize(Isolate* isolate, String locale);

View File

@ -851,10 +851,10 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::UnwrapNumberFormat(
}
// static
MaybeHandle<JSNumberFormat> JSNumberFormat::Initialize(
Isolate* isolate, Handle<JSNumberFormat> number_format,
Handle<Object> locales, Handle<Object> options_obj) {
number_format->set_flags(0);
MaybeHandle<JSNumberFormat> JSNumberFormat::New(Isolate* isolate,
Handle<Map> map,
Handle<Object> locales,
Handle<Object> options_obj) {
Factory* factory = isolate->factory();
// 1. Let requestedLocales be ? CanonicalizeLocaleList(locales).
@ -922,7 +922,6 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::Initialize(
// 9. Set numberFormat.[[Locale]] to r.[[locale]].
Handle<String> locale_str =
isolate->factory()->NewStringFromAsciiChecked(r.locale.c_str());
number_format->set_locale(*locale_str);
// 11. Let dataLocale be r.[[dataLocale]].
@ -1154,24 +1153,6 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::Initialize(
icu_number_formatter = JSNumberFormat::SetDigitOptionsToFormatter(
icu_number_formatter, digit_options);
if (digit_options.minimum_significant_digits > 0) {
// Currenct ECMA 402 spec mandate to record (Min|Max)imumFractionDigits
// uncondictionally while the unified number proposal eventually will only
// record either (Min|Max)imumFractionDigits or
// (Min|Max)imumSignaficantDigits Since LocalizedNumberFormatter can only
// remember one set, and during 2019-1-17 ECMA402 meeting that the committee
// decide not to take a PR to address that prior to the unified number
// proposal, we have to add these two 5 bits int into flags to remember the
// (Min|Max)imumFractionDigits while (Min|Max)imumSignaficantDigits is
// present.
// TODO(ftang) remove the following two lines once we ship
// int-number-format-unified
number_format->set_minimum_fraction_digits(
digit_options.minimum_fraction_digits);
number_format->set_maximum_fraction_digits(
digit_options.maximum_fraction_digits);
}
if (FLAG_harmony_intl_numberformat_unified) {
// Let notation be ? GetOption(options, "notation", "string", « "standard",
// "scientific", "engineering", "compact" », "standard").
@ -1254,6 +1235,32 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::Initialize(
Managed<icu::number::LocalizedNumberFormatter>::FromRawPtr(
isolate, 0,
new icu::number::LocalizedNumberFormatter(icu_number_formatter));
// Now all properties are ready, so we can allocate the result object.
Handle<JSNumberFormat> number_format = Handle<JSNumberFormat>::cast(
isolate->factory()->NewFastOrSlowJSObjectFromMap(map));
DisallowHeapAllocation no_gc;
number_format->set_flags(0);
number_format->set_locale(*locale_str);
if (digit_options.minimum_significant_digits > 0) {
// The current ECMA 402 spec mandates recording (Min|Max)imumFractionDigits
// unconditionally, while the unified number proposal eventually will only
// record either (Min|Max)imumFractionDigits or
// (Min|Max)imumSignificantDigits. Since LocalizedNumberFormatter can only
// remember one set, and during 2019-1-17 ECMA402 meeting the committee
// decided not to take a PR to address that prior to the unified number
// proposal, we have to add these two 5-bit ints into flags to remember the
// (Min|Max)imumFractionDigits while (Min|Max)imumSignificantDigits is
// present.
// TODO(ftang) remove the following two lines once we ship
// int-number-format-unified
number_format->set_minimum_fraction_digits(
digit_options.minimum_fraction_digits);
number_format->set_maximum_fraction_digits(
digit_options.maximum_fraction_digits);
}
number_format->set_icu_number_formatter(*managed_number_formatter);
number_format->set_bound_format(*factory->undefined_value());

View File

@ -34,9 +34,9 @@ namespace internal {
class JSNumberFormat : public JSObject {
public:
// ecma402/#sec-initializenumberformat
V8_WARN_UNUSED_RESULT static MaybeHandle<JSNumberFormat> Initialize(
Isolate* isolate, Handle<JSNumberFormat> number_format,
Handle<Object> locales, Handle<Object> options);
V8_WARN_UNUSED_RESULT static MaybeHandle<JSNumberFormat> New(
Isolate* isolate, Handle<Map> map, Handle<Object> locales,
Handle<Object> options);
// ecma402/#sec-unwrapnumberformat
V8_WARN_UNUSED_RESULT static MaybeHandle<JSNumberFormat> UnwrapNumberFormat(

View File

@ -445,10 +445,6 @@ void JSObject::InitializeBody(Map map, int start_offset,
}
}
Object JSBoundFunction::raw_bound_target_function() const {
return READ_FIELD(*this, kBoundTargetFunctionOffset);
}
ACCESSORS(JSBoundFunction, bound_target_function, JSReceiver,
kBoundTargetFunctionOffset)
ACCESSORS(JSBoundFunction, bound_this, Object, kBoundThisOffset)

View File

@ -919,7 +919,6 @@ class JSIteratorResult : public JSObject {
class JSBoundFunction : public JSObject {
public:
// [bound_target_function]: The wrapped function object.
inline Object raw_bound_target_function() const;
DECL_ACCESSORS(bound_target_function, JSReceiver)
// [bound_this]: The value that is always passed as the this value when

View File

@ -49,21 +49,24 @@ MaybeHandle<JSSegmentIterator> JSSegmentIterator::Create(
// 1. Let iterator be ObjectCreate(%SegmentIteratorPrototype%).
Handle<Map> map = Handle<Map>(
isolate->native_context()->intl_segment_iterator_map(), isolate);
Handle<JSObject> result = isolate->factory()->NewJSObjectFromMap(map);
Handle<Managed<icu::BreakIterator>> managed_break_iterator =
Managed<icu::BreakIterator>::FromRawPtr(isolate, 0, break_iterator);
Managed<icu::UnicodeString> unicode_string =
Intl::SetTextToBreakIterator(isolate, text, break_iterator);
// Now all properties are ready, so we can allocate the result object.
Handle<JSObject> result = isolate->factory()->NewJSObjectFromMap(map);
DisallowHeapAllocation no_gc;
Handle<JSSegmentIterator> segment_iterator =
Handle<JSSegmentIterator>::cast(result);
segment_iterator->set_flags(0);
segment_iterator->set_granularity(granularity);
// 2. Let iterator.[[SegmentIteratorSegmenter]] be segmenter.
Handle<Managed<icu::BreakIterator>> managed_break_iterator =
Managed<icu::BreakIterator>::FromRawPtr(isolate, 0, break_iterator);
segment_iterator->set_icu_break_iterator(*managed_break_iterator);
// 3. Let iterator.[[SegmentIteratorString]] be string.
Managed<icu::UnicodeString> unicode_string =
Intl::SetTextToBreakIterator(isolate, text, break_iterator);
segment_iterator->set_unicode_string(unicode_string);
// 4. Let iterator.[[SegmentIteratorIndex]] be 0.

View File

@ -65,6 +65,7 @@ RUNTIME_FUNCTION(Runtime_CreateJSGeneratorObject) {
generator->set_context(isolate->context());
generator->set_receiver(*receiver);
generator->set_parameters_and_registers(*parameters_and_registers);
generator->set_resume_mode(JSGeneratorObject::ResumeMode::kNext);
generator->set_continuation(JSGeneratorObject::kGeneratorExecuting);
if (generator->IsJSAsyncGeneratorObject()) {
Handle<JSAsyncGeneratorObject>::cast(generator)->set_is_awaiting(0);

View File

@ -3403,16 +3403,6 @@ void GenerateClassFieldVerifier(const std::string& class_name,
if (!type_check.empty()) type_check += " || ";
type_check += strong_value + ".Is" + runtime_type + "()";
}
// Many subtypes of JSObject can be verified in partially-initialized states
// where their fields are all undefined. We explicitly allow that here. For
// any such fields that should never be undefined, we can include extra code
// in the custom verifier functions for them.
// TODO(1240798): If Factory::InitializeJSObjectFromMap is updated to use
// correct initial values based on the type of the field, then make this
// check stricter too.
if (class_type.IsSubtypeOf(TypeOracle::GetJSObjectType())) {
type_check += " || " + strong_value + ".IsUndefined(isolate)";
}
cc_contents << " CHECK(" << type_check << ");\n";
}
cc_contents << " }\n";

View File

@ -789,19 +789,21 @@ Handle<WasmTableObject> WasmTableObject::New(Isolate* isolate,
backing_store->set(i, null);
}
Handle<JSFunction> table_ctor(
isolate->native_context()->wasm_table_constructor(), isolate);
auto table_obj = Handle<WasmTableObject>::cast(
isolate->factory()->NewJSObject(table_ctor));
table_obj->set_raw_type(static_cast<int>(type));
table_obj->set_entries(*backing_store);
Handle<Object> max;
if (has_maximum) {
max = isolate->factory()->NewNumberFromUint(maximum);
} else {
max = isolate->factory()->undefined_value();
}
Handle<JSFunction> table_ctor(
isolate->native_context()->wasm_table_constructor(), isolate);
auto table_obj = Handle<WasmTableObject>::cast(
isolate->factory()->NewJSObject(table_ctor));
DisallowHeapAllocation no_gc;
table_obj->set_raw_type(static_cast<int>(type));
table_obj->set_entries(*backing_store);
table_obj->set_maximum_length(*max);
table_obj->set_dispatch_tables(ReadOnlyRoots(isolate).empty_fixed_array());
@ -1419,6 +1421,15 @@ MaybeHandle<WasmGlobalObject> WasmGlobalObject::New(
isolate->native_context()->wasm_global_constructor(), isolate);
auto global_obj = Handle<WasmGlobalObject>::cast(
isolate->factory()->NewJSObject(global_ctor));
{
// Disallow GC until all fields have acceptable types.
DisallowHeapAllocation no_gc;
global_obj->set_flags(0);
global_obj->set_type(type);
global_obj->set_offset(offset);
global_obj->set_is_mutable(is_mutable);
}
if (wasm::ValueTypes::IsReferenceType(type)) {
DCHECK(maybe_untagged_buffer.is_null());
@ -1451,10 +1462,6 @@ MaybeHandle<WasmGlobalObject> WasmGlobalObject::New(
global_obj->set_untagged_buffer(*untagged_buffer);
}
global_obj->set_flags(0);
global_obj->set_type(type);
global_obj->set_offset(offset);
global_obj->set_is_mutable(is_mutable);
return global_obj;
}

View File

@ -1654,6 +1654,15 @@ TEST(AllocateJSObjectFromMap) {
Node* result = m.AllocateJSObjectFromMap(map, properties, elements);
CodeStubAssembler::Label done(&m);
m.GotoIfNot(m.IsJSArrayMap(map), &done);
// JS array verification requires the length field to be set.
m.StoreObjectFieldNoWriteBarrier(result, JSArray::kLengthOffset,
m.SmiConstant(0));
m.Goto(&done);
m.Bind(&done);
m.Return(result);
}