summaryrefslogtreecommitdiff
path: root/deps/v8/src/objects/objects.cc
diff options
context:
space:
mode:
authorMatheus Marchini <mmarchini@netflix.com>2020-03-05 10:49:19 -0800
committerMatheus Marchini <mmarchini@netflix.com>2020-03-18 16:23:22 -0700
commit2883c855e0105b51e5c8020d21458af109ffe3d4 (patch)
tree26777aad0a398e9f7755c8b65ac76827fe352a81 /deps/v8/src/objects/objects.cc
parent5f0af2af2a67216e00fe07ccda11e889d14abfcd (diff)
downloadnode-new-2883c855e0105b51e5c8020d21458af109ffe3d4.tar.gz
deps: update V8 to 8.1.307.20
PR-URL: https://github.com/nodejs/node/pull/32116 Reviewed-By: Michaƫl Zasso <targos@protonmail.com> Reviewed-By: Jiawen Geng <technicalcute@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Diffstat (limited to 'deps/v8/src/objects/objects.cc')
-rw-r--r--deps/v8/src/objects/objects.cc861
1 files changed, 432 insertions, 429 deletions
diff --git a/deps/v8/src/objects/objects.cc b/deps/v8/src/objects/objects.cc
index 1328b517e8..cf1a3dcc20 100644
--- a/deps/v8/src/objects/objects.cc
+++ b/deps/v8/src/objects/objects.cc
@@ -66,6 +66,7 @@
#include "src/objects/map-updater.h"
#include "src/objects/objects-body-descriptors-inl.h"
#include "src/objects/property-details.h"
+#include "src/roots/roots.h"
#include "src/utils/identity-map.h"
#ifdef V8_INTL_SUPPORT
#include "src/objects/js-break-iterator.h"
@@ -97,6 +98,7 @@
#include "src/objects/microtask-inl.h"
#include "src/objects/module-inl.h"
#include "src/objects/promise-inl.h"
+#include "src/objects/property-descriptor-object-inl.h"
#include "src/objects/property-descriptor.h"
#include "src/objects/prototype.h"
#include "src/objects/slots-atomic-inl.h"
@@ -404,15 +406,13 @@ Handle<String> AsStringOrEmpty(Isolate* isolate, Handle<Object> object) {
}
Handle<String> NoSideEffectsErrorToString(Isolate* isolate,
- Handle<Object> input) {
- Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(input);
-
+ Handle<JSReceiver> error) {
Handle<Name> name_key = isolate->factory()->name_string();
- Handle<Object> name = JSReceiver::GetDataProperty(receiver, name_key);
+ Handle<Object> name = JSReceiver::GetDataProperty(error, name_key);
Handle<String> name_str = AsStringOrEmpty(isolate, name);
Handle<Name> msg_key = isolate->factory()->message_string();
- Handle<Object> msg = JSReceiver::GetDataProperty(receiver, msg_key);
+ Handle<Object> msg = JSReceiver::GetDataProperty(error, msg_key);
Handle<String> msg_str = AsStringOrEmpty(isolate, msg);
if (name_str->length() == 0) return msg_str;
@@ -421,7 +421,12 @@ Handle<String> NoSideEffectsErrorToString(Isolate* isolate,
IncrementalStringBuilder builder(isolate);
builder.AppendString(name_str);
builder.AppendCString(": ");
- builder.AppendString(msg_str);
+
+ if (builder.Length() + msg_str->length() <= String::kMaxLength) {
+ builder.AppendString(msg_str);
+ } else {
+ builder.AppendCString("<a very large string>");
+ }
return builder.Finish().ToHandleChecked();
}
@@ -469,13 +474,14 @@ Handle<String> Object::NoSideEffectsToString(Isolate* isolate,
Handle<Symbol> symbol = Handle<Symbol>::cast(input);
if (symbol->is_private_name()) {
- return Handle<String>(String::cast(symbol->name()), isolate);
+ return Handle<String>(String::cast(symbol->description()), isolate);
}
IncrementalStringBuilder builder(isolate);
builder.AppendCString("Symbol(");
- if (symbol->name().IsString()) {
- builder.AppendString(handle(String::cast(symbol->name()), isolate));
+ if (symbol->description().IsString()) {
+ builder.AppendString(
+ handle(String::cast(symbol->description()), isolate));
}
builder.AppendCharacter(')');
@@ -491,7 +497,8 @@ Handle<String> Object::NoSideEffectsToString(Isolate* isolate,
// When internally formatting error objects, use a side-effects-free
// version of Error.prototype.toString independent of the actually
// installed toString method.
- return NoSideEffectsErrorToString(isolate, input);
+ return NoSideEffectsErrorToString(isolate,
+ Handle<JSReceiver>::cast(input));
} else if (*to_string == *isolate->object_to_string()) {
Handle<Object> ctor = JSReceiver::GetDataProperty(
receiver, isolate->factory()->constructor_string());
@@ -560,7 +567,7 @@ MaybeHandle<Object> Object::ConvertToLength(Isolate* isolate,
}
double len = DoubleToInteger(input->Number());
if (len <= 0.0) {
- return handle(Smi::kZero, isolate);
+ return handle(Smi::zero(), isolate);
} else if (len >= kMaxSafeInteger) {
len = kMaxSafeInteger;
}
@@ -571,7 +578,7 @@ MaybeHandle<Object> Object::ConvertToLength(Isolate* isolate,
MaybeHandle<Object> Object::ConvertToIndex(Isolate* isolate,
Handle<Object> input,
MessageTemplate error_index) {
- if (input->IsUndefined(isolate)) return handle(Smi::kZero, isolate);
+ if (input->IsUndefined(isolate)) return handle(Smi::zero(), isolate);
ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ToNumber(isolate, input), Object);
if (input->IsSmi() && Smi::ToInt(*input) >= 0) return input;
double len = DoubleToInteger(input->Number()) + 0.0;
@@ -964,6 +971,8 @@ MaybeHandle<FixedArray> CreateListFromArrayLikeFastPath(
length > static_cast<size_t>(FixedArray::kMaxLength)) {
return MaybeHandle<FixedArray>();
}
+ STATIC_ASSERT(FixedArray::kMaxLength <=
+ std::numeric_limits<uint32_t>::max());
return array->GetElementsAccessor()->CreateListFromArrayLike(
isolate, array, static_cast<uint32_t>(length));
}
@@ -1052,7 +1061,7 @@ MaybeHandle<Object> Object::GetLengthFromArrayLike(Isolate* isolate,
// static
MaybeHandle<Object> Object::GetProperty(LookupIterator* it,
- OnNonExistent on_non_existent) {
+ bool is_global_reference) {
for (; it->IsFound(); it->Next()) {
switch (it->state()) {
case LookupIterator::NOT_FOUND:
@@ -1067,10 +1076,19 @@ MaybeHandle<Object> Object::GetProperty(LookupIterator* it,
receiver = handle(JSGlobalObject::cast(*receiver).global_proxy(),
it->isolate());
}
+ if (is_global_reference) {
+ Maybe<bool> maybe = JSProxy::HasProperty(
+ it->isolate(), it->GetHolder<JSProxy>(), it->GetName());
+ if (maybe.IsNothing()) return MaybeHandle<Object>();
+ if (!maybe.FromJust()) {
+ it->NotFound();
+ return it->isolate()->factory()->undefined_value();
+ }
+ }
MaybeHandle<Object> result =
JSProxy::GetProperty(it->isolate(), it->GetHolder<JSProxy>(),
it->GetName(), receiver, &was_found);
- if (!was_found) it->NotFound();
+ if (!was_found && !is_global_reference) it->NotFound();
return result;
}
case LookupIterator::INTERCEPTOR: {
@@ -1094,11 +1112,6 @@ MaybeHandle<Object> Object::GetProperty(LookupIterator* it,
}
}
- if (on_non_existent == OnNonExistent::kThrowReferenceError) {
- THROW_NEW_ERROR(it->isolate(),
- NewReferenceError(MessageTemplate::kNotDefined, it->name()),
- Object);
- }
return it->isolate()->factory()->undefined_value();
}
@@ -1133,8 +1146,8 @@ MaybeHandle<Object> JSProxy::GetProperty(Isolate* isolate,
// 7. If trap is undefined, then
if (trap->IsUndefined(isolate)) {
// 7.a Return target.[[Get]](P, Receiver).
- LookupIterator it =
- LookupIterator::PropertyOrElement(isolate, receiver, name, target);
+ LookupIterator::Key key(isolate, name);
+ LookupIterator it(isolate, receiver, key, target);
MaybeHandle<Object> result = Object::GetProperty(&it);
*was_found = it.IsFound();
return result;
@@ -1236,10 +1249,7 @@ bool Object::ToInt32(int32_t* value) {
return false;
}
-// static constexpr object declarations need a definition to make the
-// compiler happy.
-constexpr Object Smi::kZero;
-V8_EXPORT_PRIVATE constexpr Object SharedFunctionInfo::kNoSharedNameSentinel;
+V8_EXPORT_PRIVATE constexpr Smi SharedFunctionInfo::kNoSharedNameSentinel;
Handle<SharedFunctionInfo> FunctionTemplateInfo::GetOrCreateSharedFunctionInfo(
Isolate* isolate, Handle<FunctionTemplateInfo> info,
@@ -1315,7 +1325,7 @@ FunctionTemplateRareData FunctionTemplateInfo::AllocateFunctionTemplateRareData(
Handle<TemplateList> TemplateList::New(Isolate* isolate, int size) {
Handle<FixedArray> list =
isolate->factory()->NewFixedArray(kLengthIndex + size);
- list->set(kLengthIndex, Smi::kZero);
+ list->set(kLengthIndex, Smi::zero());
return Handle<TemplateList>::cast(list);
}
@@ -2075,7 +2085,7 @@ void HeapObject::HeapObjectShortPrint(std::ostream& os) { // NOLINT
}
case HEAP_NUMBER_TYPE: {
os << "<HeapNumber ";
- HeapNumber::cast(*this).HeapNumberPrint(os);
+ HeapNumber::cast(*this).HeapNumberShortPrint(os);
os << ">";
break;
}
@@ -2137,11 +2147,6 @@ void Tuple2::BriefPrintDetails(std::ostream& os) {
os << " " << Brief(value1()) << ", " << Brief(value2());
}
-void Tuple3::BriefPrintDetails(std::ostream& os) {
- os << " " << Brief(value1()) << ", " << Brief(value2()) << ", "
- << Brief(value3());
-}
-
void ClassPositions::BriefPrintDetails(std::ostream& os) {
os << " " << start() << ", " << end();
}
@@ -2183,14 +2188,14 @@ int HeapObject::SizeFromMap(Map map) const {
if (instance_size != kVariableSizeSentinel) return instance_size;
// Only inline the most frequent cases.
InstanceType instance_type = map.instance_type();
- if (IsInRange(instance_type, FIRST_FIXED_ARRAY_TYPE, LAST_FIXED_ARRAY_TYPE)) {
+ if (base::IsInRange(instance_type, FIRST_FIXED_ARRAY_TYPE,
+ LAST_FIXED_ARRAY_TYPE)) {
return FixedArray::SizeFor(
FixedArray::unchecked_cast(*this).synchronized_length());
}
- if (IsInRange(instance_type, FIRST_CONTEXT_TYPE, LAST_CONTEXT_TYPE)) {
+ if (base::IsInRange(instance_type, FIRST_CONTEXT_TYPE, LAST_CONTEXT_TYPE)) {
if (instance_type == NATIVE_CONTEXT_TYPE) return NativeContext::kSize;
- return Context::SizeFor(
- Context::unchecked_cast(*this).synchronized_length());
+ return Context::SizeFor(Context::unchecked_cast(*this).length());
}
if (instance_type == ONE_BYTE_STRING_TYPE ||
instance_type == ONE_BYTE_INTERNALIZED_STRING_TYPE) {
@@ -2229,8 +2234,8 @@ int HeapObject::SizeFromMap(Map map) const {
return DescriptorArray::SizeFor(
DescriptorArray::unchecked_cast(*this).number_of_all_descriptors());
}
- if (IsInRange(instance_type, FIRST_WEAK_FIXED_ARRAY_TYPE,
- LAST_WEAK_FIXED_ARRAY_TYPE)) {
+ if (base::IsInRange(instance_type, FIRST_WEAK_FIXED_ARRAY_TYPE,
+ LAST_WEAK_FIXED_ARRAY_TYPE)) {
return WeakFixedArray::SizeFor(
WeakFixedArray::unchecked_cast(*this).synchronized_length());
}
@@ -2761,10 +2766,10 @@ Maybe<bool> Object::AddDataProperty(LookupIterator* it, Handle<Object> value,
NewTypeError(MessageTemplate::kObjectNotExtensible, it->GetName()));
}
- if (it->IsElement()) {
+ if (it->IsElement(*receiver)) {
if (receiver->IsJSArray()) {
Handle<JSArray> array = Handle<JSArray>::cast(receiver);
- if (JSArray::WouldChangeReadOnlyLength(array, it->index())) {
+ if (JSArray::WouldChangeReadOnlyLength(array, it->array_index())) {
RETURN_FAILURE(isolate, GetShouldThrow(it->isolate(), should_throw),
NewTypeError(MessageTemplate::kStrictReadOnlyProperty,
isolate->factory()->length_string(),
@@ -2773,7 +2778,8 @@ Maybe<bool> Object::AddDataProperty(LookupIterator* it, Handle<Object> value,
}
Handle<JSObject> receiver_obj = Handle<JSObject>::cast(receiver);
- JSObject::AddDataElement(receiver_obj, it->index(), value, attributes);
+ JSObject::AddDataElement(receiver_obj, it->array_index(), value,
+ attributes);
JSObject::ValidateElements(*receiver_obj);
return Just(true);
} else {
@@ -2975,8 +2981,8 @@ Maybe<bool> JSProxy::SetProperty(Handle<JSProxy> proxy, Handle<Name> name,
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
if (trap->IsUndefined(isolate)) {
- LookupIterator it =
- LookupIterator::PropertyOrElement(isolate, receiver, name, target);
+ LookupIterator::Key key(isolate, name);
+ LookupIterator it(isolate, receiver, key, target);
return Object::SetSuperProperty(&it, value, StoreOrigin::kMaybeKeyed,
should_throw);
@@ -3468,7 +3474,7 @@ Maybe<bool> JSProxy::SetPrivateSymbol(Isolate* isolate, Handle<JSProxy> proxy,
? desc->value()
: Handle<Object>::cast(isolate->factory()->undefined_value());
- LookupIterator it(proxy, private_name, proxy);
+ LookupIterator it(isolate, proxy, private_name, proxy);
if (it.IsFound()) {
DCHECK_EQ(LookupIterator::DATA, it.state());
@@ -3965,6 +3971,65 @@ Handle<WeakArrayList> WeakArrayList::AddToEnd(Isolate* isolate,
return array;
}
+// static
+Handle<WeakArrayList> WeakArrayList::Append(Isolate* isolate,
+ Handle<WeakArrayList> array,
+ const MaybeObjectHandle& value,
+ AllocationType allocation) {
+ int length = array->length();
+
+ if (length < array->capacity()) {
+ array->Set(length, *value);
+ array->set_length(length + 1);
+ return array;
+ }
+
+ // Not enough space in the array left, either grow, shrink or
+ // compact the array.
+ int new_length = array->CountLiveElements() + 1;
+
+ bool shrink = new_length < length / 4;
+ bool grow = 3 * (length / 4) < new_length;
+
+ if (shrink || grow) {
+ // Grow or shrink array and compact out-of-place.
+ int new_capacity = CapacityForLength(new_length);
+ array = isolate->factory()->CompactWeakArrayList(array, new_capacity,
+ allocation);
+
+ } else {
+ // Perform compaction in the current array.
+ array->Compact(isolate);
+ }
+
+ // Now append value to the array, there should always be enough space now.
+ DCHECK_LT(array->length(), array->capacity());
+
+ // Reload length, allocation might have killed some weak refs.
+ int index = array->length();
+ array->Set(index, *value);
+ array->set_length(index + 1);
+ return array;
+}
+
+void WeakArrayList::Compact(Isolate* isolate) {
+ int length = this->length();
+ int new_length = 0;
+
+ for (int i = 0; i < length; i++) {
+ MaybeObject value = Get(isolate, i);
+
+ if (!value->IsCleared()) {
+ if (new_length != i) {
+ Set(new_length, value);
+ }
+ ++new_length;
+ }
+ }
+
+ set_length(new_length);
+}
+
bool WeakArrayList::IsFull() { return length() == capacity(); }
// static
@@ -3974,9 +4039,7 @@ Handle<WeakArrayList> WeakArrayList::EnsureSpace(Isolate* isolate,
AllocationType allocation) {
int capacity = array->capacity();
if (capacity < length) {
- int new_capacity = length;
- new_capacity = new_capacity + Max(new_capacity / 2, 2);
- int grow_by = new_capacity - capacity;
+ int grow_by = CapacityForLength(length) - capacity;
array = isolate->factory()->CopyWeakArrayListAndGrow(array, grow_by,
allocation);
}
@@ -3993,6 +4056,16 @@ int WeakArrayList::CountLiveWeakReferences() const {
return live_weak_references;
}
+int WeakArrayList::CountLiveElements() const {
+ int non_cleared_objects = 0;
+ for (int i = 0; i < length(); i++) {
+ if (!Get(i)->IsCleared()) {
+ ++non_cleared_objects;
+ }
+ }
+ return non_cleared_objects;
+}
+
bool WeakArrayList::RemoveOne(const MaybeObjectHandle& value) {
if (length() == 0) return false;
// Optimize for the most recently added element to be removed again.
@@ -4109,12 +4182,22 @@ WeakArrayList PrototypeUsers::Compact(Handle<WeakArrayList> array, Heap* heap,
return *new_array;
}
+Handle<RegExpMatchInfo> RegExpMatchInfo::New(Isolate* isolate,
+ int capture_count) {
+ Handle<RegExpMatchInfo> match_info = isolate->factory()->NewRegExpMatchInfo();
+ return ReserveCaptures(isolate, match_info, capture_count);
+}
+
Handle<RegExpMatchInfo> RegExpMatchInfo::ReserveCaptures(
Isolate* isolate, Handle<RegExpMatchInfo> match_info, int capture_count) {
DCHECK_GE(match_info->length(), kLastMatchOverhead);
- const int required_length = kFirstCaptureIndex + capture_count;
- return Handle<RegExpMatchInfo>::cast(
+
+ int capture_register_count = (capture_count + 1) * 2;
+ const int required_length = kFirstCaptureIndex + capture_register_count;
+ Handle<RegExpMatchInfo> result = Handle<RegExpMatchInfo>::cast(
EnsureSpaceInFixedArray(isolate, match_info, required_length));
+ result->SetNumberOfCaptureRegisters(capture_register_count);
+ return result;
}
// static
@@ -4142,6 +4225,11 @@ Handle<FrameArray> FrameArray::AppendJSFrame(Handle<FrameArray> in,
Handle<FrameArray> FrameArray::AppendWasmFrame(
Handle<FrameArray> in, Handle<WasmInstanceObject> wasm_instance,
int wasm_function_index, wasm::WasmCode* code, int offset, int flags) {
+ // This must be either a compiled or interpreted wasm frame, or an asm.js
+ // frame (which is always compiled).
+ DCHECK_EQ(1, ((flags & kIsWasmInterpretedFrame) != 0) +
+ ((flags & kIsWasmCompiledFrame) != 0) +
+ ((flags & kIsAsmJsWasmFrame) != 0));
Isolate* isolate = wasm_instance->GetIsolate();
const int frame_count = in->FrameCount();
const int new_length = LengthFor(frame_count + 1);
@@ -4344,7 +4432,8 @@ bool DescriptorArray::IsEqualTo(DescriptorArray other) {
MaybeHandle<String> Name::ToFunctionName(Isolate* isolate, Handle<Name> name) {
if (name->IsString()) return Handle<String>::cast(name);
// ES6 section 9.2.11 SetFunctionName, step 4.
- Handle<Object> description(Handle<Symbol>::cast(name)->name(), isolate);
+ Handle<Object> description(Handle<Symbol>::cast(name)->description(),
+ isolate);
if (description->IsUndefined(isolate)) {
return isolate->factory()->empty_string();
}
@@ -4639,7 +4728,7 @@ bool Script::GetPositionInfo(Handle<Script> script, int position,
return script->GetPositionInfo(position, info, offset_flag);
}
-bool Script::IsUserJavaScript() { return type() == Script::TYPE_NORMAL; }
+bool Script::IsUserJavaScript() const { return type() == Script::TYPE_NORMAL; }
bool Script::ContainsAsmModule() {
DisallowHeapAllocation no_gc;
@@ -4678,34 +4767,20 @@ bool GetPositionInfoSlow(const Script script, int position,
}
} // namespace
-#define SMI_VALUE(x) (Smi::ToInt(x))
bool Script::GetPositionInfo(int position, PositionInfo* info,
OffsetFlag offset_flag) const {
DisallowHeapAllocation no_allocation;
- // For wasm, we do not rely on the line_ends array, but do the translation
- // directly.
+ // For wasm, we use the byte offset as the column.
if (type() == Script::TYPE_WASM) {
DCHECK_LE(0, position);
wasm::NativeModule* native_module = wasm_native_module();
const wasm::WasmModule* module = native_module->module();
- if (source_mapping_url().IsString()) {
- if (module->functions.size() == 0) return false;
- info->line = 0;
- info->column = position;
- info->line_start = module->functions[0].code.offset();
- info->line_end = module->functions.back().code.end_offset();
- return true;
- }
- int func_index = GetContainingWasmFunction(module, position);
- if (func_index < 0) return false;
-
- const wasm::WasmFunction& function = module->functions[func_index];
-
- info->line = func_index;
- info->column = position - function.code.offset();
- info->line_start = function.code.offset();
- info->line_end = function.code.end_offset();
+ if (module->functions.size() == 0) return false;
+ info->line = 0;
+ info->column = position;
+ info->line_start = module->functions[0].code.offset();
+ info->line_end = module->functions.back().code.end_offset();
return true;
}
@@ -4723,12 +4798,12 @@ bool Script::GetPositionInfo(int position, PositionInfo* info,
// passed, and positions beyond the end of the script return as failure.
if (position < 0) {
position = 0;
- } else if (position > SMI_VALUE(ends.get(ends_len - 1))) {
+ } else if (position > Smi::ToInt(ends.get(ends_len - 1))) {
return false;
}
// Determine line number by doing a binary search on the line ends array.
- if (SMI_VALUE(ends.get(0)) >= position) {
+ if (Smi::ToInt(ends.get(0)) >= position) {
info->line = 0;
info->line_start = 0;
info->column = position;
@@ -4739,23 +4814,23 @@ bool Script::GetPositionInfo(int position, PositionInfo* info,
while (right > 0) {
DCHECK_LE(left, right);
const int mid = (left + right) / 2;
- if (position > SMI_VALUE(ends.get(mid))) {
+ if (position > Smi::ToInt(ends.get(mid))) {
left = mid + 1;
- } else if (position <= SMI_VALUE(ends.get(mid - 1))) {
+ } else if (position <= Smi::ToInt(ends.get(mid - 1))) {
right = mid - 1;
} else {
info->line = mid;
break;
}
}
- DCHECK(SMI_VALUE(ends.get(info->line)) >= position &&
- SMI_VALUE(ends.get(info->line - 1)) < position);
- info->line_start = SMI_VALUE(ends.get(info->line - 1)) + 1;
+ DCHECK(Smi::ToInt(ends.get(info->line)) >= position &&
+ Smi::ToInt(ends.get(info->line - 1)) < position);
+ info->line_start = Smi::ToInt(ends.get(info->line - 1)) + 1;
info->column = position - info->line_start;
}
// Line end is position of the linebreak character.
- info->line_end = SMI_VALUE(ends.get(info->line));
+ info->line_end = Smi::ToInt(ends.get(info->line));
if (info->line_end > 0) {
DCHECK(source().IsString());
String src = String::cast(source());
@@ -4776,7 +4851,6 @@ bool Script::GetPositionInfo(int position, PositionInfo* info,
return true;
}
-#undef SMI_VALUE
int Script::GetColumnNumber(Handle<Script> script, int code_pos) {
PositionInfo info;
@@ -4825,37 +4899,6 @@ MaybeHandle<SharedFunctionInfo> Script::FindSharedFunctionInfo(
return handle(SharedFunctionInfo::cast(heap_object), isolate);
}
-std::unique_ptr<v8::tracing::TracedValue> Script::ToTracedValue() {
- auto value = v8::tracing::TracedValue::Create();
- if (name().IsString()) {
- value->SetString("name", String::cast(name()).ToCString());
- }
- value->SetInteger("lineOffset", line_offset());
- value->SetInteger("columnOffset", column_offset());
- if (source_mapping_url().IsString()) {
- value->SetString("sourceMappingURL",
- String::cast(source_mapping_url()).ToCString());
- }
- if (source().IsString()) {
- value->SetString("source", String::cast(source()).ToCString());
- }
- return value;
-}
-
-// static
-const char* Script::kTraceScope = "v8::internal::Script";
-
-uint64_t Script::TraceID() const { return id(); }
-
-std::unique_ptr<v8::tracing::TracedValue> Script::TraceIDRef() const {
- auto value = v8::tracing::TracedValue::Create();
- std::ostringstream ost;
- ost << "0x" << std::hex << TraceID();
- value->SetString("id_ref", ost.str());
- value->SetString("scope", kTraceScope);
- return value;
-}
-
Script::Iterator::Iterator(Isolate* isolate)
: iterator_(isolate->heap()->script_list()) {}
@@ -4876,59 +4919,42 @@ uint32_t SharedFunctionInfo::Hash() {
return static_cast<uint32_t>(base::hash_combine(start_pos, script_id));
}
-std::unique_ptr<v8::tracing::TracedValue> SharedFunctionInfo::ToTracedValue(
- FunctionLiteral* literal) {
- auto value = v8::tracing::TracedValue::Create();
- if (HasSharedName()) {
- value->SetString("name", Name().ToCString());
- }
- if (HasInferredName()) {
- value->SetString("inferredName", inferred_name().ToCString());
- }
- if (is_toplevel()) {
- value->SetBoolean("isToplevel", true);
- }
- value->SetInteger("formalParameterCount", internal_formal_parameter_count());
- value->SetString("languageMode", LanguageMode2String(language_mode()));
- value->SetString("kind", FunctionKind2String(kind()));
- if (script().IsScript()) {
- value->SetValue("script", Script::cast(script()).TraceIDRef());
- value->BeginDictionary("sourcePosition");
- Script::PositionInfo info;
- // We get the start position from the {literal} here, because the
- // SharedFunctionInfo itself might not have a way to get to the
- // start position early on (currently that's the case when it's
- // marked for eager compilation).
- if (Script::cast(script()).GetPositionInfo(literal->start_position(), &info,
- Script::WITH_OFFSET)) {
- value->SetInteger("line", info.line + 1);
- value->SetInteger("column", info.column + 1);
- }
- value->EndDictionary();
- }
- return value;
-}
+void SharedFunctionInfo::Init(ReadOnlyRoots ro_roots, int unique_id) {
+ DisallowHeapAllocation no_allocation;
-// static
-const char* SharedFunctionInfo::kTraceScope =
- "v8::internal::SharedFunctionInfo";
+ // Set the function data to the "illegal" builtin. Ideally we'd use some sort
+ // of "uninitialized" marker here, but it's cheaper to use a valid buitin and
+ // avoid having to do uninitialized checks elsewhere.
+ set_builtin_id(Builtins::kIllegal);
+
+ // Set the name to the no-name sentinel, this can be updated later.
+ set_name_or_scope_info(SharedFunctionInfo::kNoSharedNameSentinel,
+ SKIP_WRITE_BARRIER);
+
+ // Generally functions won't have feedback, unless they have been created
+ // from a FunctionLiteral. Those can just reset this field to keep the
+ // SharedFunctionInfo in a consistent state.
+ set_raw_outer_scope_info_or_feedback_metadata(ro_roots.the_hole_value(),
+ SKIP_WRITE_BARRIER);
+ set_script_or_debug_info(ro_roots.undefined_value(), SKIP_WRITE_BARRIER);
+ set_function_literal_id(kFunctionLiteralIdInvalid);
+#if V8_SFI_HAS_UNIQUE_ID
+ set_unique_id(unique_id);
+#endif
-uint64_t SharedFunctionInfo::TraceID(FunctionLiteral* literal) const {
- int literal_id =
- literal ? literal->function_literal_id() : function_literal_id();
- Script script = Script::cast(this->script());
- return (static_cast<uint64_t>(script.id() + 1) << 32) |
- (static_cast<uint64_t>(literal_id));
-}
+ // Set integer fields (smi or int, depending on the architecture).
+ set_length(0);
+ set_internal_formal_parameter_count(0);
+ set_expected_nof_properties(0);
+ set_raw_function_token_offset(0);
-std::unique_ptr<v8::tracing::TracedValue> SharedFunctionInfo::TraceIDRef()
- const {
- auto value = v8::tracing::TracedValue::Create();
- std::ostringstream ost;
- ost << "0x" << std::hex << TraceID();
- value->SetString("id_ref", ost.str());
- value->SetString("scope", kTraceScope);
- return value;
+ // All flags default to false or 0, except ConstructAsBuiltinBit just because
+ // we're using the kIllegal builtin.
+ set_flags(ConstructAsBuiltinBit::encode(true));
+
+ UpdateFunctionMapIndex();
+
+ clear_padding();
}
Code SharedFunctionInfo::GetCode() const {
@@ -5018,59 +5044,58 @@ void SharedFunctionInfo::ScriptIterator::Reset(Isolate* isolate,
index_ = 0;
}
-void SharedFunctionInfo::SetScript(Handle<SharedFunctionInfo> shared,
- Handle<HeapObject> script_object,
+void SharedFunctionInfo::SetScript(ReadOnlyRoots roots,
+ HeapObject script_object,
int function_literal_id,
bool reset_preparsed_scope_data) {
- if (shared->script() == *script_object) return;
- Isolate* isolate = shared->GetIsolate();
+ DisallowHeapAllocation no_gc;
+
+ if (script() == script_object) return;
- if (reset_preparsed_scope_data &&
- shared->HasUncompiledDataWithPreparseData()) {
- shared->ClearPreparseData();
+ if (reset_preparsed_scope_data && HasUncompiledDataWithPreparseData()) {
+ ClearPreparseData();
}
// Add shared function info to new script's list. If a collection occurs,
// the shared function info may be temporarily in two lists.
// This is okay because the gc-time processing of these lists can tolerate
// duplicates.
- if (script_object->IsScript()) {
- DCHECK(!shared->script().IsScript());
- Handle<Script> script = Handle<Script>::cast(script_object);
- Handle<WeakFixedArray> list =
- handle(script->shared_function_infos(), isolate);
+ if (script_object.IsScript()) {
+ DCHECK(!script().IsScript());
+ Script script = Script::cast(script_object);
+ WeakFixedArray list = script.shared_function_infos();
#ifdef DEBUG
- DCHECK_LT(function_literal_id, list->length());
- MaybeObject maybe_object = list->Get(function_literal_id);
+ DCHECK_LT(function_literal_id, list.length());
+ MaybeObject maybe_object = list.Get(function_literal_id);
HeapObject heap_object;
if (maybe_object->GetHeapObjectIfWeak(&heap_object)) {
- DCHECK_EQ(heap_object, *shared);
+ DCHECK_EQ(heap_object, *this);
}
#endif
- list->Set(function_literal_id, HeapObjectReference::Weak(*shared));
+ list.Set(function_literal_id, HeapObjectReference::Weak(*this));
} else {
- DCHECK(shared->script().IsScript());
+ DCHECK(script().IsScript());
// Remove shared function info from old script's list.
- Script old_script = Script::cast(shared->script());
+ Script old_script = Script::cast(script());
// Due to liveedit, it might happen that the old_script doesn't know
// about the SharedFunctionInfo, so we have to guard against that.
- Handle<WeakFixedArray> infos(old_script.shared_function_infos(), isolate);
- if (function_literal_id < infos->length()) {
+ WeakFixedArray infos = old_script.shared_function_infos();
+ if (function_literal_id < infos.length()) {
MaybeObject raw =
old_script.shared_function_infos().Get(function_literal_id);
HeapObject heap_object;
- if (raw->GetHeapObjectIfWeak(&heap_object) && heap_object == *shared) {
+ if (raw->GetHeapObjectIfWeak(&heap_object) && heap_object == *this) {
old_script.shared_function_infos().Set(
- function_literal_id, HeapObjectReference::Strong(
- ReadOnlyRoots(isolate).undefined_value()));
+ function_literal_id,
+ HeapObjectReference::Strong(roots.undefined_value()));
}
}
}
// Finally set new script.
- shared->set_script(*script_object);
+ set_script(script_object);
}
bool SharedFunctionInfo::HasBreakInfo() const {
@@ -5215,64 +5240,34 @@ Handle<Object> SharedFunctionInfo::GetSourceCodeHarmony(
return builder.Finish().ToHandleChecked();
}
-namespace {
-void TraceInlining(SharedFunctionInfo shared, const char* msg) {
- if (FLAG_trace_turbo_inlining) {
- StdoutStream os;
- os << Brief(shared) << ": IsInlineable? " << msg << "\n";
- }
-}
-} // namespace
-
-bool SharedFunctionInfo::IsInlineable() {
- if (!script().IsScript()) {
- TraceInlining(*this, "false (no Script associated with it)");
- return false;
- }
+SharedFunctionInfo::Inlineability SharedFunctionInfo::GetInlineability() const {
+ if (!script().IsScript()) return kHasNoScript;
if (GetIsolate()->is_precise_binary_code_coverage() &&
!has_reported_binary_coverage()) {
// We may miss invocations if this function is inlined.
- TraceInlining(*this, "false (requires reported binary coverage)");
- return false;
+ return kNeedsBinaryCoverage;
}
- if (optimization_disabled()) {
- TraceInlining(*this, "false (optimization disabled)");
- return false;
- }
+ if (optimization_disabled()) return kHasOptimizationDisabled;
// Built-in functions are handled by the JSCallReducer.
- if (HasBuiltinId()) {
- TraceInlining(*this, "false (is a builtin)");
- return false;
- }
+ if (HasBuiltinId()) return kIsBuiltin;
- if (!IsUserJavaScript()) {
- TraceInlining(*this, "false (is not user code)");
- return false;
- }
+ if (!IsUserJavaScript()) return kIsNotUserCode;
// If there is no bytecode array, it is either not compiled or it is compiled
// with WebAssembly for the asm.js pipeline. In either case we don't want to
// inline.
- if (!HasBytecodeArray()) {
- TraceInlining(*this, "false (has no BytecodeArray)");
- return false;
- }
+ if (!HasBytecodeArray()) return kHasNoBytecode;
if (GetBytecodeArray().length() > FLAG_max_inlined_bytecode_size) {
- TraceInlining(*this, "false (length > FLAG_max_inlined_bytecode_size)");
- return false;
+ return kExceedsBytecodeLimit;
}
- if (HasBreakInfo()) {
- TraceInlining(*this, "false (may contain break points)");
- return false;
- }
+ if (HasBreakInfo()) return kMayContainBreakPoints;
- TraceInlining(*this, "true");
- return true;
+ return kIsInlineable;
}
int SharedFunctionInfo::SourceSize() { return EndPosition() - StartPosition(); }
@@ -5317,7 +5312,9 @@ void SharedFunctionInfo::DisableOptimization(BailoutReason reason) {
// Code should be the lazy compilation stub or else interpreted.
DCHECK(abstract_code().kind() == AbstractCode::INTERPRETED_FUNCTION ||
abstract_code().kind() == AbstractCode::BUILTIN);
- PROFILE(GetIsolate(), CodeDisableOptEvent(abstract_code(), *this));
+ PROFILE(GetIsolate(),
+ CodeDisableOptEvent(handle(abstract_code(), GetIsolate()),
+ handle(*this, GetIsolate())));
if (FLAG_trace_opt) {
PrintF("[disabled optimization for ");
ShortPrint();
@@ -5325,27 +5322,21 @@ void SharedFunctionInfo::DisableOptimization(BailoutReason reason) {
}
}
+// static
void SharedFunctionInfo::InitFromFunctionLiteral(
- Handle<SharedFunctionInfo> shared_info, FunctionLiteral* lit,
- bool is_toplevel) {
- Isolate* isolate = shared_info->GetIsolate();
- bool needs_position_info = true;
+ Isolate* isolate, Handle<SharedFunctionInfo> shared_info,
+ FunctionLiteral* lit, bool is_toplevel) {
+ DCHECK(!shared_info->name_or_scope_info().IsScopeInfo());
// When adding fields here, make sure DeclarationScope::AnalyzePartially is
// updated accordingly.
shared_info->set_internal_formal_parameter_count(lit->parameter_count());
shared_info->SetFunctionTokenPosition(lit->function_token_position(),
lit->start_position());
- if (shared_info->scope_info().HasPositionInfo()) {
- shared_info->scope_info().SetPositionInfo(lit->start_position(),
- lit->end_position());
- needs_position_info = false;
- }
shared_info->set_syntax_kind(lit->syntax_kind());
shared_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
shared_info->set_language_mode(lit->language_mode());
shared_info->set_function_literal_id(lit->function_literal_id());
- // shared_info->set_kind(lit->kind());
// FunctionKind must have already been set.
DCHECK(lit->kind() == shared_info->kind());
shared_info->set_needs_home_object(lit->scope()->NeedsHomeObject());
@@ -5377,32 +5368,31 @@ void SharedFunctionInfo::InitFromFunctionLiteral(
shared_info->set_is_safe_to_skip_arguments_adaptor(
lit->SafeToSkipArgumentsAdaptor());
DCHECK_NULL(lit->produced_preparse_data());
+
// If we're about to eager compile, we'll have the function literal
// available, so there's no need to wastefully allocate an uncompiled data.
- // TODO(leszeks): This should be explicitly passed as a parameter, rather
- // than relying on a property of the literal.
- needs_position_info = false;
+ return;
+ }
+
+ shared_info->set_is_safe_to_skip_arguments_adaptor(false);
+ shared_info->UpdateExpectedNofPropertiesFromEstimate(lit);
+
+ Handle<UncompiledData> data;
+
+ ProducedPreparseData* scope_data = lit->produced_preparse_data();
+ if (scope_data != nullptr) {
+ Handle<PreparseData> preparse_data =
+ scope_data->Serialize(shared_info->GetIsolate());
+
+ data = isolate->factory()->NewUncompiledDataWithPreparseData(
+ lit->inferred_name(), lit->start_position(), lit->end_position(),
+ preparse_data);
} else {
- shared_info->set_is_safe_to_skip_arguments_adaptor(false);
- ProducedPreparseData* scope_data = lit->produced_preparse_data();
- if (scope_data != nullptr) {
- Handle<PreparseData> preparse_data =
- scope_data->Serialize(shared_info->GetIsolate());
- Handle<UncompiledData> data =
- isolate->factory()->NewUncompiledDataWithPreparseData(
- lit->inferred_name(), lit->start_position(), lit->end_position(),
- preparse_data);
- shared_info->set_uncompiled_data(*data);
- needs_position_info = false;
- }
- shared_info->UpdateExpectedNofPropertiesFromEstimate(lit);
- }
- if (needs_position_info) {
- Handle<UncompiledData> data =
- isolate->factory()->NewUncompiledDataWithoutPreparseData(
- lit->inferred_name(), lit->start_position(), lit->end_position());
- shared_info->set_uncompiled_data(*data);
+ data = isolate->factory()->NewUncompiledDataWithoutPreparseData(
+ lit->inferred_name(), lit->start_position(), lit->end_position());
}
+
+ shared_info->set_uncompiled_data(*data);
}
uint16_t SharedFunctionInfo::get_property_estimate_from_literal(
@@ -5684,7 +5674,7 @@ bool JSArray::HasReadOnlyLength(Handle<JSArray> array) {
}
Isolate* isolate = array->GetIsolate();
- LookupIterator it(array, isolate->factory()->length_string(), array,
+ LookupIterator it(isolate, array, isolate->factory()->length_string(), array,
LookupIterator::OWN_SKIP_INTERCEPTOR);
CHECK_EQ(LookupIterator::ACCESSOR, it.state());
return it.IsReadOnly();
@@ -5708,8 +5698,7 @@ void Dictionary<Derived, Shape>::Print(std::ostream& os) {
DisallowHeapAllocation no_gc;
ReadOnlyRoots roots = this->GetReadOnlyRoots();
Derived dictionary = Derived::cast(*this);
- int capacity = dictionary.Capacity();
- for (int i = 0; i < capacity; i++) {
+ for (InternalIndex i : dictionary.IterateEntries()) {
Object k = dictionary.KeyAt(i);
if (!dictionary.ToKey(roots, i, &k)) continue;
os << "\n ";
@@ -5750,11 +5739,11 @@ const char* Symbol::PrivateSymbolToName() const {
void Symbol::SymbolShortPrint(std::ostream& os) {
os << "<Symbol:";
- if (!name().IsUndefined()) {
+ if (!description().IsUndefined()) {
os << " ";
HeapStringAllocator allocator;
StringStream accumulator(&allocator);
- String::cast(name()).StringShortPrint(&accumulator, false);
+ String::cast(description()).StringShortPrint(&accumulator, false);
os << accumulator.ToCString().get();
} else {
os << " (" << PrivateSymbolToName() << ")";
@@ -5877,11 +5866,30 @@ Handle<Object> JSPromise::Fulfill(Handle<JSPromise> promise,
PromiseReaction::kFulfill);
}
+static void MoveMessageToPromise(Isolate* isolate, Handle<JSPromise> promise) {
+ if (isolate->thread_local_top()->pending_message_obj_.IsTheHole(isolate)) {
+ return;
+ }
+
+ Handle<Object> message =
+ handle(isolate->thread_local_top()->pending_message_obj_, isolate);
+ Handle<Symbol> key = isolate->factory()->promise_debug_message_symbol();
+ Object::SetProperty(isolate, promise, key, message, StoreOrigin::kMaybeKeyed,
+ Just(ShouldThrow::kThrowOnError))
+ .Assert();
+
+ // The message object for a rejected promise was only stored for this purpose.
+ // Clear it, otherwise we might leak memory.
+ isolate->clear_pending_message();
+}
+
// static
Handle<Object> JSPromise::Reject(Handle<JSPromise> promise,
Handle<Object> reason, bool debug_event) {
Isolate* const isolate = promise->GetIsolate();
+ if (isolate->debug()->is_active()) MoveMessageToPromise(isolate, promise);
+
if (debug_event) isolate->debug()->OnPromiseReject(promise, reason);
isolate->RunPromiseHook(PromiseHookType::kResolve, promise,
isolate->factory()->undefined_value());
@@ -6006,7 +6014,7 @@ Handle<Object> JSPromise::TriggerPromiseReactions(Isolate* isolate,
{
DisallowHeapAllocation no_gc;
Object current = *reactions;
- Object reversed = Smi::kZero;
+ Object reversed = Smi::zero();
while (!current.IsSmi()) {
Object next = PromiseReaction::cast(current).next();
PromiseReaction::cast(current).set_next(reversed);
@@ -6090,10 +6098,9 @@ Handle<Object> JSPromise::TriggerPromiseReactions(Isolate* isolate,
return isolate->factory()->undefined_value();
}
-namespace {
-
-JSRegExp::Flags RegExpFlagsFromString(Isolate* isolate, Handle<String> flags,
- bool* success) {
+// static
+JSRegExp::Flags JSRegExp::FlagsFromString(Isolate* isolate,
+ Handle<String> flags, bool* success) {
STATIC_ASSERT(JSRegExp::FlagFromChar('g') == JSRegExp::kGlobal);
STATIC_ASSERT(JSRegExp::FlagFromChar('i') == JSRegExp::kIgnoreCase);
STATIC_ASSERT(JSRegExp::FlagFromChar('m') == JSRegExp::kMultiline);
@@ -6136,16 +6143,14 @@ JSRegExp::Flags RegExpFlagsFromString(Isolate* isolate, Handle<String> flags,
return value;
}
-} // namespace
-
// static
MaybeHandle<JSRegExp> JSRegExp::New(Isolate* isolate, Handle<String> pattern,
- Flags flags) {
+ Flags flags, uint32_t backtrack_limit) {
Handle<JSFunction> constructor = isolate->regexp_function();
Handle<JSRegExp> regexp =
Handle<JSRegExp>::cast(isolate->factory()->NewJSObject(constructor));
- return JSRegExp::Initialize(regexp, pattern, flags);
+ return JSRegExp::Initialize(regexp, pattern, flags, backtrack_limit);
}
// static
@@ -6155,10 +6160,12 @@ Handle<JSRegExp> JSRegExp::Copy(Handle<JSRegExp> regexp) {
}
Object JSRegExp::Code(bool is_latin1) const {
+ DCHECK_EQ(TypeTag(), JSRegExp::IRREGEXP);
return DataAt(code_index(is_latin1));
}
Object JSRegExp::Bytecode(bool is_latin1) const {
+ DCHECK_EQ(TypeTag(), JSRegExp::IRREGEXP);
return DataAt(bytecode_index(is_latin1));
}
@@ -6201,7 +6208,7 @@ void JSRegExp::MarkTierUpForNextExec() {
DCHECK(FLAG_regexp_tier_up);
DCHECK_EQ(TypeTag(), JSRegExp::IRREGEXP);
FixedArray::cast(data()).set(JSRegExp::kIrregexpTicksUntilTierUpIndex,
- Smi::kZero);
+ Smi::zero());
}
namespace {
@@ -6323,7 +6330,7 @@ MaybeHandle<JSRegExp> JSRegExp::Initialize(Handle<JSRegExp> regexp,
Handle<String> flags_string) {
Isolate* isolate = regexp->GetIsolate();
bool success = false;
- Flags flags = RegExpFlagsFromString(isolate, flags_string, &success);
+ Flags flags = JSRegExp::FlagsFromString(isolate, flags_string, &success);
if (!success) {
THROW_NEW_ERROR(
isolate,
@@ -6335,7 +6342,8 @@ MaybeHandle<JSRegExp> JSRegExp::Initialize(Handle<JSRegExp> regexp,
// static
MaybeHandle<JSRegExp> JSRegExp::Initialize(Handle<JSRegExp> regexp,
- Handle<String> source, Flags flags) {
+ Handle<String> source, Flags flags,
+ uint32_t backtrack_limit) {
Isolate* isolate = regexp->GetIsolate();
Factory* factory = isolate->factory();
// If source is the empty string we set it to "(?:)" instead as
@@ -6344,8 +6352,9 @@ MaybeHandle<JSRegExp> JSRegExp::Initialize(Handle<JSRegExp> regexp,
source = String::Flatten(isolate, source);
- RETURN_ON_EXCEPTION(isolate, RegExp::Compile(isolate, regexp, source, flags),
- JSRegExp);
+ RETURN_ON_EXCEPTION(
+ isolate, RegExp::Compile(isolate, regexp, source, flags, backtrack_limit),
+ JSRegExp);
Handle<String> escaped_source;
ASSIGN_RETURN_ON_EXCEPTION(isolate, escaped_source,
@@ -6359,7 +6368,7 @@ MaybeHandle<JSRegExp> JSRegExp::Initialize(Handle<JSRegExp> regexp,
if (constructor.IsJSFunction() &&
JSFunction::cast(constructor).initial_map() == map) {
// If we still have the original map, set in-object properties directly.
- regexp->InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex, Smi::kZero,
+ regexp->InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex, Smi::zero(),
SKIP_WRITE_BARRIER);
} else {
// Map has changed, so use generic, but slower, method.
@@ -6472,7 +6481,7 @@ template <typename Derived, typename Shape>
Handle<Derived> HashTable<Derived, Shape>::NewInternal(
Isolate* isolate, int capacity, AllocationType allocation) {
Factory* factory = isolate->factory();
- int length = EntryToIndex(capacity);
+ int length = EntryToIndex(InternalIndex(capacity));
RootIndex map_root_index = Shape::GetMapRootIndex();
Handle<FixedArray> array =
factory->NewFixedArrayWithMap(map_root_index, length, allocation);
@@ -6497,8 +6506,7 @@ void HashTable<Derived, Shape>::Rehash(ReadOnlyRoots roots, Derived new_table) {
}
// Rehash the elements.
- int capacity = this->Capacity();
- for (int i = 0; i < capacity; i++) {
+ for (InternalIndex i : this->IterateEntries()) {
uint32_t from_index = EntryToIndex(i);
Object k = this->get(from_index);
if (!Shape::IsLive(roots, k)) continue;
@@ -6514,12 +6522,12 @@ void HashTable<Derived, Shape>::Rehash(ReadOnlyRoots roots, Derived new_table) {
}
template <typename Derived, typename Shape>
-uint32_t HashTable<Derived, Shape>::EntryForProbe(ReadOnlyRoots roots, Object k,
- int probe,
- uint32_t expected) {
+InternalIndex HashTable<Derived, Shape>::EntryForProbe(ReadOnlyRoots roots,
+ Object k, int probe,
+ InternalIndex expected) {
uint32_t hash = Shape::HashForObject(roots, k);
uint32_t capacity = this->Capacity();
- uint32_t entry = FirstProbe(hash, capacity);
+ InternalIndex entry = FirstProbe(hash, capacity);
for (int i = 1; i < probe; i++) {
if (entry == expected) return expected;
entry = NextProbe(entry, i, capacity);
@@ -6528,7 +6536,7 @@ uint32_t HashTable<Derived, Shape>::EntryForProbe(ReadOnlyRoots roots, Object k,
}
template <typename Derived, typename Shape>
-void HashTable<Derived, Shape>::Swap(uint32_t entry1, uint32_t entry2,
+void HashTable<Derived, Shape>::Swap(InternalIndex entry1, InternalIndex entry2,
WriteBarrierMode mode) {
int index1 = EntryToIndex(entry1);
int index2 = EntryToIndex(entry2);
@@ -6557,22 +6565,30 @@ void HashTable<Derived, Shape>::Rehash(ReadOnlyRoots roots) {
// All elements at entries given by one of the first _probe_ probes
// are placed correctly. Other elements might need to be moved.
done = true;
- for (uint32_t current = 0; current < capacity; current++) {
+ for (InternalIndex current(0); current.raw_value() < capacity;
+ /* {current} is advanced manually below, when appropriate.*/) {
Object current_key = KeyAt(current);
- if (!Shape::IsLive(roots, current_key)) continue;
- uint32_t target = EntryForProbe(roots, current_key, probe, current);
- if (current == target) continue;
+ if (!Shape::IsLive(roots, current_key)) {
+ ++current; // Advance to next entry.
+ continue;
+ }
+ InternalIndex target = EntryForProbe(roots, current_key, probe, current);
+ if (current == target) {
+ ++current; // Advance to next entry.
+ continue;
+ }
Object target_key = KeyAt(target);
if (!Shape::IsLive(roots, target_key) ||
EntryForProbe(roots, target_key, probe, target) != target) {
// Put the current element into the correct position.
Swap(current, target, mode);
- // The other element will be processed on the next iteration.
- current--;
+ // The other element will be processed on the next iteration,
+ // so don't advance {current} here!
} else {
// The place for the current element is occupied. Leave the element
// for the next probe.
done = false;
+ ++current; // Advance to next entry.
}
}
}
@@ -6580,7 +6596,7 @@ void HashTable<Derived, Shape>::Rehash(ReadOnlyRoots roots) {
Object the_hole = roots.the_hole_value();
HeapObject undefined = roots.undefined_value();
Derived* self = static_cast<Derived*>(this);
- for (uint32_t current = 0; current < capacity; current++) {
+ for (InternalIndex current : InternalIndex::Range(capacity)) {
if (KeyAt(current) == the_hole) {
self->set_key(EntryToIndex(current) + kEntryKeyIndex, undefined,
SKIP_WRITE_BARRIER);
@@ -6660,9 +6676,9 @@ Handle<Derived> HashTable<Derived, Shape>::Shrink(Isolate* isolate,
}
template <typename Derived, typename Shape>
-uint32_t HashTable<Derived, Shape>::FindInsertionEntry(uint32_t hash) {
+InternalIndex HashTable<Derived, Shape>::FindInsertionEntry(uint32_t hash) {
uint32_t capacity = Capacity();
- uint32_t entry = FirstProbe(hash, capacity);
+ InternalIndex entry = FirstProbe(hash, capacity);
uint32_t count = 1;
// EnsureCapacity will guarantee the hash table is never full.
ReadOnlyRoots roots = GetReadOnlyRoots();
@@ -6720,10 +6736,10 @@ Handle<String> StringTable::LookupString(Isolate* isolate,
template <typename StringTableKey>
Handle<String> StringTable::LookupKey(Isolate* isolate, StringTableKey* key) {
Handle<StringTable> table = isolate->factory()->string_table();
- int entry = table->FindEntry(isolate, key);
+ InternalIndex entry = table->FindEntry(isolate, key);
// String already in table.
- if (entry != kNotFound) {
+ if (entry.is_found()) {
return handle(String::cast(table->KeyAt(entry)), isolate);
}
@@ -6754,10 +6770,10 @@ Handle<String> StringTable::AddKeyNoResize(Isolate* isolate,
// InvalidStringLength error.
CHECK(!string.is_null());
DCHECK(string->HasHashCode());
- DCHECK_EQ(table->FindEntry(isolate, key), kNotFound);
+ DCHECK(table->FindEntry(isolate, key).is_not_found());
// Add the new string and return it along with the string table.
- int entry = table->FindInsertionEntry(key->hash());
+ InternalIndex entry = table->FindInsertionEntry(key->hash());
table->set(EntryToIndex(entry), *string);
table->ElementAdded();
@@ -6813,8 +6829,9 @@ Address LookupString(Isolate* isolate, String string, String source,
return Smi::FromInt(ResultSentinel::kUnsupported).ptr();
}
- int entry = table.FindEntry(ReadOnlyRoots(isolate), &key, key.hash());
- if (entry == kNotFound) {
+ InternalIndex entry =
+ table.FindEntry(ReadOnlyRoots(isolate), &key, key.hash());
+ if (entry.is_not_found()) {
// A string that's not an array index, and not in the string table,
// cannot have been used as a property name before.
return Smi::FromInt(ResultSentinel::kNotFound).ptr();
@@ -6872,7 +6889,7 @@ Handle<StringSet> StringSet::Add(Isolate* isolate, Handle<StringSet> stringset,
if (!stringset->Has(isolate, name)) {
stringset = EnsureCapacity(isolate, stringset);
uint32_t hash = ShapeT::Hash(isolate, *name);
- int entry = stringset->FindInsertionEntry(hash);
+ InternalIndex entry = stringset->FindInsertionEntry(hash);
stringset->set(EntryToIndex(entry), *name);
stringset->ElementAdded();
}
@@ -6880,7 +6897,7 @@ Handle<StringSet> StringSet::Add(Isolate* isolate, Handle<StringSet> stringset,
}
bool StringSet::Has(Isolate* isolate, Handle<String> name) {
- return FindEntry(isolate, *name) != kNotFound;
+ return FindEntry(isolate, *name).is_found();
}
Handle<ObjectHashSet> ObjectHashSet::Add(Isolate* isolate,
@@ -6889,7 +6906,7 @@ Handle<ObjectHashSet> ObjectHashSet::Add(Isolate* isolate,
int32_t hash = key->GetOrCreateHash(isolate).value();
if (!set->Has(isolate, key, hash)) {
set = EnsureCapacity(isolate, set);
- int entry = set->FindInsertionEntry(hash);
+ InternalIndex entry = set->FindInsertionEntry(hash);
set->set(EntryToIndex(entry), *key);
set->ElementAdded();
}
@@ -7026,8 +7043,8 @@ MaybeHandle<SharedFunctionInfo> CompilationCacheTable::LookupScript(
Isolate* isolate = native_context->GetIsolate();
src = String::Flatten(isolate, src);
StringSharedKey key(src, shared, language_mode, kNoSourcePosition);
- int entry = table->FindEntry(isolate, &key);
- if (entry == kNotFound) return MaybeHandle<SharedFunctionInfo>();
+ InternalIndex entry = table->FindEntry(isolate, &key);
+ if (entry.is_not_found()) return MaybeHandle<SharedFunctionInfo>();
int index = EntryToIndex(entry);
if (!table->get(index).IsFixedArray()) {
return MaybeHandle<SharedFunctionInfo>();
@@ -7047,14 +7064,14 @@ InfoCellPair CompilationCacheTable::LookupEval(
Isolate* isolate = native_context->GetIsolate();
src = String::Flatten(isolate, src);
StringSharedKey key(src, outer_info, language_mode, position);
- int entry = table->FindEntry(isolate, &key);
- if (entry == kNotFound) return empty_result;
+ InternalIndex entry = table->FindEntry(isolate, &key);
+ if (entry.is_not_found()) return empty_result;
int index = EntryToIndex(entry);
if (!table->get(index).IsFixedArray()) return empty_result;
- Object obj = table->get(EntryToIndex(entry) + 1);
+ Object obj = table->get(index + 1);
if (obj.IsSharedFunctionInfo()) {
FeedbackCell feedback_cell =
- SearchLiteralsMap(*table, EntryToIndex(entry) + 2, *native_context);
+ SearchLiteralsMap(*table, index + 2, *native_context);
return InfoCellPair(SharedFunctionInfo::cast(obj), feedback_cell);
}
return empty_result;
@@ -7065,8 +7082,8 @@ Handle<Object> CompilationCacheTable::LookupRegExp(Handle<String> src,
Isolate* isolate = GetIsolate();
DisallowHeapAllocation no_allocation;
RegExpKey key(src, flags);
- int entry = FindEntry(isolate, &key);
- if (entry == kNotFound) return isolate->factory()->undefined_value();
+ InternalIndex entry = FindEntry(isolate, &key);
+ if (entry.is_not_found()) return isolate->factory()->undefined_value();
return Handle<Object>(get(EntryToIndex(entry) + 1), isolate);
}
@@ -7085,7 +7102,7 @@ Handle<CompilationCacheTable> CompilationCacheTable::PutScript(
StringSharedKey key(src, shared, language_mode, kNoSourcePosition);
Handle<Object> k = key.AsHandle(isolate);
cache = EnsureCapacity(isolate, cache);
- int entry = cache->FindInsertionEntry(key.Hash());
+ InternalIndex entry = cache->FindInsertionEntry(key.Hash());
cache->set(EntryToIndex(entry), *k);
cache->set(EntryToIndex(entry) + 1, *value);
cache->ElementAdded();
@@ -7102,8 +7119,8 @@ Handle<CompilationCacheTable> CompilationCacheTable::PutEval(
StringSharedKey key(src, outer_info, value->language_mode(), position);
{
Handle<Object> k = key.AsHandle(isolate);
- int entry = cache->FindEntry(isolate, &key);
- if (entry != kNotFound) {
+ InternalIndex entry = cache->FindEntry(isolate, &key);
+ if (entry.is_found()) {
cache->set(EntryToIndex(entry), *k);
cache->set(EntryToIndex(entry) + 1, *value);
// AddToFeedbackCellsMap may allocate a new sub-array to live in the
@@ -7117,7 +7134,7 @@ Handle<CompilationCacheTable> CompilationCacheTable::PutEval(
}
cache = EnsureCapacity(isolate, cache);
- int entry = cache->FindInsertionEntry(key.Hash());
+ InternalIndex entry = cache->FindInsertionEntry(key.Hash());
Handle<Object> k =
isolate->factory()->NewNumber(static_cast<double>(key.Hash()));
cache->set(EntryToIndex(entry), *k);
@@ -7131,7 +7148,7 @@ Handle<CompilationCacheTable> CompilationCacheTable::PutRegExp(
JSRegExp::Flags flags, Handle<FixedArray> value) {
RegExpKey key(src, flags);
cache = EnsureCapacity(isolate, cache);
- int entry = cache->FindInsertionEntry(key.Hash());
+ InternalIndex entry = cache->FindInsertionEntry(key.Hash());
// We store the value in the key slot, and compare the search key
// to the stored value with a custon IsMatch function during lookups.
cache->set(EntryToIndex(entry), *value);
@@ -7143,7 +7160,7 @@ Handle<CompilationCacheTable> CompilationCacheTable::PutRegExp(
void CompilationCacheTable::Age() {
DisallowHeapAllocation no_allocation;
Object the_hole_value = GetReadOnlyRoots().the_hole_value();
- for (int entry = 0, size = Capacity(); entry < size; entry++) {
+ for (InternalIndex entry : IterateEntries()) {
int entry_index = EntryToIndex(entry);
int value_index = entry_index + 1;
@@ -7172,7 +7189,7 @@ void CompilationCacheTable::Age() {
void CompilationCacheTable::Remove(Object value) {
DisallowHeapAllocation no_allocation;
Object the_hole_value = GetReadOnlyRoots().the_hole_value();
- for (int entry = 0, size = Capacity(); entry < size; entry++) {
+ for (InternalIndex entry : IterateEntries()) {
int entry_index = EntryToIndex(entry);
int value_index = entry_index + 1;
if (get(value_index) == value) {
@@ -7211,7 +7228,7 @@ int BaseNameDictionary<Derived, Shape>::NextEnumerationIndex(
// Iterate over the dictionary using the enumeration order and update
// the dictionary with new enumeration indices.
for (int i = 0; i < length; i++) {
- int index = Smi::ToInt(iteration_order->get(i));
+ InternalIndex index(Smi::ToInt(iteration_order->get(i)));
DCHECK(dictionary->IsKey(dictionary->GetReadOnlyRoots(),
dictionary->KeyAt(index)));
@@ -7232,7 +7249,7 @@ int BaseNameDictionary<Derived, Shape>::NextEnumerationIndex(
template <typename Derived, typename Shape>
Handle<Derived> Dictionary<Derived, Shape>::DeleteEntry(
- Isolate* isolate, Handle<Derived> dictionary, int entry) {
+ Isolate* isolate, Handle<Derived> dictionary, InternalIndex entry) {
DCHECK(Shape::kEntrySize != 3 ||
dictionary->DetailsAt(entry).IsConfigurable());
dictionary->ClearEntry(isolate, entry);
@@ -7245,10 +7262,10 @@ Handle<Derived> Dictionary<Derived, Shape>::AtPut(Isolate* isolate,
Handle<Derived> dictionary,
Key key, Handle<Object> value,
PropertyDetails details) {
- int entry = dictionary->FindEntry(isolate, key);
+ InternalIndex entry = dictionary->FindEntry(isolate, key);
// If the entry is present set the value;
- if (entry == Dictionary::kNotFound) {
+ if (entry.is_not_found()) {
return Derived::Add(isolate, dictionary, key, value, details);
}
@@ -7262,8 +7279,8 @@ template <typename Derived, typename Shape>
Handle<Derived>
BaseNameDictionary<Derived, Shape>::AddNoUpdateNextEnumerationIndex(
Isolate* isolate, Handle<Derived> dictionary, Key key, Handle<Object> value,
- PropertyDetails details, int* entry_out) {
- // Insert element at empty or deleted entry
+ PropertyDetails details, InternalIndex* entry_out) {
+ // Insert element at empty or deleted entry.
return Dictionary<Derived, Shape>::Add(isolate, dictionary, key, value,
details, entry_out);
}
@@ -7271,7 +7288,7 @@ BaseNameDictionary<Derived, Shape>::AddNoUpdateNextEnumerationIndex(
template <typename Derived, typename Shape>
Handle<Derived> BaseNameDictionary<Derived, Shape>::Add(
Isolate* isolate, Handle<Derived> dictionary, Key key, Handle<Object> value,
- PropertyDetails details, int* entry_out) {
+ PropertyDetails details, InternalIndex* entry_out) {
// Insert element at empty or deleted entry
DCHECK_EQ(0, details.dictionary_index());
// Assign an enumeration index to the property and update
@@ -7291,17 +7308,17 @@ Handle<Derived> Dictionary<Derived, Shape>::Add(Isolate* isolate,
Handle<Derived> dictionary,
Key key, Handle<Object> value,
PropertyDetails details,
- int* entry_out) {
+ InternalIndex* entry_out) {
uint32_t hash = Shape::Hash(isolate, key);
- // Valdate key is absent.
- SLOW_DCHECK((dictionary->FindEntry(isolate, key) == Dictionary::kNotFound));
+ // Validate that the key is absent.
+ SLOW_DCHECK(dictionary->FindEntry(isolate, key).is_not_found());
// Check whether the dictionary should be extended.
dictionary = Derived::EnsureCapacity(isolate, dictionary);
// Compute the key object.
Handle<Object> k = Shape::AsHandle(isolate, key);
- uint32_t entry = dictionary->FindInsertionEntry(hash);
+ InternalIndex entry = dictionary->FindInsertionEntry(hash);
dictionary->SetEntry(isolate, entry, *k, *value, details);
DCHECK(dictionary->KeyAt(entry).IsNumber() ||
Shape::Unwrap(dictionary->KeyAt(entry)).IsUniqueName());
@@ -7356,10 +7373,9 @@ Handle<NumberDictionary> NumberDictionary::Set(
void NumberDictionary::CopyValuesTo(FixedArray elements) {
ReadOnlyRoots roots = GetReadOnlyRoots();
int pos = 0;
- int capacity = this->Capacity();
DisallowHeapAllocation no_gc;
WriteBarrierMode mode = elements.GetWriteBarrierMode(no_gc);
- for (int i = 0; i < capacity; i++) {
+ for (InternalIndex i : this->IterateEntries()) {
Object k;
if (this->ToKey(roots, i, &k)) {
elements.set(pos++, this->ValueAt(i), mode);
@@ -7371,9 +7387,8 @@ void NumberDictionary::CopyValuesTo(FixedArray elements) {
template <typename Derived, typename Shape>
int Dictionary<Derived, Shape>::NumberOfEnumerableProperties() {
ReadOnlyRoots roots = this->GetReadOnlyRoots();
- int capacity = this->Capacity();
int result = 0;
- for (int i = 0; i < capacity; i++) {
+ for (InternalIndex i : this->IterateEntries()) {
Object k;
if (!this->ToKey(roots, i, &k)) continue;
if (k.FilterKey(ENUMERABLE_STRINGS)) continue;
@@ -7388,8 +7403,10 @@ template <typename Dictionary>
struct EnumIndexComparator {
explicit EnumIndexComparator(Dictionary dict) : dict(dict) {}
bool operator()(Tagged_t a, Tagged_t b) {
- PropertyDetails da(dict.DetailsAt(Smi(static_cast<Address>(a)).value()));
- PropertyDetails db(dict.DetailsAt(Smi(static_cast<Address>(b)).value()));
+ PropertyDetails da(
+ dict.DetailsAt(InternalIndex(Smi(static_cast<Address>(a)).value())));
+ PropertyDetails db(
+ dict.DetailsAt(InternalIndex(Smi(static_cast<Address>(b)).value())));
return da.dictionary_index() < db.dictionary_index();
}
Dictionary dict;
@@ -7401,51 +7418,55 @@ void BaseNameDictionary<Derived, Shape>::CopyEnumKeysTo(
KeyCollectionMode mode, KeyAccumulator* accumulator) {
DCHECK_IMPLIES(mode != KeyCollectionMode::kOwnOnly, accumulator != nullptr);
int length = storage->length();
- int capacity = dictionary->Capacity();
int properties = 0;
ReadOnlyRoots roots(isolate);
- for (int i = 0; i < capacity; i++) {
- Object key;
- if (!dictionary->ToKey(roots, i, &key)) continue;
- bool is_shadowing_key = false;
- if (key.IsSymbol()) continue;
- PropertyDetails details = dictionary->DetailsAt(i);
- if (details.IsDontEnum()) {
- if (mode == KeyCollectionMode::kIncludePrototypes) {
- is_shadowing_key = true;
- } else {
+ {
+ AllowHeapAllocation allow_gc;
+ for (InternalIndex i : dictionary->IterateEntries()) {
+ Object key;
+ if (!dictionary->ToKey(roots, i, &key)) continue;
+ bool is_shadowing_key = false;
+ if (key.IsSymbol()) continue;
+ PropertyDetails details = dictionary->DetailsAt(i);
+ if (details.IsDontEnum()) {
+ if (mode == KeyCollectionMode::kIncludePrototypes) {
+ is_shadowing_key = true;
+ } else {
+ continue;
+ }
+ }
+ if (is_shadowing_key) {
+ // This might allocate, but {key} is not used afterwards.
+ accumulator->AddShadowingKey(key, &allow_gc);
continue;
+ } else {
+ storage->set(properties, Smi::FromInt(i.as_int()));
}
+ properties++;
+ if (mode == KeyCollectionMode::kOwnOnly && properties == length) break;
}
- if (is_shadowing_key) {
- accumulator->AddShadowingKey(key);
- continue;
- } else {
- storage->set(properties, Smi::FromInt(i));
- }
- properties++;
- if (mode == KeyCollectionMode::kOwnOnly && properties == length) break;
}
CHECK_EQ(length, properties);
- DisallowHeapAllocation no_gc;
- Derived raw_dictionary = *dictionary;
- FixedArray raw_storage = *storage;
- EnumIndexComparator<Derived> cmp(raw_dictionary);
- // Use AtomicSlot wrapper to ensure that std::sort uses atomic load and
- // store operations that are safe for concurrent marking.
- AtomicSlot start(storage->GetFirstElementAddress());
- std::sort(start, start + length, cmp);
- for (int i = 0; i < length; i++) {
- int index = Smi::ToInt(raw_storage.get(i));
- raw_storage.set(i, raw_dictionary.NameAt(index));
+ {
+ DisallowHeapAllocation no_gc;
+ Derived raw_dictionary = *dictionary;
+ FixedArray raw_storage = *storage;
+ EnumIndexComparator<Derived> cmp(raw_dictionary);
+ // Use AtomicSlot wrapper to ensure that std::sort uses atomic load and
+ // store operations that are safe for concurrent marking.
+ AtomicSlot start(storage->GetFirstElementAddress());
+ std::sort(start, start + length, cmp);
+ for (int i = 0; i < length; i++) {
+ InternalIndex index(Smi::ToInt(raw_storage.get(i)));
+ raw_storage.set(i, raw_dictionary.NameAt(index));
+ }
}
}
template <typename Derived, typename Shape>
Handle<FixedArray> BaseNameDictionary<Derived, Shape>::IterationIndices(
Isolate* isolate, Handle<Derived> dictionary) {
- int capacity = dictionary->Capacity();
int length = dictionary->NumberOfElements();
Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
ReadOnlyRoots roots(isolate);
@@ -7453,10 +7474,10 @@ Handle<FixedArray> BaseNameDictionary<Derived, Shape>::IterationIndices(
{
DisallowHeapAllocation no_gc;
Derived raw_dictionary = *dictionary;
- for (int i = 0; i < capacity; i++) {
+ for (InternalIndex i : dictionary->IterateEntries()) {
Object k;
if (!raw_dictionary.ToKey(roots, i, &k)) continue;
- array->set(array_size++, Smi::FromInt(i));
+ array->set(array_size++, Smi::FromInt(i.as_int()));
}
DCHECK_EQ(array_size, length);
@@ -7475,21 +7496,25 @@ ExceptionStatus BaseNameDictionary<Derived, Shape>::CollectKeysTo(
Handle<Derived> dictionary, KeyAccumulator* keys) {
Isolate* isolate = keys->isolate();
ReadOnlyRoots roots(isolate);
- int capacity = dictionary->Capacity();
+ // TODO(jkummerow): Consider using a std::unique_ptr<InternalIndex[]> instead.
Handle<FixedArray> array =
isolate->factory()->NewFixedArray(dictionary->NumberOfElements());
int array_size = 0;
PropertyFilter filter = keys->filter();
+ // Handle enumerable strings in CopyEnumKeysTo.
+ DCHECK_NE(keys->filter(), ENUMERABLE_STRINGS);
{
DisallowHeapAllocation no_gc;
- Derived raw_dictionary = *dictionary;
- for (int i = 0; i < capacity; i++) {
- Object k;
- if (!raw_dictionary.ToKey(roots, i, &k)) continue;
- if (k.FilterKey(filter)) continue;
+ for (InternalIndex i : dictionary->IterateEntries()) {
+ Object key;
+ Derived raw_dictionary = *dictionary;
+ if (!raw_dictionary.ToKey(roots, i, &key)) continue;
+ if (key.FilterKey(filter)) continue;
PropertyDetails details = raw_dictionary.DetailsAt(i);
if ((details.attributes() & filter) != 0) {
- keys->AddShadowingKey(k);
+ AllowHeapAllocation gc;
+ // This might allocate, but {key} is not used afterwards.
+ keys->AddShadowingKey(key, &gc);
continue;
}
if (filter & ONLY_ALL_CAN_READ) {
@@ -7498,10 +7523,10 @@ ExceptionStatus BaseNameDictionary<Derived, Shape>::CollectKeysTo(
if (!accessors.IsAccessorInfo()) continue;
if (!AccessorInfo::cast(accessors).all_can_read()) continue;
}
- array->set(array_size++, Smi::FromInt(i));
+ array->set(array_size++, Smi::FromInt(i.as_int()));
}
- EnumIndexComparator<Derived> cmp(raw_dictionary);
+ EnumIndexComparator<Derived> cmp(*dictionary);
// Use AtomicSlot wrapper to ensure that std::sort uses atomic load and
// store operations that are safe for concurrent marking.
AtomicSlot start(array->GetFirstElementAddress());
@@ -7510,7 +7535,7 @@ ExceptionStatus BaseNameDictionary<Derived, Shape>::CollectKeysTo(
bool has_seen_symbol = false;
for (int i = 0; i < array_size; i++) {
- int index = Smi::ToInt(array->get(i));
+ InternalIndex index(Smi::ToInt(array->get(i)));
Object key = dictionary->NameAt(index);
if (key.IsSymbol()) {
has_seen_symbol = true;
@@ -7521,7 +7546,7 @@ ExceptionStatus BaseNameDictionary<Derived, Shape>::CollectKeysTo(
}
if (has_seen_symbol) {
for (int i = 0; i < array_size; i++) {
- int index = Smi::ToInt(array->get(i));
+ InternalIndex index(Smi::ToInt(array->get(i)));
Object key = dictionary->NameAt(index);
if (!key.IsSymbol()) continue;
ExceptionStatus status = keys->AddKey(key, DO_NOT_CONVERT);
@@ -7536,8 +7561,7 @@ template <typename Derived, typename Shape>
Object Dictionary<Derived, Shape>::SlowReverseLookup(Object value) {
Derived dictionary = Derived::cast(*this);
ReadOnlyRoots roots = dictionary.GetReadOnlyRoots();
- int capacity = dictionary.Capacity();
- for (int i = 0; i < capacity; i++) {
+ for (InternalIndex i : dictionary.IterateEntries()) {
Object k;
if (!dictionary.ToKey(roots, i, &k)) continue;
Object e = dictionary.ValueAt(i);
@@ -7550,7 +7574,7 @@ template <typename Derived, typename Shape>
void ObjectHashTableBase<Derived, Shape>::FillEntriesWithHoles(
Handle<Derived> table) {
int length = table->length();
- for (int i = Derived::EntryToIndex(0); i < length; i++) {
+ for (int i = Derived::EntryToIndex(InternalIndex(0)); i < length; i++) {
table->set_the_hole(i);
}
}
@@ -7562,8 +7586,8 @@ Object ObjectHashTableBase<Derived, Shape>::Lookup(ReadOnlyRoots roots,
DisallowHeapAllocation no_gc;
DCHECK(this->IsKey(roots, *key));
- int entry = this->FindEntry(roots, key, hash);
- if (entry == kNotFound) return roots.the_hole_value();
+ InternalIndex entry = this->FindEntry(roots, key, hash);
+ if (entry.is_not_found()) return roots.the_hole_value();
return this->get(Derived::EntryToIndex(entry) + 1);
}
@@ -7589,7 +7613,7 @@ Object ObjectHashTableBase<Derived, Shape>::Lookup(Handle<Object> key,
}
template <typename Derived, typename Shape>
-Object ObjectHashTableBase<Derived, Shape>::ValueAt(int entry) {
+Object ObjectHashTableBase<Derived, Shape>::ValueAt(InternalIndex entry) {
return this->get(EntryToValueIndex(entry));
}
@@ -7618,10 +7642,10 @@ Handle<Derived> ObjectHashTableBase<Derived, Shape>::Put(Isolate* isolate,
DCHECK(table->IsKey(roots, *key));
DCHECK(!value->IsTheHole(roots));
- int entry = table->FindEntry(roots, key, hash);
+ InternalIndex entry = table->FindEntry(roots, key, hash);
// Key is already in table, just overwrite value.
- if (entry != kNotFound) {
+ if (entry.is_found()) {
table->set(Derived::EntryToValueIndex(entry), *value);
return table;
}
@@ -7673,8 +7697,8 @@ Handle<Derived> ObjectHashTableBase<Derived, Shape>::Remove(
ReadOnlyRoots roots = table->GetReadOnlyRoots();
DCHECK(table->IsKey(roots, *key));
- int entry = table->FindEntry(roots, key, hash);
- if (entry == kNotFound) {
+ InternalIndex entry = table->FindEntry(roots, key, hash);
+ if (entry.is_not_found()) {
*was_present = false;
return table;
}
@@ -7685,8 +7709,8 @@ Handle<Derived> ObjectHashTableBase<Derived, Shape>::Remove(
}
template <typename Derived, typename Shape>
-void ObjectHashTableBase<Derived, Shape>::AddEntry(int entry, Object key,
- Object value) {
+void ObjectHashTableBase<Derived, Shape>::AddEntry(InternalIndex entry,
+ Object key, Object value) {
Derived* self = static_cast<Derived*>(this);
self->set_key(Derived::EntryToIndex(entry), key);
self->set(Derived::EntryToValueIndex(entry), value);
@@ -7694,7 +7718,7 @@ void ObjectHashTableBase<Derived, Shape>::AddEntry(int entry, Object key,
}
template <typename Derived, typename Shape>
-void ObjectHashTableBase<Derived, Shape>::RemoveEntry(int entry) {
+void ObjectHashTableBase<Derived, Shape>::RemoveEntry(InternalIndex entry) {
this->set_the_hole(Derived::EntryToIndex(entry));
this->set_the_hole(Derived::EntryToValueIndex(entry));
this->ElementRemoved();
@@ -7786,7 +7810,7 @@ Handle<JSArray> JSWeakCollection::GetEntries(Handle<JSWeakCollection> holder,
for (int i = 0;
count / values_per_entry < max_entries && i < table->Capacity(); i++) {
Object key;
- if (table->ToKey(roots, i, &key)) {
+ if (table->ToKey(roots, InternalIndex(i), &key)) {
entries->set(count++, key);
if (values_per_entry > 1) {
Object value = table->Lookup(handle(key, isolate));
@@ -7800,7 +7824,8 @@ Handle<JSArray> JSWeakCollection::GetEntries(Handle<JSWeakCollection> holder,
}
Handle<PropertyCell> PropertyCell::InvalidateEntry(
- Isolate* isolate, Handle<GlobalDictionary> dictionary, int entry) {
+ Isolate* isolate, Handle<GlobalDictionary> dictionary,
+ InternalIndex entry) {
// Swap with a copy.
Handle<PropertyCell> cell(dictionary->CellAt(entry), isolate);
Handle<Name> name(cell->name(), isolate);
@@ -7810,6 +7835,7 @@ Handle<PropertyCell> PropertyCell::InvalidateEntry(
bool is_the_hole = cell->value().IsTheHole(isolate);
// Cell is officially mutable henceforth.
PropertyDetails details = cell->property_details();
+ DCHECK(details.IsConfigurable());
details = details.set_cell_type(is_the_hole ? PropertyCellType::kUninitialized
: PropertyCellType::kMutable);
new_cell->set_property_details(details);
@@ -7880,15 +7906,14 @@ PropertyCellType PropertyCell::UpdatedType(Isolate* isolate,
}
Handle<PropertyCell> PropertyCell::PrepareForValue(
- Isolate* isolate, Handle<GlobalDictionary> dictionary, int entry,
+ Isolate* isolate, Handle<GlobalDictionary> dictionary, InternalIndex entry,
Handle<Object> value, PropertyDetails details) {
DCHECK(!value->IsTheHole(isolate));
Handle<PropertyCell> cell(dictionary->CellAt(entry), isolate);
const PropertyDetails original_details = cell->property_details();
// Data accesses could be cached in ics or optimized code.
bool invalidate =
- (original_details.kind() == kData && details.kind() == kAccessor) ||
- (!original_details.IsReadOnly() && details.IsReadOnly());
+ original_details.kind() == kData && details.kind() == kAccessor;
int index;
PropertyCellType old_type = original_details.cell_type();
// Preserve the enumeration index unless the property was deleted or never
@@ -8140,6 +8165,15 @@ Maybe<bool> JSFinalizationGroup::Cleanup(
Isolate* isolate, Handle<JSFinalizationGroup> finalization_group,
Handle<Object> cleanup) {
DCHECK(cleanup->IsCallable());
+ // Attempt to shrink key_map now, as unregister tokens are held weakly and the
+ // map is not shrinkable when sweeping dead tokens during GC itself.
+ if (!finalization_group->key_map().IsUndefined(isolate)) {
+ Handle<SimpleNumberDictionary> key_map = handle(
+ SimpleNumberDictionary::cast(finalization_group->key_map()), isolate);
+ key_map = SimpleNumberDictionary::Shrink(isolate, key_map);
+ finalization_group->set_key_map(*key_map);
+ }
+
// It's possible that the cleared_cells list is empty, since
// FinalizationGroup.unregister() removed all its elements before this task
// ran. In that case, don't call the cleanup function.
@@ -8170,36 +8204,5 @@ Maybe<bool> JSFinalizationGroup::Cleanup(
return Just(true);
}
-MaybeHandle<FixedArray> JSReceiver::GetPrivateEntries(
- Isolate* isolate, Handle<JSReceiver> receiver) {
- PropertyFilter key_filter = static_cast<PropertyFilter>(PRIVATE_NAMES_ONLY);
-
- Handle<FixedArray> keys;
- ASSIGN_RETURN_ON_EXCEPTION_VALUE(
- isolate, keys,
- KeyAccumulator::GetKeys(receiver, KeyCollectionMode::kOwnOnly, key_filter,
- GetKeysConversion::kConvertToString),
- MaybeHandle<FixedArray>());
-
- Handle<FixedArray> entries =
- isolate->factory()->NewFixedArray(keys->length() * 2);
- int length = 0;
-
- for (int i = 0; i < keys->length(); ++i) {
- Handle<Object> obj_key = handle(keys->get(i), isolate);
- Handle<Symbol> key(Symbol::cast(*obj_key), isolate);
- CHECK(key->is_private_name());
- Handle<Object> value;
- ASSIGN_RETURN_ON_EXCEPTION_VALUE(
- isolate, value, Object::GetProperty(isolate, receiver, key),
- MaybeHandle<FixedArray>());
-
- entries->set(length++, *key);
- entries->set(length++, *value);
- }
- DCHECK_EQ(length, entries->length());
- return FixedArray::ShrinkOrEmpty(isolate, entries, length);
-}
-
} // namespace internal
} // namespace v8