[offthread] Add OffThreadFactory support to AST strings

Add support for internalizing an AstValueFactory using the off-thread
factory. Includes adding ConsString support to OffThreadFactory.

This introduces a Handle union wrapper, which is used in locations that
can store a Handle or an OffThreadHandle. This is used in this patch for
the internalized "string" field of AST strings, and will be able to be
used for other similar fields in other classes (e.g. the ScopeInfo
handle in Scope, object boilerplate descriptor handles, the inferred
name handle on FunctionLiterals, etc.). It has a Factory-templated
getter which returns the appropriate handle for the factory, and a
debug-only tag to make sure the right getter is used at runtime. This
union wrapper currently decomposes implicitly to a Handle if the getter
is not called, to minimise code changes, but this implicit conversion
will likely be removed for clarity.

Bug: chromium:1011762
Change-Id: I5dd3a7bbdc483b66f5ff687e0079c545b636dc13
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1993971
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#65816}
This commit is contained in:
Leszek Swirski 2020-01-15 12:59:56 +01:00 committed by Commit Bot
parent d64a48dbdf
commit bcbb553db0
36 changed files with 554 additions and 307 deletions

View File

@ -16,6 +16,7 @@ include_rules = [
"+src/heap/heap-inl.h",
"+src/heap/heap-write-barrier-inl.h",
"+src/heap/heap-write-barrier.h",
"+src/heap/off-thread-factory-inl.h",
"+src/heap/off-thread-factory.h",
"+src/heap/read-only-heap-inl.h",
"+src/heap/read-only-heap.h",

View File

@ -27,6 +27,9 @@
#include "src/ast/ast-value-factory.h"
#include "src/common/globals.h"
#include "src/heap/factory-inl.h"
#include "src/heap/off-thread-factory-inl.h"
#include "src/objects/objects-inl.h"
#include "src/objects/objects.h"
#include "src/strings/char-predicates-inl.h"
@ -54,20 +57,42 @@ class OneByteStringStream {
} // namespace
void AstRawString::Internalize(Isolate* isolate) {
void AstRawString::Internalize(Factory* factory) {
DCHECK(!has_string_);
if (literal_bytes_.length() == 0) {
set_string(isolate->factory()->empty_string());
set_string(factory->empty_string());
} else if (is_one_byte()) {
OneByteStringKey key(hash_field_, literal_bytes_);
set_string(StringTable::LookupKey(isolate, &key));
set_string(factory->InternalizeStringWithKey(&key));
} else {
TwoByteStringKey key(hash_field_,
Vector<const uint16_t>::cast(literal_bytes_));
set_string(StringTable::LookupKey(isolate, &key));
set_string(factory->InternalizeStringWithKey(&key));
}
}
void AstRawString::Internalize(OffThreadFactory* factory) {
DCHECK(!has_string_);
if (literal_bytes_.length() == 0) {
set_string(factory->empty_string());
return;
}
// For the off-thread case, we already de-duplicated the AstRawStrings during
// construction and don't have access to the main thread string table yet, so
// we just unconditionally create strings and will internalize them properly
// during merging.
OffThreadHandle<SeqString> string;
if (is_one_byte()) {
string = factory->NewOneByteInternalizedString(
Vector<const uint8_t>::cast(literal_bytes_), hash_field());
} else {
string = factory->NewTwoByteInternalizedString(
Vector<const uc16>::cast(literal_bytes_), hash_field());
}
set_string(string);
}
bool AstRawString::AsArrayIndex(uint32_t* index) const {
// The StringHasher will set up the hash in such a way that we can use it to
// figure out whether the string is convertible to an array index.
@ -134,22 +159,28 @@ bool AstRawString::Compare(void* a, void* b) {
}
}
void AstConsString::Internalize(Isolate* isolate) {
template <typename Factory>
void AstConsString::Internalize(Factory* factory) {
if (IsEmpty()) {
set_string(isolate->factory()->empty_string());
set_string(factory->empty_string());
return;
}
// AstRawStrings are internalized before AstConsStrings, so
// AstRawString::string() will just work.
Handle<String> tmp(segment_.string->string());
FactoryHandle<Factory, String> tmp(segment_.string->string().get<Factory>());
for (AstConsString::Segment* current = segment_.next; current != nullptr;
current = current->next) {
tmp = isolate->factory()
->NewConsString(current->string->string(), tmp)
tmp = factory
->NewConsString(current->string->string().get<Factory>(), tmp,
AllocationType::kOld)
.ToHandleChecked();
}
set_string(tmp);
}
template EXPORT_TEMPLATE_DEFINE(
V8_BASE_EXPORT) void AstConsString::Internalize<Factory>(Factory* factory);
template EXPORT_TEMPLATE_DEFINE(V8_BASE_EXPORT) void AstConsString::Internalize<
OffThreadFactory>(OffThreadFactory* factory);
std::forward_list<const AstRawString*> AstConsString::ToRawStrings() const {
std::forward_list<const AstRawString*> result;
@ -250,24 +281,30 @@ AstConsString* AstValueFactory::NewConsString(const AstRawString* str1,
return NewConsString()->AddString(zone_, str1)->AddString(zone_, str2);
}
void AstValueFactory::Internalize(Isolate* isolate) {
template <typename Factory>
void AstValueFactory::Internalize(Factory* factory) {
// Strings need to be internalized before values, because values refer to
// strings.
for (AstRawString* current = strings_; current != nullptr;) {
AstRawString* next = current->next();
current->Internalize(isolate);
current->Internalize(factory);
current = next;
}
// AstConsStrings refer to AstRawStrings.
for (AstConsString* current = cons_strings_; current != nullptr;) {
AstConsString* next = current->next();
current->Internalize(isolate);
current->Internalize(factory);
current = next;
}
ResetStrings();
}
template EXPORT_TEMPLATE_DEFINE(
V8_BASE_EXPORT) void AstValueFactory::Internalize<Factory>(Factory*
factory);
template EXPORT_TEMPLATE_DEFINE(V8_BASE_EXPORT) void AstValueFactory::
Internalize<OffThreadFactory>(OffThreadFactory* factory);
AstRawString* AstValueFactory::GetString(uint32_t hash_field, bool is_one_byte,
Vector<const byte> literal_bytes) {

View File

@ -34,6 +34,7 @@
#include "src/common/globals.h"
#include "src/execution/isolate.h"
#include "src/heap/factory.h"
#include "src/heap/off-thread-factory.h"
#include "src/numbers/conversions.h"
// Ast(Raw|Cons)String and AstValueFactory are for storing strings and
@ -56,7 +57,8 @@ class AstRawString final : public ZoneObject {
V8_EXPORT_PRIVATE bool IsOneByteEqualTo(const char* data) const;
uint16_t FirstCharacter() const;
void Internalize(Isolate* isolate);
void Internalize(Factory* factory);
void Internalize(OffThreadFactory* factory);
// Access the physical representation:
bool is_one_byte() const { return is_one_byte_; }
@ -68,10 +70,9 @@ class AstRawString final : public ZoneObject {
uint32_t Hash() const { return hash_field_ >> Name::kHashShift; }
// This function can be called after internalizing.
V8_INLINE Handle<String> string() const {
DCHECK_NOT_NULL(string_);
V8_INLINE HandleOrOffThreadHandle<String> string() const {
DCHECK(has_string_);
return Handle<String>(string_);
return string_;
}
private:
@ -96,20 +97,18 @@ class AstRawString final : public ZoneObject {
return &next_;
}
void set_string(Handle<String> string) {
void set_string(HandleOrOffThreadHandle<String> string) {
DCHECK(!string.is_null());
DCHECK(!has_string_);
string_ = string.location();
string_ = string;
#ifdef DEBUG
has_string_ = true;
#endif
}
// {string_} is stored as Address* instead of a Handle<String> so it can be
// stored in a union with {next_}.
union {
AstRawString* next_;
Address* string_;
HandleOrOffThreadHandle<String> string_;
};
Vector<const byte> literal_bytes_; // Memory owned by Zone.
@ -144,11 +143,13 @@ class AstConsString final : public ZoneObject {
return segment_.string == nullptr;
}
void Internalize(Isolate* isolate);
template <typename Factory>
void Internalize(Factory* factory);
V8_INLINE Handle<String> string() const {
DCHECK_NOT_NULL(string_);
return Handle<String>(string_);
// This function can be called after internalizing.
V8_INLINE HandleOrOffThreadHandle<String> string() const {
DCHECK(has_string_);
return string_;
}
std::forward_list<const AstRawString*> ToRawStrings() const;
@ -161,12 +162,20 @@ class AstConsString final : public ZoneObject {
AstConsString* next() const { return next_; }
AstConsString** next_location() { return &next_; }
void set_string(HandleOrOffThreadHandle<String> string) {
DCHECK(!string.is_null());
DCHECK(!has_string_);
string_ = string;
#ifdef DEBUG
has_string_ = true;
#endif
}
// {string_} is stored as Address* instead of a Handle<String> so it can be
// stored in a union with {next_}.
void set_string(Handle<String> string) { string_ = string.location(); }
union {
AstConsString* next_;
Address* string_;
HandleOrOffThreadHandle<String> string_;
};
struct Segment {
@ -174,6 +183,13 @@ class AstConsString final : public ZoneObject {
AstConsString::Segment* next;
};
Segment segment_;
#ifdef DEBUG
// (Debug-only:) Verify the object life-cylce: Some functions may only be
// called after internalization (that is, after a v8::internal::String has
// been set); some only before.
bool has_string_ = false;
#endif
};
enum class AstSymbol : uint8_t { kHomeObjectSymbol };
@ -313,7 +329,8 @@ class AstValueFactory {
V8_EXPORT_PRIVATE AstConsString* NewConsString(const AstRawString* str1,
const AstRawString* str2);
V8_EXPORT_PRIVATE void Internalize(Isolate* isolate);
template <typename Factory>
V8_EXPORT_PRIVATE void Internalize(Factory* factory);
#define F(name, str) \
const AstRawString* name##_string() const { \

View File

@ -226,10 +226,6 @@ bool FunctionLiteral::SafeToSkipArgumentsAdaptor() const {
scope()->rest_parameter() == nullptr;
}
Handle<String> FunctionLiteral::name(Isolate* isolate) const {
return raw_name_ ? raw_name_->string() : isolate->factory()->empty_string();
}
int FunctionLiteral::start_position() const {
return scope()->start_position();
}
@ -520,7 +516,8 @@ void ObjectLiteral::BuildBoilerplateDescription(Isolate* isolate) {
Handle<Object> key =
key_literal->AsArrayIndex(&element_index)
? isolate->factory()->NewNumberFromUint(element_index)
: Handle<Object>::cast(key_literal->AsRawPropertyName()->string());
: Handle<Object>::cast(
key_literal->AsRawPropertyName()->string().get<Factory>());
Handle<Object> value = GetBoilerplateValue(property->value(), isolate);
@ -703,11 +700,11 @@ Handle<TemplateObjectDescription> GetTemplateObject::GetOrBuildDescription(
bool raw_and_cooked_match = true;
for (int i = 0; i < raw_strings->length(); ++i) {
if (this->cooked_strings()->at(i) == nullptr ||
*this->raw_strings()->at(i)->string() !=
*this->cooked_strings()->at(i)->string()) {
*this->raw_strings()->at(i)->string().get<Factory>() !=
*this->cooked_strings()->at(i)->string().get<Factory>()) {
raw_and_cooked_match = false;
}
raw_strings->set(i, *this->raw_strings()->at(i)->string());
raw_strings->set(i, *this->raw_strings()->at(i)->string().get<Factory>());
}
Handle<FixedArray> cooked_strings = raw_strings;
if (!raw_and_cooked_match) {
@ -715,7 +712,8 @@ Handle<TemplateObjectDescription> GetTemplateObject::GetOrBuildDescription(
this->cooked_strings()->length(), AllocationType::kOld);
for (int i = 0; i < cooked_strings->length(); ++i) {
if (this->cooked_strings()->at(i) != nullptr) {
cooked_strings->set(i, *this->cooked_strings()->at(i)->string());
cooked_strings->set(
i, *this->cooked_strings()->at(i)->string().get<Factory>());
} else {
cooked_strings->set(i, ReadOnlyRoots(isolate).undefined_value());
}
@ -900,7 +898,7 @@ Handle<Object> Literal::BuildValue(Isolate* isolate) const {
case kHeapNumber:
return isolate->factory()->NewNumber<AllocationType::kOld>(number_);
case kString:
return string_->string();
return string_->string().get<Factory>();
case kSymbol:
return isolate->factory()->home_object_symbol();
case kBoolean:

View File

@ -1176,7 +1176,7 @@ class MaterializedLiteral : public Expression {
// Node for capturing a regexp literal.
class RegExpLiteral final : public MaterializedLiteral {
public:
Handle<String> pattern() const { return pattern_->string(); }
Handle<String> pattern() const { return pattern_->string().get<Factory>(); }
const AstRawString* raw_pattern() const { return pattern_; }
int flags() const { return flags_; }
@ -1493,7 +1493,7 @@ class VariableProxy final : public Expression {
public:
bool IsValidReferenceExpression() const { return !is_new_target(); }
Handle<String> name() const { return raw_name()->string(); }
Handle<String> name() const { return raw_name()->string().get<Factory>(); }
const AstRawString* raw_name() const {
return is_resolved() ? var_->raw_name() : raw_name_;
}
@ -2205,9 +2205,9 @@ class FunctionLiteral final : public Expression {
// Empty handle means that the function does not have a shared name (i.e.
// the name will be set dynamically after creation of the function closure).
MaybeHandle<String> name() const {
return raw_name_ ? raw_name_->string() : MaybeHandle<String>();
return raw_name_ ? raw_name_->string().get<Factory>()
: MaybeHandle<String>();
}
Handle<String> name(Isolate* isolate) const;
bool has_shared_name() const { return raw_name_ != nullptr; }
const AstConsString* raw_name() const { return raw_name_; }
void set_raw_name(const AstConsString* name) { raw_name_ = name; }
@ -2270,7 +2270,7 @@ class FunctionLiteral final : public Expression {
return inferred_name_;
}
if (raw_inferred_name_ != nullptr) {
return raw_inferred_name_->string();
return raw_inferred_name_->string().get<Factory>();
}
UNREACHABLE();
}
@ -2555,7 +2555,7 @@ class ClassLiteral final : public Expression {
class NativeFunctionLiteral final : public Expression {
public:
Handle<String> name() const { return name_->string(); }
Handle<String> name() const { return name_->string().get<Factory>(); }
const AstRawString* raw_name() const { return name_; }
v8::Extension* extension() const { return extension_; }

View File

@ -86,9 +86,10 @@ void SourceTextModuleDescriptor::AddStarExport(
namespace {
Handle<PrimitiveHeapObject> ToStringOrUndefined(Isolate* isolate,
const AstRawString* s) {
return (s == nullptr) ? Handle<PrimitiveHeapObject>::cast(
isolate->factory()->undefined_value())
: Handle<PrimitiveHeapObject>::cast(s->string());
return (s == nullptr)
? Handle<PrimitiveHeapObject>::cast(
isolate->factory()->undefined_value())
: Handle<PrimitiveHeapObject>::cast(s->string().get<Factory>());
}
} // namespace
@ -126,7 +127,7 @@ Handle<FixedArray> SourceTextModuleDescriptor::SerializeRegularExports(
Handle<FixedArray> export_names = isolate->factory()->NewFixedArray(count);
data[index + SourceTextModuleInfo::kRegularExportLocalNameOffset] =
it->second->local_name->string();
it->second->local_name->string().get<Factory>();
data[index + SourceTextModuleInfo::kRegularExportCellIndexOffset] =
handle(Smi::FromInt(it->second->cell_index), isolate);
data[index + SourceTextModuleInfo::kRegularExportExportNamesOffset] =
@ -136,7 +137,7 @@ Handle<FixedArray> SourceTextModuleDescriptor::SerializeRegularExports(
// Collect the export names.
int i = 0;
for (; it != next; ++it) {
export_names->set(i++, *it->second->export_name->string());
export_names->set(i++, *it->second->export_name->string().get<Factory>());
}
DCHECK_EQ(i, count);

View File

@ -587,10 +587,9 @@ void CallPrinter::PrintLiteral(Handle<Object> value, bool quote) {
void CallPrinter::PrintLiteral(const AstRawString* value, bool quote) {
PrintLiteral(value->string(), quote);
PrintLiteral(value->string().get<Factory>(), quote);
}
//-----------------------------------------------------------------------------

View File

@ -835,7 +835,7 @@ Variable* Scope::LookupInScopeInfo(const AstRawString* name, Scope* cache) {
DCHECK_NULL(cache->variables_.Lookup(name));
DisallowHeapAllocation no_gc;
String name_handle = *name->string();
String name_handle = *name->string().get<Factory>();
// The Scope is backed up by ScopeInfo. This means it cannot operate in a
// heap-independent mode, and all strings must be internalized immediately. So
// it's ok to get the Handle<String> here.
@ -2655,7 +2655,7 @@ Variable* ClassScope::LookupPrivateNameInScopeInfo(const AstRawString* name) {
DCHECK_NULL(LookupLocalPrivateName(name));
DisallowHeapAllocation no_gc;
String name_handle = *name->string();
String name_handle = *name->string().get<Factory>();
VariableMode mode;
InitializationFlag init_flag;
MaybeAssignedFlag maybe_assigned_flag;

View File

@ -57,7 +57,7 @@ class Variable final : public ZoneObject {
// parameter initializers.
void set_scope(Scope* scope) { scope_ = scope; }
Handle<String> name() const { return name_->string(); }
Handle<String> name() const { return name_->string().get<Factory>(); }
const AstRawString* raw_name() const { return name_; }
VariableMode mode() const { return VariableModeField::decode(bit_field_); }
void set_mode(VariableMode mode) {

View File

@ -564,7 +564,7 @@ MaybeHandle<SharedFunctionInfo> GenerateUnoptimizedCodeForToplevel(
Isolate* isolate, Handle<Script> script, ParseInfo* parse_info,
AccountingAllocator* allocator, IsCompiledScope* is_compiled_scope) {
EnsureSharedFunctionInfosArrayOnScript(script, parse_info, isolate);
parse_info->ast_value_factory()->Internalize(isolate);
parse_info->ast_value_factory()->Internalize(isolate->factory());
if (!Compiler::Analyze(parse_info)) return MaybeHandle<SharedFunctionInfo>();
DeclarationScope::AllocateScopeInfos(parse_info, isolate);
@ -962,7 +962,7 @@ MaybeHandle<SharedFunctionInfo> FinalizeTopLevel(
UnoptimizedCompilationJob* outer_function_job,
UnoptimizedCompilationJobList* inner_function_jobs) {
// Internalize ast values onto the heap.
parse_info->ast_value_factory()->Internalize(isolate);
parse_info->ast_value_factory()->Internalize(isolate->factory());
// Create shared function infos for top level and shared function infos array
// for inner functions.
@ -1360,7 +1360,7 @@ bool Compiler::Compile(Handle<SharedFunctionInfo> shared_info,
}
// Internalize ast values onto the heap.
parse_info.ast_value_factory()->Internalize(isolate);
parse_info.ast_value_factory()->Internalize(isolate->factory());
// Finalize compilation of the unoptimized bytecode or asm-js data.
if (!FinalizeUnoptimizedCode(&parse_info, isolate, shared_info,
@ -1472,7 +1472,7 @@ bool Compiler::FinalizeBackgroundCompileTask(
}
// Parsing has succeeded - finalize compilation.
parse_info->ast_value_factory()->Internalize(isolate);
parse_info->ast_value_factory()->Internalize(isolate->factory());
if (!FinalizeUnoptimizedCode(parse_info, isolate, shared_info,
task->outer_function_job(),
task->inner_function_jobs())) {

View File

@ -261,7 +261,7 @@ void ScopeIterator::TryParseAndRetrieveScopes(ReparseStrategy strategy) {
if (parsing::ParseAny(info_, shared_info, isolate_) &&
Rewriter::Rewrite(info_)) {
info_->ast_value_factory()->Internalize(isolate_);
info_->ast_value_factory()->Internalize(isolate_->factory());
DeclarationScope* literal_scope = info_->literal()->scope();
ScopeChainRetriever scope_chain_retriever(literal_scope, function_,

View File

@ -761,7 +761,7 @@ bool ParseScript(Isolate* isolate, Handle<Script> script, ParseInfo* parse_info,
success = parsing::ParseProgram(parse_info, script, isolate);
if (success) {
success = Compiler::Analyze(parse_info);
parse_info->ast_value_factory()->Internalize(isolate);
parse_info->ast_value_factory()->Internalize(isolate->factory());
}
}
if (!success) {

View File

@ -1233,7 +1233,7 @@ Handle<String> RenderCallSite(Isolate* isolate, Handle<Object> object,
if (ComputeLocation(isolate, location)) {
ParseInfo info(isolate, *location->shared());
if (parsing::ParseAny(&info, location->shared(), isolate)) {
info.ast_value_factory()->Internalize(isolate);
info.ast_value_factory()->Internalize(isolate->factory());
CallPrinter printer(isolate, location->shared()->IsUserJavaScript());
Handle<String> str = printer.Print(info.literal(), location->start_pos());
*hint = printer.GetErrorHint();
@ -1334,7 +1334,7 @@ Object ErrorUtils::ThrowLoadFromNullOrUndefined(Isolate* isolate,
ParseInfo info(isolate, *location.shared());
if (parsing::ParseAny(&info, location.shared(), isolate)) {
info.ast_value_factory()->Internalize(isolate);
info.ast_value_factory()->Internalize(isolate->factory());
CallPrinter printer(isolate, location.shared()->IsUserJavaScript());
Handle<String> str = printer.Print(info.literal(), location.start_pos());
@ -1351,7 +1351,8 @@ Object ErrorUtils::ThrowLoadFromNullOrUndefined(Isolate* isolate,
maybe_property_name = destructuring_prop->key()
->AsLiteral()
->AsRawPropertyName()
->string();
->string()
.get<Factory>();
// Change the message location to point at the property name.
pos = destructuring_prop->key()->position();
}

View File

@ -203,8 +203,12 @@ class OffThreadHandle {
return OffThreadHandle<T>(T::cast(*other));
}
// Allow OffThreadHandle to act as a MaybeHandle.
bool is_null() const { return obj_.is_null(); }
bool is_null() const {
// TODO(leszeks): This will only work for HeapObjects, figure out a way to
// make is_null work for Object and Smi too.
return obj_.is_null();
}
bool ToHandle(OffThreadHandle<T>* out) {
if (is_null()) return false;
@ -220,6 +224,70 @@ class OffThreadHandle {
T obj_;
};
// A helper class which wraps an normal or off-thread handle, and returns one
// or the other depending on the factory type.
template <typename T>
class HandleOrOffThreadHandle {
public:
HandleOrOffThreadHandle() = default;
template <typename U>
HandleOrOffThreadHandle(Handle<U> handle) // NOLINT
: value_(bit_cast<Address>(static_cast<Handle<T>>(handle).location())) {
#ifdef DEBUG
which_ = kHandle;
#endif
}
template <typename U>
HandleOrOffThreadHandle(OffThreadHandle<U> handle) // NOLINT
: value_(static_cast<OffThreadHandle<T>>(handle)->ptr()) {
#ifdef DEBUG
which_ = kOffThreadHandle;
#endif
}
// To minimize the impact of these handles on main-thread callers, we allow
// them to implicitly convert to Handles.
template <typename U>
operator Handle<U>() {
return get<class Factory>();
}
template <typename FactoryType>
inline FactoryHandle<FactoryType, T> get() {
return get_for(Tag<FactoryType>());
}
inline bool is_null() const { return value_ == 0; }
#ifdef DEBUG
inline bool is_initialized() { return which_ != kUninitialized; }
#endif
private:
// Tagged overloads because we can't specialize the above getter
// without also specializing the class.
template <typename FactoryType>
struct Tag {};
V8_INLINE Handle<T> get_for(Tag<class Factory>) {
DCHECK_NE(which_, kOffThreadHandle);
return Handle<T>(reinterpret_cast<Address*>(value_));
}
V8_INLINE OffThreadHandle<T> get_for(Tag<class OffThreadFactory>) {
DCHECK_NE(which_, kHandle);
return OffThreadHandle<T>(T::unchecked_cast(Object(value_)));
}
// Either handle.location() or off_thread_handle->ptr().
Address value_;
#ifdef DEBUG
enum { kUninitialized, kHandle, kOffThreadHandle } which_;
#endif
};
// ----------------------------------------------------------------------------
// A stack-allocated class that governs a number of local handles.
// After a handle scope has been created, all local handles will be

View File

@ -78,6 +78,103 @@ FactoryBase<Impl>::NewRawTwoByteString(int length, AllocationType allocation) {
return string;
}
template <typename Impl>
FactoryMaybeHandle<Impl, String> FactoryBase<Impl>::NewConsString(
FactoryHandle<Impl, String> left, FactoryHandle<Impl, String> right,
AllocationType allocation) {
if (left->IsThinString()) {
left = handle(ThinString::cast(*left).actual(), impl());
}
if (right->IsThinString()) {
right = handle(ThinString::cast(*right).actual(), impl());
}
int left_length = left->length();
if (left_length == 0) return right;
int right_length = right->length();
if (right_length == 0) return left;
int length = left_length + right_length;
if (length == 2) {
uint16_t c1 = left->Get(0);
uint16_t c2 = right->Get(0);
return impl()->MakeOrFindTwoCharacterString(c1, c2);
}
// Make sure that an out of memory exception is thrown if the length
// of the new cons string is too large.
if (length > String::kMaxLength || length < 0) {
return impl()->template Throw<String>(
impl()->NewInvalidStringLengthError());
}
bool left_is_one_byte = left->IsOneByteRepresentation();
bool right_is_one_byte = right->IsOneByteRepresentation();
bool is_one_byte = left_is_one_byte && right_is_one_byte;
// If the resulting string is small make a flat string.
if (length < ConsString::kMinLength) {
// Note that neither of the two inputs can be a slice because:
STATIC_ASSERT(ConsString::kMinLength <= SlicedString::kMinLength);
DCHECK(left->IsFlat());
DCHECK(right->IsFlat());
STATIC_ASSERT(ConsString::kMinLength <= String::kMaxLength);
if (is_one_byte) {
FactoryHandle<Impl, SeqOneByteString> result =
NewRawOneByteString(length, allocation).ToHandleChecked();
DisallowHeapAllocation no_gc;
uint8_t* dest = result->GetChars(no_gc);
// Copy left part.
const uint8_t* src = left->template GetChars<uint8_t>(no_gc);
CopyChars(dest, src, left_length);
// Copy right part.
src = right->template GetChars<uint8_t>(no_gc);
CopyChars(dest + left_length, src, right_length);
return result;
}
FactoryHandle<Impl, SeqTwoByteString> result =
NewRawTwoByteString(length, allocation).ToHandleChecked();
DisallowHeapAllocation pointer_stays_valid;
uc16* sink = result->GetChars(pointer_stays_valid);
String::WriteToFlat(*left, sink, 0, left->length());
String::WriteToFlat(*right, sink + left->length(), 0, right->length());
return result;
}
return NewConsString(left, right, length, is_one_byte, allocation);
}
template <typename Impl>
FactoryHandle<Impl, String> FactoryBase<Impl>::NewConsString(
FactoryHandle<Impl, String> left, FactoryHandle<Impl, String> right,
int length, bool one_byte, AllocationType allocation) {
DCHECK(!left->IsThinString());
DCHECK(!right->IsThinString());
DCHECK_GE(length, ConsString::kMinLength);
DCHECK_LE(length, String::kMaxLength);
FactoryHandle<Impl, ConsString> result = handle(
ConsString::cast(
one_byte
? NewWithImmortalMap(read_only_roots().cons_one_byte_string_map(),
allocation)
: NewWithImmortalMap(read_only_roots().cons_string_map(),
allocation)),
impl());
DisallowHeapAllocation no_gc;
WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
result->set_hash_field(String::kEmptyHashField);
result->set_length(length);
result->set_first(*left, mode);
result->set_second(*right, mode);
return result;
}
template <typename Impl>
FactoryHandle<Impl, SeqOneByteString>
FactoryBase<Impl>::AllocateRawOneByteInternalizedString(int length,
@ -120,6 +217,12 @@ FactoryBase<Impl>::AllocateRawTwoByteInternalizedString(int length,
return answer;
}
template <typename Impl>
HeapObject FactoryBase<Impl>::NewWithImmortalMap(Map map,
AllocationType allocation) {
return AllocateRawWithImmortalMap(map.instance_size(), allocation, map);
}
template <typename Impl>
HeapObject FactoryBase<Impl>::AllocateRawWithImmortalMap(
int size, AllocationType allocation, Map map,

View File

@ -38,11 +38,21 @@ class V8_EXPORT_PRIVATE FactoryBase {
V8_WARN_UNUSED_RESULT FactoryMaybeHandle<Impl, SeqTwoByteString>
NewRawTwoByteString(int length,
AllocationType allocation = AllocationType::kYoung);
// Create a new cons string object which consists of a pair of strings.
V8_WARN_UNUSED_RESULT FactoryMaybeHandle<Impl, String> NewConsString(
FactoryHandle<Impl, String> left, FactoryHandle<Impl, String> right,
AllocationType allocation = AllocationType::kYoung);
V8_WARN_UNUSED_RESULT FactoryHandle<Impl, String> NewConsString(
FactoryHandle<Impl, String> left, FactoryHandle<Impl, String> right,
int length, bool one_byte,
AllocationType allocation = AllocationType::kYoung);
protected:
HeapObject AllocateRawWithImmortalMap(
int size, AllocationType allocation, Map map,
AllocationAlignment alignment = kWordAligned);
HeapObject NewWithImmortalMap(Map map, AllocationType allocation);
private:
Impl* impl() { return static_cast<Impl*>(this); }

View File

@ -769,6 +769,10 @@ template <class StringTableKey>
Handle<String> Factory::InternalizeStringWithKey(StringTableKey* key) {
return StringTable::LookupKey(isolate(), key);
}
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Handle<String> Factory::InternalizeStringWithKey(OneByteStringKey* key);
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Handle<String> Factory::InternalizeStringWithKey(TwoByteStringKey* key);
MaybeHandle<String> Factory::NewStringFromOneByte(
const Vector<const uint8_t>& string, AllocationType allocation) {
@ -1037,116 +1041,13 @@ Handle<String> Factory::LookupSingleCharacterStringFromCode(uint16_t code) {
return InternalizeString(Vector<const uint16_t>(buffer, 1));
}
static inline Handle<String> MakeOrFindTwoCharacterString(Isolate* isolate,
uint16_t c1,
uint16_t c2) {
Handle<String> Factory::MakeOrFindTwoCharacterString(uint16_t c1, uint16_t c2) {
if ((c1 | c2) <= unibrow::Latin1::kMaxChar) {
uint8_t buffer[] = {static_cast<uint8_t>(c1), static_cast<uint8_t>(c2)};
return isolate->factory()->InternalizeString(
Vector<const uint8_t>(buffer, 2));
return InternalizeString(Vector<const uint8_t>(buffer, 2));
}
uint16_t buffer[] = {c1, c2};
return isolate->factory()->InternalizeString(
Vector<const uint16_t>(buffer, 2));
}
template <typename SinkChar, typename StringType>
Handle<String> ConcatStringContent(Handle<StringType> result,
Handle<String> first,
Handle<String> second) {
DisallowHeapAllocation pointer_stays_valid;
SinkChar* sink = result->GetChars(pointer_stays_valid);
String::WriteToFlat(*first, sink, 0, first->length());
String::WriteToFlat(*second, sink + first->length(), 0, second->length());
return result;
}
MaybeHandle<String> Factory::NewConsString(Handle<String> left,
Handle<String> right) {
if (left->IsThinString()) {
left = handle(Handle<ThinString>::cast(left)->actual(), isolate());
}
if (right->IsThinString()) {
right = handle(Handle<ThinString>::cast(right)->actual(), isolate());
}
int left_length = left->length();
if (left_length == 0) return right;
int right_length = right->length();
if (right_length == 0) return left;
int length = left_length + right_length;
if (length == 2) {
uint16_t c1 = left->Get(0);
uint16_t c2 = right->Get(0);
return MakeOrFindTwoCharacterString(isolate(), c1, c2);
}
// Make sure that an out of memory exception is thrown if the length
// of the new cons string is too large.
if (length > String::kMaxLength || length < 0) {
THROW_NEW_ERROR(isolate(), NewInvalidStringLengthError(), String);
}
bool left_is_one_byte = left->IsOneByteRepresentation();
bool right_is_one_byte = right->IsOneByteRepresentation();
bool is_one_byte = left_is_one_byte && right_is_one_byte;
// If the resulting string is small make a flat string.
if (length < ConsString::kMinLength) {
// Note that neither of the two inputs can be a slice because:
STATIC_ASSERT(ConsString::kMinLength <= SlicedString::kMinLength);
DCHECK(left->IsFlat());
DCHECK(right->IsFlat());
STATIC_ASSERT(ConsString::kMinLength <= String::kMaxLength);
if (is_one_byte) {
Handle<SeqOneByteString> result =
NewRawOneByteString(length).ToHandleChecked();
DisallowHeapAllocation no_gc;
uint8_t* dest = result->GetChars(no_gc);
// Copy left part.
const uint8_t* src =
left->IsExternalString()
? Handle<ExternalOneByteString>::cast(left)->GetChars()
: Handle<SeqOneByteString>::cast(left)->GetChars(no_gc);
for (int i = 0; i < left_length; i++) *dest++ = src[i];
// Copy right part.
src = right->IsExternalString()
? Handle<ExternalOneByteString>::cast(right)->GetChars()
: Handle<SeqOneByteString>::cast(right)->GetChars(no_gc);
for (int i = 0; i < right_length; i++) *dest++ = src[i];
return result;
}
return ConcatStringContent<uc16>(
NewRawTwoByteString(length).ToHandleChecked(), left, right);
}
return NewConsString(left, right, length, is_one_byte);
}
Handle<String> Factory::NewConsString(Handle<String> left, Handle<String> right,
int length, bool one_byte) {
DCHECK(!left->IsThinString());
DCHECK(!right->IsThinString());
DCHECK_GE(length, ConsString::kMinLength);
DCHECK_LE(length, String::kMaxLength);
Handle<ConsString> result(
ConsString::cast(
one_byte ? New(cons_one_byte_string_map(), AllocationType::kYoung)
: New(cons_string_map(), AllocationType::kYoung)),
isolate());
DisallowHeapAllocation no_gc;
WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
result->set_hash_field(String::kEmptyHashField);
result->set_length(length);
result->set_first(*left, mode);
result->set_second(*right, mode);
return result;
return InternalizeString(Vector<const uint16_t>(buffer, 2));
}
Handle<String> Factory::NewSurrogatePairString(uint16_t lead, uint16_t trail) {
@ -1184,7 +1085,7 @@ Handle<String> Factory::NewProperSubString(Handle<String> str, int begin,
// table to prevent creation of many unnecessary strings.
uint16_t c1 = str->Get(begin);
uint16_t c2 = str->Get(begin + 1);
return MakeOrFindTwoCharacterString(isolate(), c1, c2);
return MakeOrFindTwoCharacterString(c1, c2);
}
if (!FLAG_string_slices || length < SlicedString::kMinLength) {

View File

@ -124,7 +124,6 @@ class V8_EXPORT_PRIVATE Factory : public FactoryBase<Factory> {
Handle<T> MakeHandle(T obj) {
return handle(obj, isolate());
}
Handle<Oddball> NewOddball(Handle<Map> map, const char* to_string,
Handle<Object> to_number, const char* type_of,
byte kind);
@ -345,14 +344,6 @@ class V8_EXPORT_PRIVATE Factory : public FactoryBase<Factory> {
// A cache is used for Latin1 codes.
Handle<String> LookupSingleCharacterStringFromCode(uint16_t code);
// Create a new cons string object which consists of a pair of strings.
V8_WARN_UNUSED_RESULT MaybeHandle<String> NewConsString(Handle<String> left,
Handle<String> right);
V8_WARN_UNUSED_RESULT Handle<String> NewConsString(Handle<String> left,
Handle<String> right,
int length, bool one_byte);
// Create or lookup a single characters tring made up of a utf16 surrogate
// pair.
Handle<String> NewSurrogatePairString(uint16_t lead, uint16_t trail);
@ -1074,6 +1065,8 @@ class V8_EXPORT_PRIVATE Factory : public FactoryBase<Factory> {
MaybeHandle<String> NewStringFromTwoByte(const uc16* string, int length,
AllocationType allocation);
Handle<String> MakeOrFindTwoCharacterString(uint16_t c1, uint16_t c2);
// Attempt to find the number in a small cache. If we finds it, return
// the string representation of the number. Otherwise return undefined.
Handle<Object> NumberToStringCacheGet(Object number, int hash);

View File

@ -0,0 +1,25 @@
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_HEAP_OFF_THREAD_FACTORY_INL_H_
#define V8_HEAP_OFF_THREAD_FACTORY_INL_H_
#include "src/heap/off-thread-factory.h"
#include "src/roots/roots-inl.h"
namespace v8 {
namespace internal {
#define ROOT_ACCESSOR(Type, name, CamelName) \
OffThreadHandle<Type> OffThreadFactory::name() { \
return OffThreadHandle<Type>(read_only_roots().name()); \
}
READ_ONLY_ROOT_LIST(ROOT_ACCESSOR)
#undef ROOT_ACCESSOR
#endif // V8_HEAP_OFF_THREAD_FACTORY_INL_H_
} // namespace internal
} // namespace v8

View File

@ -180,6 +180,24 @@ OffThreadHandle<FixedArray> OffThreadFactory::StringWrapperForTest(
return OffThreadHandle<FixedArray>(array);
}
OffThreadHandle<String> OffThreadFactory::MakeOrFindTwoCharacterString(
uint16_t c1, uint16_t c2) {
// TODO(leszeks): Do some real caching here. Also, these strings should be
// internalized.
if ((c1 | c2) <= unibrow::Latin1::kMaxChar) {
OffThreadHandle<SeqOneByteString> ret =
NewRawOneByteString(2, AllocationType::kOld);
ret->SeqOneByteStringSet(0, c1);
ret->SeqOneByteStringSet(1, c2);
return ret;
}
OffThreadHandle<SeqTwoByteString> ret =
NewRawTwoByteString(2, AllocationType::kOld);
ret->SeqTwoByteStringSet(0, c1);
ret->SeqTwoByteStringSet(1, c2);
return ret;
}
HeapObject OffThreadFactory::AllocateRaw(int size, AllocationType allocation,
AllocationAlignment alignment) {
DCHECK(!is_finished);

View File

@ -50,6 +50,11 @@ class V8_EXPORT_PRIVATE OffThreadFactory
ReadOnlyRoots read_only_roots() const { return roots_; }
#define ROOT_ACCESSOR(Type, name, CamelName) \
inline OffThreadHandle<Type> name();
READ_ONLY_ROOT_LIST(ROOT_ACCESSOR)
#undef ROOT_ACCESSOR
void FinishOffThread();
void Publish(Isolate* isolate);
@ -75,6 +80,9 @@ class V8_EXPORT_PRIVATE OffThreadFactory
inline bool EmptyStringRootIsInitialized() { return true; }
// ------
OffThreadHandle<String> MakeOrFindTwoCharacterString(uint16_t c1,
uint16_t c2);
ReadOnlyRoots roots_;
OffThreadSpace space_;
OffThreadLargeObjectSpace lo_space_;

View File

@ -752,7 +752,7 @@ class BytecodeGenerator::GlobalDeclarationsBuilder final : public ZoneObject {
if (!var->is_used()) continue;
if (var->location() != VariableLocation::UNALLOCATED) continue;
if (decl->node_type() == AstNode::kVariableDeclaration) {
data->set(array_index++, *var->raw_name()->string());
data->set(array_index++, *var->raw_name()->string().get<Factory>());
} else {
FunctionLiteral* f = static_cast<FunctionDeclaration*>(decl)->fun();
Handle<Object> sfi(Compiler::GetSharedFunctionInfo(f, script, isolate));

View File

@ -376,7 +376,7 @@ Handle<Object> ConstantArrayBuilder::Entry::ToHandle(Isolate* isolate) const {
// TODO(leszeks): There's probably a better value we could use here.
return isolate->factory()->the_hole_value();
case Tag::kRawString:
return raw_string_->string();
return raw_string_->string().get<Factory>();
case Tag::kHeapNumber:
return isolate->factory()->NewNumber<AllocationType::kOld>(heap_number_);
case Tag::kBigInt:

View File

@ -175,7 +175,7 @@ void InterpreterCompilationJob::CheckAndPrintBytecodeMismatch(
Isolate* isolate, Handle<Script> script, Handle<BytecodeArray> bytecode) {
int first_mismatch = generator()->CheckBytecodeMatches(bytecode);
if (first_mismatch >= 0) {
parse_info()->ast_value_factory()->Internalize(isolate);
parse_info()->ast_value_factory()->Internalize(isolate->factory());
DeclarationScope::AllocateScopeInfos(parse_info(), isolate);
Handle<BytecodeArray> new_bytecode =
@ -184,7 +184,8 @@ void InterpreterCompilationJob::CheckAndPrintBytecodeMismatch(
std::cerr << "Bytecode mismatch";
#ifdef OBJECT_PRINT
std::cerr << " found for function: ";
Handle<String> name = parse_info()->function_name()->string();
Handle<String> name =
parse_info()->function_name()->string().get<Factory>();
if (name->length() == 0) {
std::cerr << "anonymous";
} else {

View File

@ -516,7 +516,8 @@ Handle<ClassBoilerplate> ClassBoilerplate::BuildClassBoilerplate(
desc.AddIndexedProperty(isolate, index, value_kind, value_index);
} else {
Handle<String> name = key_literal->AsRawPropertyName()->string();
Handle<String> name =
key_literal->AsRawPropertyName()->string().get<Factory>();
DCHECK(name->IsInternalizedString());
desc.AddNamedProperty(isolate, name, value_kind, value_index);
}

View File

@ -1057,7 +1057,8 @@ Handle<SourceTextModuleInfo> SourceTextModuleInfo::New(
Handle<FixedArray> module_request_positions =
isolate->factory()->NewFixedArray(size);
for (const auto& elem : descr->module_requests()) {
module_requests->set(elem.second.index, *elem.first->string());
module_requests->set(elem.second.index,
*elem.first->string().get<Factory>());
module_request_positions->set(elem.second.index,
Smi::FromInt(elem.second.position));
}

View File

@ -639,7 +639,7 @@ FunctionLiteral* Parser::DoParseProgram(Isolate* isolate, ParseInfo* info) {
// conflicting var declarations with outer scope-info-backed scopes.
if (info->is_eval()) {
DCHECK(parsing_on_main_thread_);
info->ast_value_factory()->Internalize(isolate);
info->ast_value_factory()->Internalize(isolate->factory());
}
CheckConflictingVarDeclarations(scope);
@ -809,7 +809,7 @@ FunctionLiteral* Parser::ParseFunction(Isolate* isolate, ParseInfo* info,
if (V8_UNLIKELY(FLAG_log_function_events) && result != nullptr) {
double ms = timer.Elapsed().InMillisecondsF();
// We need to make sure that the debug-name is available.
ast_value_factory()->Internalize(isolate);
ast_value_factory()->Internalize(isolate->factory());
DeclarationScope* function_scope = result->scope();
std::unique_ptr<char[]> function_name = result->GetDebugName();
LOG(isolate,

View File

@ -83,7 +83,7 @@ bool ParseFunction(ParseInfo* info, Handle<SharedFunctionInfo> shared_info,
result = parser.ParseFunction(isolate, info, shared_info);
info->set_literal(result);
if (result) {
info->ast_value_factory()->Internalize(isolate);
info->ast_value_factory()->Internalize(isolate->factory());
if (info->is_eval()) {
info->set_allow_eval_cache(parser.allow_eval_cache());
}

View File

@ -16,7 +16,7 @@ namespace internal {
Handle<String> PendingCompilationErrorHandler::MessageDetails::ArgumentString(
Isolate* isolate) const {
if (arg_ != nullptr) return arg_->string();
if (arg_ != nullptr) return arg_->string().get<Factory>();
if (char_arg_ != nullptr) {
return isolate->factory()
->NewStringFromUtf8(CStrVector(char_arg_))
@ -83,7 +83,7 @@ void PendingCompilationErrorHandler::ReportErrors(
} else {
DCHECK(has_pending_error());
// Internalize ast values for throwing the pending error.
ast_value_factory->Internalize(isolate);
ast_value_factory->Internalize(isolate->factory());
ThrowPendingError(isolate, script);
}
}

View File

@ -170,7 +170,7 @@ TEST(InterpreterLoadLiteral) {
builder.LoadLiteral(-2.1e19).Return();
ast_factory.Internalize(isolate);
ast_factory.Internalize(isolate->factory());
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
InterpreterTester tester(isolate, bytecode_array);
@ -189,13 +189,14 @@ TEST(InterpreterLoadLiteral) {
const AstRawString* raw_string = ast_factory.GetOneByteString("String");
builder.LoadLiteral(raw_string).Return();
ast_factory.Internalize(isolate);
ast_factory.Internalize(isolate->factory());
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
InterpreterTester tester(isolate, bytecode_array);
auto callable = tester.GetCallable<>();
Handle<Object> return_val = callable().ToHandleChecked();
CHECK(i::String::cast(*return_val).Equals(*raw_string->string()));
CHECK(i::String::cast(*return_val)
.Equals(*raw_string->string().get<Factory>()));
}
}
@ -222,18 +223,15 @@ TEST(InterpreterLoadStoreRegisters) {
}
}
static const Token::Value kShiftOperators[] = {
Token::Value::SHL, Token::Value::SAR, Token::Value::SHR};
static const Token::Value kArithmeticOperators[] = {
Token::Value::BIT_OR, Token::Value::BIT_XOR, Token::Value::BIT_AND,
Token::Value::SHL, Token::Value::SAR, Token::Value::SHR,
Token::Value::ADD, Token::Value::SUB, Token::Value::MUL,
Token::Value::DIV, Token::Value::MOD};
static double BinaryOpC(Token::Value op, double lhs, double rhs) {
switch (op) {
case Token::Value::ADD:
@ -537,7 +535,7 @@ TEST(InterpreterStringAdd) {
builder.LoadLiteral(test_cases[i].lhs).StoreAccumulatorInRegister(reg);
LoadLiteralForTest(&builder, test_cases[i].rhs);
builder.BinaryOperation(Token::Value::ADD, reg, GetIndex(slot)).Return();
ast_factory.Internalize(isolate);
ast_factory.Internalize(isolate->factory());
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
InterpreterTester tester(isolate, bytecode_array, metadata);
@ -605,7 +603,7 @@ TEST(InterpreterParameter8) {
.BinaryOperation(Token::Value::ADD, builder.Parameter(5), GetIndex(slot5))
.BinaryOperation(Token::Value::ADD, builder.Parameter(6), GetIndex(slot6))
.Return();
ast_factory.Internalize(isolate);
ast_factory.Internalize(isolate->factory());
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
InterpreterTester tester(isolate, bytecode_array, metadata);
@ -745,7 +743,7 @@ TEST(InterpreterBinaryOpTypeFeedback) {
LoadLiteralForTest(&builder, test_case.arg2);
builder.BinaryOperation(test_case.op, reg, GetIndex(slot0)).Return();
ast_factory.Internalize(isolate);
ast_factory.Internalize(isolate->factory());
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
InterpreterTester tester(isolate, bytecode_array, metadata);
@ -851,7 +849,7 @@ TEST(InterpreterBinaryOpSmiTypeFeedback) {
.BinaryOperation(test_case.op, reg, GetIndex(slot0))
.Return();
ast_factory.Internalize(isolate);
ast_factory.Internalize(isolate->factory());
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
InterpreterTester tester(isolate, bytecode_array, metadata);
@ -1032,7 +1030,9 @@ TEST(InterpreterLoadGlobal) {
// Test loading a global.
std::string source(
"var global = 321;\n"
"function " + InterpreterTester::function_name() + "() {\n"
"function " +
InterpreterTester::function_name() +
"() {\n"
" return global;\n"
"}");
InterpreterTester tester(isolate, source.c_str());
@ -1050,7 +1050,9 @@ TEST(InterpreterStoreGlobal) {
// Test storing to a global.
std::string source(
"var global = 321;\n"
"function " + InterpreterTester::function_name() + "() {\n"
"function " +
InterpreterTester::function_name() +
"() {\n"
" global = 999;\n"
"}");
InterpreterTester tester(isolate, source.c_str());
@ -1071,7 +1073,9 @@ TEST(InterpreterCallGlobal) {
// Test calling a global function.
std::string source(
"function g_add(a, b) { return a + b; }\n"
"function " + InterpreterTester::function_name() + "() {\n"
"function " +
InterpreterTester::function_name() +
"() {\n"
" return g_add(5, 10);\n"
"}");
InterpreterTester tester(isolate, source.c_str());
@ -1088,7 +1092,9 @@ TEST(InterpreterLoadUnallocated) {
// Test loading an unallocated global.
std::string source(
"unallocated = 123;\n"
"function " + InterpreterTester::function_name() + "() {\n"
"function " +
InterpreterTester::function_name() +
"() {\n"
" return unallocated;\n"
"}");
InterpreterTester tester(isolate, source.c_str());
@ -1106,7 +1112,9 @@ TEST(InterpreterStoreUnallocated) {
// Test storing to an unallocated global.
std::string source(
"unallocated = 321;\n"
"function " + InterpreterTester::function_name() + "() {\n"
"function " +
InterpreterTester::function_name() +
"() {\n"
" unallocated = 999;\n"
"}");
InterpreterTester tester(isolate, source.c_str());
@ -1138,7 +1146,7 @@ TEST(InterpreterLoadNamedProperty) {
BytecodeArrayBuilder builder(zone, 1, 0, &feedback_spec);
builder.LoadNamedProperty(builder.Receiver(), name, GetIndex(slot)).Return();
ast_factory.Internalize(isolate);
ast_factory.Internalize(isolate->factory());
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
InterpreterTester tester(isolate, bytecode_array, metadata);
@ -1192,7 +1200,7 @@ TEST(InterpreterLoadKeyedProperty) {
builder.LoadLiteral(key)
.LoadKeyedProperty(builder.Receiver(), GetIndex(slot))
.Return();
ast_factory.Internalize(isolate);
ast_factory.Internalize(isolate->factory());
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
InterpreterTester tester(isolate, bytecode_array, metadata);
@ -1235,7 +1243,7 @@ TEST(InterpreterStoreNamedProperty) {
.StoreNamedProperty(builder.Receiver(), name, GetIndex(slot),
LanguageMode::kStrict)
.Return();
ast_factory.Internalize(isolate);
ast_factory.Internalize(isolate->factory());
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
InterpreterTester tester(isolate, bytecode_array, metadata);
@ -1300,7 +1308,7 @@ TEST(InterpreterStoreKeyedProperty) {
.StoreKeyedProperty(builder.Receiver(), Register(0), GetIndex(slot),
i::LanguageMode::kSloppy)
.Return();
ast_factory.Internalize(isolate);
ast_factory.Internalize(isolate->factory());
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
InterpreterTester tester(isolate, bytecode_array, metadata);
@ -1360,7 +1368,7 @@ TEST(InterpreterCall) {
builder.CallProperty(reg, args, call_slot_index);
builder.Return();
ast_factory.Internalize(isolate);
ast_factory.Internalize(isolate->factory());
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
InterpreterTester tester(isolate, bytecode_array, metadata);
@ -1382,7 +1390,7 @@ TEST(InterpreterCall) {
.MoveRegister(builder.Receiver(), args[0]);
builder.CallProperty(reg, args, call_slot_index);
builder.Return();
ast_factory.Internalize(isolate);
ast_factory.Internalize(isolate->factory());
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
InterpreterTester tester(isolate, bytecode_array, metadata);
@ -1416,7 +1424,7 @@ TEST(InterpreterCall) {
builder.Return();
ast_factory.Internalize(isolate);
ast_factory.Internalize(isolate->factory());
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
InterpreterTester tester(isolate, bytecode_array, metadata);
@ -1465,7 +1473,7 @@ TEST(InterpreterCall) {
builder.Return();
ast_factory.Internalize(isolate);
ast_factory.Internalize(isolate->factory());
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
InterpreterTester tester(isolate, bytecode_array, metadata);
@ -1675,15 +1683,15 @@ TEST(InterpreterJumpConstantWith16BitOperand) {
for (int i = 0; i < 6600; i++) {
builder.LoadLiteral(Smi::zero()); // 1-byte
builder.BinaryOperation(Token::Value::ADD, scratch,
GetIndex(slot)); // 6-bytes
builder.StoreAccumulatorInRegister(scratch); // 4-bytes
builder.MoveRegister(scratch, reg); // 6-bytes
GetIndex(slot)); // 6-bytes
builder.StoreAccumulatorInRegister(scratch); // 4-bytes
builder.MoveRegister(scratch, reg); // 6-bytes
}
builder.Bind(&done);
builder.LoadAccumulatorWithRegister(reg);
builder.Return();
ast_factory.Internalize(isolate);
ast_factory.Internalize(isolate->factory());
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
BytecodeArrayIterator iterator(bytecode_array);
@ -1727,7 +1735,7 @@ TEST(InterpreterJumpWith32BitOperand) {
builder.Bind(&done);
builder.Return();
ast_factory.Internalize(isolate);
ast_factory.Internalize(isolate->factory());
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
BytecodeArrayIterator iterator(bytecode_array);
@ -1865,7 +1873,7 @@ TEST(InterpreterHeapNumberComparisons) {
.CompareOperation(comparison, r0, GetIndex(slot))
.Return();
ast_factory.Internalize(isolate);
ast_factory.Internalize(isolate->factory());
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
InterpreterTester tester(isolate, bytecode_array, metadata);
auto callable = tester.GetCallable<>();
@ -1912,7 +1920,7 @@ TEST(InterpreterBigIntComparisons) {
.CompareOperation(comparison, r0, GetIndex(slot))
.Return();
ast_factory.Internalize(isolate);
ast_factory.Internalize(isolate->factory());
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
InterpreterTester tester(isolate, bytecode_array, metadata);
auto callable = tester.GetCallable<>();
@ -1960,7 +1968,7 @@ TEST(InterpreterStringComparisons) {
.CompareOperation(comparison, r0, GetIndex(slot))
.Return();
ast_factory.Internalize(isolate);
ast_factory.Internalize(isolate->factory());
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
InterpreterTester tester(isolate, bytecode_array, metadata);
auto callable = tester.GetCallable<>();
@ -2072,7 +2080,7 @@ TEST(InterpreterMixedComparisons) {
builder.CompareOperation(comparison, lhs_reg, GetIndex(slot))
.Return();
ast_factory.Internalize(isolate);
ast_factory.Internalize(isolate->factory());
Handle<BytecodeArray> bytecode_array =
builder.ToBytecodeArray(isolate);
InterpreterTester tester(isolate, bytecode_array, metadata);
@ -2287,7 +2295,7 @@ TEST(InterpreterTestIn) {
.CompareOperation(Token::Value::IN, r0, GetIndex(slot))
.Return();
ast_factory.Internalize(isolate);
ast_factory.Internalize(isolate->factory());
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
InterpreterTester tester(isolate, bytecode_array, metadata);
auto callable = tester.GetCallable<>();
@ -2345,7 +2353,7 @@ TEST(InterpreterUnaryNotNonBoolean) {
Register r0(0);
LoadLiteralForTest(&builder, object_type_tuples[i].first);
builder.LogicalNot(ToBooleanMode::kConvertToBoolean).Return();
ast_factory.Internalize(isolate);
ast_factory.Internalize(isolate->factory());
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
InterpreterTester tester(isolate, bytecode_array);
auto callable = tester.GetCallable<>();
@ -2431,15 +2439,16 @@ TEST(InterpreterFunctionLiteral) {
Isolate* isolate = handles.main_isolate();
// Test calling a function literal.
std::string source(
"function " + InterpreterTester::function_name() + "(a) {\n"
" return (function(x){ return x + 2; })(a);\n"
"}");
std::string source("function " + InterpreterTester::function_name() +
"(a) {\n"
" return (function(x){ return x + 2; })(a);\n"
"}");
InterpreterTester tester(isolate, source.c_str());
auto callable = tester.GetCallable<Handle<Object>>();
Handle<i::Object> return_val = callable(
Handle<Smi>(Smi::FromInt(3), handles.main_isolate())).ToHandleChecked();
Handle<i::Object> return_val =
callable(Handle<Smi>(Smi::FromInt(3), handles.main_isolate()))
.ToHandleChecked();
CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(5));
}
@ -2449,8 +2458,7 @@ TEST(InterpreterRegExpLiterals) {
Factory* factory = isolate->factory();
std::pair<const char*, Handle<Object>> literals[] = {
std::make_pair("return /abd/.exec('cccabbdd');\n",
factory->null_value()),
std::make_pair("return /abd/.exec('cccabbdd');\n", factory->null_value()),
std::make_pair("return /ab+d/.exec('cccabbdd')[0];\n",
factory->NewStringFromStaticChars("abbd")),
std::make_pair("return /AbC/i.exec('ssaBC')[0];\n",
@ -2477,8 +2485,7 @@ TEST(InterpreterArrayLiterals) {
Factory* factory = isolate->factory();
std::pair<const char*, Handle<Object>> literals[] = {
std::make_pair("return [][0];\n",
factory->undefined_value()),
std::make_pair("return [][0];\n", factory->undefined_value()),
std::make_pair("return [1, 3, 2][1];\n",
handle(Smi::FromInt(3), isolate)),
std::make_pair("return ['a', 'b', 'c'][2];\n",
@ -2488,8 +2495,7 @@ TEST(InterpreterArrayLiterals) {
std::make_pair("return [[1, 2, 3], ['a', 'b', 'c']][1][0];\n",
factory->NewStringFromStaticChars("a")),
std::make_pair("var t = 't'; return [[t, t + 'est'], [1 + t]][0][1];\n",
factory->NewStringFromStaticChars("test"))
};
factory->NewStringFromStaticChars("test"))};
for (size_t i = 0; i < arraysize(literals); i++) {
std::string source(InterpreterTester::SourceForBody(literals[i].first));
@ -2507,8 +2513,7 @@ TEST(InterpreterObjectLiterals) {
Factory* factory = isolate->factory();
std::pair<const char*, Handle<Object>> literals[] = {
std::make_pair("return { }.name;",
factory->undefined_value()),
std::make_pair("return { }.name;", factory->undefined_value()),
std::make_pair("return { name: 'string', val: 9.2 }.name;",
factory->NewStringFromStaticChars("string")),
std::make_pair("var a = 15; return { name: 'string', val: a }.val;",
@ -2636,7 +2641,7 @@ TEST(InterpreterContextVariables) {
" return a + b; }",
handle(Smi::FromInt(30), isolate)),
std::make_pair("'use strict';" + unique_vars.str() +
"eval(); var b = 100; return b;",
"eval(); var b = 100; return b;",
handle(Smi::FromInt(100), isolate)),
};
@ -2718,8 +2723,7 @@ TEST(InterpreterComma) {
std::pair<const char*, Handle<Object>> literals[] = {
std::make_pair("var a; return 0, a;\n", factory->undefined_value()),
std::make_pair("return 'a', 2.2, 3;\n",
handle(Smi::FromInt(3), isolate)),
std::make_pair("return 'a', 2.2, 3;\n", handle(Smi::FromInt(3), isolate)),
std::make_pair("return 'a', 'b', 'c';\n",
factory->NewStringFromStaticChars("c")),
std::make_pair("return 3.2, 2.3, 4.5;\n", factory->NewNumber(4.5)),
@ -2885,10 +2889,8 @@ TEST(InterpreterThrow) {
Factory* factory = isolate->factory();
std::pair<const char*, Handle<Object>> throws[] = {
std::make_pair("throw undefined;\n",
factory->undefined_value()),
std::make_pair("throw 1;\n",
handle(Smi::FromInt(1), isolate)),
std::make_pair("throw undefined;\n", factory->undefined_value()),
std::make_pair("throw 1;\n", handle(Smi::FromInt(1), isolate)),
std::make_pair("throw 'Error';\n",
factory->NewStringFromStaticChars("Error")),
std::make_pair("var a = true; if (a) { throw 'Error'; }\n",
@ -3131,10 +3133,8 @@ TEST(InterpreterConditional) {
Isolate* isolate = handles.main_isolate();
std::pair<const char*, Handle<Object>> conditional[] = {
std::make_pair("return true ? 2 : 3;",
handle(Smi::FromInt(2), isolate)),
std::make_pair("return false ? 2 : 3;",
handle(Smi::FromInt(3), isolate)),
std::make_pair("return true ? 2 : 3;", handle(Smi::FromInt(2), isolate)),
std::make_pair("return false ? 2 : 3;", handle(Smi::FromInt(3), isolate)),
std::make_pair("var a = 1; return a ? 20 : 30;",
handle(Smi::FromInt(20), isolate)),
std::make_pair("var a = 1; return a ? 20 : 30;",
@ -4074,14 +4074,15 @@ TEST(InterpreterLookupSlot) {
Factory* factory = isolate->factory();
// TODO(mythria): Add more tests when we have support for eval/with.
const char* function_prologue = "var f;"
"var x = 1;"
"function f1() {"
" eval(\"function t() {";
const char* function_epilogue = " }; f = t;\");"
"}"
"f1();";
const char* function_prologue =
"var f;"
"var x = 1;"
"function f1() {"
" eval(\"function t() {";
const char* function_epilogue =
" }; f = t;\");"
"}"
"f1();";
std::pair<const char*, Handle<Object>> lookup_slot[] = {
{"return x;", handle(Smi::FromInt(1), isolate)},
@ -4262,18 +4263,19 @@ TEST(InterpreterDeleteLookupSlot) {
Factory* factory = isolate->factory();
// TODO(mythria): Add more tests when we have support for eval/with.
const char* function_prologue = "var f;"
"var x = 1;"
"y = 10;"
"var obj = {val:10};"
"var z = 30;"
"function f1() {"
" var z = 20;"
" eval(\"function t() {";
const char* function_epilogue = " }; f = t;\");"
"}"
"f1();";
const char* function_prologue =
"var f;"
"var x = 1;"
"y = 10;"
"var obj = {val:10};"
"var z = 30;"
"function f1() {"
" var z = 20;"
" eval(\"function t() {";
const char* function_epilogue =
" }; f = t;\");"
"}"
"f1();";
std::pair<const char*, Handle<Object>> delete_lookup_slot[] = {
{"return delete x;", factory->false_value()},

View File

@ -907,7 +907,7 @@ void TestScanRegExp(const char* re_source, const char* expected) {
HashSeed(CcTest::i_isolate()));
const i::AstRawString* current_symbol =
scanner.CurrentSymbol(&ast_value_factory);
ast_value_factory.Internalize(CcTest::i_isolate());
ast_value_factory.Internalize(CcTest::i_isolate()->factory());
i::Handle<i::String> val = current_symbol->string();
i::DisallowHeapAllocation no_alloc;
i::String::FlatContent content = val->GetFlatContent(no_alloc);
@ -1061,7 +1061,7 @@ TEST(ScopeUsesArgumentsSuperThis) {
info.set_allow_lazy_parsing(false);
CHECK(i::parsing::ParseProgram(&info, script, isolate));
CHECK(i::Rewriter::Rewrite(&info));
info.ast_value_factory()->Internalize(isolate);
info.ast_value_factory()->Internalize(isolate->factory());
CHECK(i::DeclarationScope::Analyze(&info));
i::DeclarationScope::AllocateScopeInfos(&info, isolate);
CHECK_NOT_NULL(info.literal());
@ -3312,7 +3312,7 @@ TEST(SerializationOfMaybeAssignmentFlag) {
i::AstValueFactory avf(&zone, isolate->ast_string_constants(),
HashSeed(isolate));
const i::AstRawString* name = avf.GetOneByteString("result");
avf.Internalize(isolate);
avf.Internalize(isolate->factory());
i::Handle<i::String> str = name->string();
CHECK(str->IsInternalizedString());
i::DeclarationScope* script_scope =
@ -3362,7 +3362,7 @@ TEST(IfArgumentsArrayAccessedThenParametersMaybeAssigned) {
i::AstValueFactory avf(&zone, isolate->ast_string_constants(),
HashSeed(isolate));
const i::AstRawString* name_x = avf.GetOneByteString("x");
avf.Internalize(isolate);
avf.Internalize(isolate->factory());
i::DeclarationScope* script_scope =
new (&zone) i::DeclarationScope(&zone, &avf);

View File

@ -7,8 +7,11 @@
#include <limits>
#include <memory>
#include "src/ast/ast-value-factory.h"
#include "src/handles/handles-inl.h"
#include "src/handles/handles.h"
#include "src/heap/off-thread-factory.h"
#include "src/objects/fixed-array.h"
#include "src/objects/string.h"
#include "test/unittests/test-utils.h"
@ -22,10 +25,33 @@ class OffThreadFactoryTest : public TestWithIsolateAndZone {
OffThreadFactory* off_thread_factory() { return &off_thread_factory_; }
// We only internalize strings which are referred to in other slots, so create
// a wrapper pointing at the off_thread_string.
OffThreadHandle<FixedArray> WrapString(OffThreadHandle<String> string) {
// TODO(leszeks): Replace with a different factory method (e.g. FixedArray)
// once OffThreadFactory supports it.
return off_thread_factory()->StringWrapperForTest(string);
}
private:
OffThreadFactory off_thread_factory_;
};
TEST_F(OffThreadFactoryTest, HandleOrOffThreadHandle_IsNullWhenConstructed) {
// Default constructed HandleOrOffThreadHandles should be considered both null
// and uninitialized.
EXPECT_TRUE(HandleOrOffThreadHandle<HeapObject>().is_null());
#ifdef DEBUG
EXPECT_TRUE(!HandleOrOffThreadHandle<HeapObject>().is_initialized());
#endif
// Default constructed HandleOrOffThreadHandles should work as both null
// handles and null off-thread handles.
EXPECT_TRUE(HandleOrOffThreadHandle<HeapObject>().get<Factory>().is_null());
EXPECT_TRUE(
HandleOrOffThreadHandle<HeapObject>().get<OffThreadFactory>().is_null());
}
TEST_F(OffThreadFactoryTest, OneByteInternalizedString_IsAddedToStringTable) {
Vector<const uint8_t> string_vector = StaticCharVector("foo");
uint32_t hash_field = StringHasher::HashSequentialString<uint8_t>(
@ -35,10 +61,6 @@ TEST_F(OffThreadFactoryTest, OneByteInternalizedString_IsAddedToStringTable) {
off_thread_factory()->NewOneByteInternalizedString(string_vector,
hash_field);
// We only internalize strings which are referred to in other slots, so create
// a wrapper pointing at the off_thread_string.
// TODO(leszeks): Replace with a different holder (e.g. FixedArray) once
// OffThreadFactory supports it.
OffThreadHandle<FixedArray> off_thread_wrapper =
off_thread_factory()->StringWrapperForTest(off_thread_string);
@ -77,14 +99,10 @@ TEST_F(OffThreadFactoryTest,
off_thread_factory()->NewOneByteInternalizedString(string_vector,
hash_field);
// We only internalize strings which are referred to in other slots, so create
// a wrapper pointing at the off_thread_string.
// TODO(leszeks): Replace with a different holder (e.g. FixedArray) once
// OffThreadFactory supports it.
OffThreadHandle<FixedArray> off_thread_wrapper_1 =
off_thread_factory()->StringWrapperForTest(off_thread_string_1);
WrapString(off_thread_string_1);
OffThreadHandle<FixedArray> off_thread_wrapper_2 =
off_thread_factory()->StringWrapperForTest(off_thread_string_2);
WrapString(off_thread_string_2);
off_thread_factory()->FinishOffThread();
@ -100,5 +118,54 @@ TEST_F(OffThreadFactoryTest,
EXPECT_EQ(*string_1, *string_2);
}
TEST_F(OffThreadFactoryTest, AstRawString_IsInternalized) {
AstValueFactory ast_value_factory(zone(), isolate()->ast_string_constants(),
HashSeed(isolate()));
const AstRawString* raw_string = ast_value_factory.GetOneByteString("foo");
ast_value_factory.Internalize(off_thread_factory());
OffThreadHandle<FixedArray> off_thread_wrapper =
WrapString(raw_string->string().get<OffThreadFactory>());
off_thread_factory()->FinishOffThread();
Handle<FixedArray> wrapper = handle(*off_thread_wrapper, isolate());
off_thread_factory()->Publish(isolate());
Handle<String> string = handle(String::cast(wrapper->get(0)), isolate());
EXPECT_TRUE(string->IsOneByteEqualTo(CStrVector("foo")));
EXPECT_TRUE(string->IsInternalizedString());
}
TEST_F(OffThreadFactoryTest, AstConsString_CreatesConsString) {
AstValueFactory ast_value_factory(zone(), isolate()->ast_string_constants(),
HashSeed(isolate()));
const AstRawString* foo_string = ast_value_factory.GetOneByteString("foo");
const AstRawString* bar_string =
ast_value_factory.GetOneByteString("bar-plus-padding-for-length");
const AstConsString* foobar_string =
ast_value_factory.NewConsString(foo_string, bar_string);
ast_value_factory.Internalize(off_thread_factory());
OffThreadHandle<FixedArray> off_thread_wrapper =
WrapString(foobar_string->string().get<OffThreadFactory>());
off_thread_factory()->FinishOffThread();
Handle<FixedArray> wrapper = handle(*off_thread_wrapper, isolate());
off_thread_factory()->Publish(isolate());
Handle<String> string = handle(String::cast(wrapper->get(0)), isolate());
EXPECT_TRUE(string->IsConsString());
EXPECT_TRUE(string->Equals(*isolate()->factory()->NewStringFromStaticChars(
"foobar-plus-padding-for-length")));
}
} // namespace internal
} // namespace v8

View File

@ -447,7 +447,7 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
// Generate BytecodeArray.
scope.SetScriptScopeInfo(factory->NewScopeInfo(1));
ast_factory.Internalize(isolate());
ast_factory.Internalize(isolate()->factory());
Handle<BytecodeArray> the_array = builder.ToBytecodeArray(isolate());
CHECK_EQ(the_array->frame_size(),
builder.total_register_count() * kSystemPointerSize);
@ -493,7 +493,6 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
#undef CHECK_BYTECODE_PRESENT
}
TEST_F(BytecodeArrayBuilderTest, FrameSizesLookGood) {
for (int locals = 0; locals < 5; locals++) {
for (int temps = 0; temps < 3; temps++) {
@ -520,7 +519,6 @@ TEST_F(BytecodeArrayBuilderTest, FrameSizesLookGood) {
}
}
TEST_F(BytecodeArrayBuilderTest, RegisterValues) {
int index = 1;
@ -532,7 +530,6 @@ TEST_F(BytecodeArrayBuilderTest, RegisterValues) {
CHECK_EQ(actual_index, index);
}
TEST_F(BytecodeArrayBuilderTest, Parameters) {
BytecodeArrayBuilder builder(zone(), 10, 0);
@ -541,7 +538,6 @@ TEST_F(BytecodeArrayBuilderTest, Parameters) {
CHECK_EQ(param8.index() - receiver.index(), 9);
}
TEST_F(BytecodeArrayBuilderTest, Constants) {
BytecodeArrayBuilder builder(zone(), 1, 0);
AstValueFactory ast_factory(zone(), isolate()->ast_string_constants(),
@ -564,7 +560,7 @@ TEST_F(BytecodeArrayBuilderTest, Constants) {
.LoadLiteral(nan)
.Return();
ast_factory.Internalize(isolate());
ast_factory.Internalize(isolate()->factory());
Handle<BytecodeArray> array = builder.ToBytecodeArray(isolate());
// Should only have one entry for each identical constant.
EXPECT_EQ(4, array->constant_pool().length());
@ -695,7 +691,6 @@ TEST_F(BytecodeArrayBuilderTest, ForwardJumps) {
iterator.Advance();
}
TEST_F(BytecodeArrayBuilderTest, BackwardJumps) {
BytecodeArrayBuilder builder(zone(), 1, 1);

View File

@ -73,7 +73,7 @@ TEST_F(BytecodeArrayIteratorTest, IteratesBytecodeArray) {
.Return();
// Test iterator sees the expected output from the builder.
ast_factory.Internalize(isolate());
ast_factory.Internalize(isolate()->factory());
BytecodeArrayIterator iterator(builder.ToBytecodeArray(isolate()));
const int kPrefixByteSize = 1;
int offset = 0;

View File

@ -66,7 +66,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, InvalidBeforeStart) {
.Debugger()
.Return();
ast_factory.Internalize(isolate());
ast_factory.Internalize(isolate()->factory());
Handle<BytecodeArray> bytecodeArray = builder.ToBytecodeArray(isolate());
BytecodeArrayRandomIterator iterator(bytecodeArray, zone());
@ -120,7 +120,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, InvalidAfterEnd) {
.Debugger()
.Return();
ast_factory.Internalize(isolate());
ast_factory.Internalize(isolate()->factory());
Handle<BytecodeArray> bytecodeArray = builder.ToBytecodeArray(isolate());
BytecodeArrayRandomIterator iterator(bytecodeArray, zone());
@ -174,7 +174,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, AccessesFirst) {
.Debugger()
.Return();
ast_factory.Internalize(isolate());
ast_factory.Internalize(isolate()->factory());
Handle<BytecodeArray> bytecodeArray = builder.ToBytecodeArray(isolate());
BytecodeArrayRandomIterator iterator(bytecodeArray, zone());
@ -233,7 +233,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, AccessesLast) {
.Debugger()
.Return();
ast_factory.Internalize(isolate());
ast_factory.Internalize(isolate()->factory());
Handle<BytecodeArray> bytecodeArray = builder.ToBytecodeArray(isolate());
BytecodeArrayRandomIterator iterator(bytecodeArray, zone());
@ -294,7 +294,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, RandomAccessValid) {
.Return();
// Test iterator sees the expected output from the builder.
ast_factory.Internalize(isolate());
ast_factory.Internalize(isolate()->factory());
BytecodeArrayRandomIterator iterator(builder.ToBytecodeArray(isolate()),
zone());
const int kPrefixByteSize = 1;
@ -480,7 +480,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, IteratesBytecodeArray) {
.Return();
// Test iterator sees the expected output from the builder.
ast_factory.Internalize(isolate());
ast_factory.Internalize(isolate()->factory());
BytecodeArrayRandomIterator iterator(builder.ToBytecodeArray(isolate()),
zone());
const int kPrefixByteSize = 1;
@ -761,7 +761,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, IteratesBytecodeArrayBackwards) {
.Return();
// Test iterator sees the expected output from the builder.
ast_factory.Internalize(isolate());
ast_factory.Internalize(isolate()->factory());
Handle<BytecodeArray> bytecodeArray = builder.ToBytecodeArray(isolate());
BytecodeArrayRandomIterator iterator(bytecodeArray, zone());
const int kPrefixByteSize = 1;

View File

@ -40,7 +40,7 @@ TEST_F(ConstantArrayBuilderTest, AllocateAllEntries) {
builder.Insert(i + 0.5);
}
CHECK_EQ(builder.size(), k16BitCapacity);
ast_factory.Internalize(isolate());
ast_factory.Internalize(isolate()->factory());
for (size_t i = 0; i < k16BitCapacity; i++) {
CHECK_EQ(
Handle<HeapNumber>::cast(builder.At(i, isolate()).ToHandleChecked())
@ -90,7 +90,7 @@ TEST_F(ConstantArrayBuilderTest, ToLargeFixedArrayWithReservations) {
for (int i = 0; i < kNumberOfElements; i++) {
builder.CommitReservedEntry(builder.CreateReservedEntry(), Smi::FromInt(i));
}
ast_factory.Internalize(isolate());
ast_factory.Internalize(isolate()->factory());
Handle<FixedArray> constant_array = builder.ToFixedArray(isolate());
ASSERT_EQ(kNumberOfElements, constant_array->length());
for (int i = 0; i < kNumberOfElements; i++) {
@ -149,7 +149,7 @@ TEST_F(ConstantArrayBuilderTest, AllocateEntriesWithIdx8Reservations) {
builder.DiscardReservedEntry(OperandSize::kByte);
}
ast_factory.Internalize(isolate());
ast_factory.Internalize(isolate()->factory());
Handle<FixedArray> constant_array = builder.ToFixedArray(isolate());
CHECK_EQ(constant_array->length(),
static_cast<int>(2 * k8BitCapacity + reserved));
@ -203,7 +203,7 @@ TEST_F(ConstantArrayBuilderTest, AllocateEntriesWithWideReservations) {
CHECK_EQ(builder.size(), i + 1);
}
ast_factory.Internalize(isolate());
ast_factory.Internalize(isolate()->factory());
Handle<FixedArray> constant_array = builder.ToFixedArray(isolate());
CHECK_EQ(constant_array->length(),
static_cast<int>(k8BitCapacity + reserved));
@ -234,7 +234,7 @@ TEST_F(ConstantArrayBuilderTest, GapFilledWhenLowReservationCommitted) {
Smi::FromInt(static_cast<int>(i)));
CHECK_EQ(builder.size(), 2 * k8BitCapacity);
}
ast_factory.Internalize(isolate());
ast_factory.Internalize(isolate()->factory());
Handle<FixedArray> constant_array = builder.ToFixedArray(isolate());
CHECK_EQ(constant_array->length(), static_cast<int>(2 * k8BitCapacity));
for (size_t i = 0; i < k8BitCapacity; i++) {
@ -300,7 +300,7 @@ TEST_F(ConstantArrayBuilderTest, HolesWithUnusedReservations) {
builder.DiscardReservedEntry(OperandSize::kByte);
}
ast_factory.Internalize(isolate());
ast_factory.Internalize(isolate()->factory());
Handle<FixedArray> constant_array = builder.ToFixedArray(isolate());
CHECK_EQ(constant_array->length(), k8BitCapacity + 1);
for (int i = kNumberOfHoles; i < k8BitCapacity; i++) {
@ -343,7 +343,7 @@ TEST_F(ConstantArrayBuilderTest, ReservationsAtAllScales) {
builder.DiscardReservedEntry(OperandSize::kQuad);
}
ast_factory.Internalize(isolate());
ast_factory.Internalize(isolate()->factory());
Handle<FixedArray> constant_array = builder.ToFixedArray(isolate());
CHECK_EQ(constant_array->length(), 65537);
int count = 1;