Renamed "symbols" to "internalized strings" throughout the code base,
in preparation of the introduction of ES6 'symbols' (aka private/unique names). The SymbolTable became the StringTable. I also made sure to adapt all comments. The only remaining use of the term "symbol" (other than unrelated uses in the parser and such) is now 'NewSymbol' in the API and the 'V8.KeyedLoadGenericSymbol' counter, changing which might break embedders. The one functional change in this CL is that I removed the former 'empty_string' constant, since it is redundant given the 'empty_symbol' constant that we also had (and both were used inconsistently). R=yangguo@chromium.org BUG= Review URL: https://codereview.chromium.org/12210083 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13781 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
3b7417a506
commit
55f93b5532
@ -4221,7 +4221,7 @@ class Internals {
|
||||
static const int kNullValueRootIndex = 7;
|
||||
static const int kTrueValueRootIndex = 8;
|
||||
static const int kFalseValueRootIndex = 9;
|
||||
static const int kEmptySymbolRootIndex = 119;
|
||||
static const int kEmptyStringRootIndex = 118;
|
||||
|
||||
static const int kNodeClassIdOffset = 1 * kApiPointerSize;
|
||||
static const int kNodeFlagsOffset = 1 * kApiPointerSize + 3;
|
||||
@ -4671,7 +4671,7 @@ Local<String> String::Empty(Isolate* isolate) {
|
||||
typedef internal::Object* S;
|
||||
typedef internal::Internals I;
|
||||
if (!I::IsInitialized(isolate)) return Empty();
|
||||
S* slot = I::GetRoot(isolate, I::kEmptySymbolRootIndex);
|
||||
S* slot = I::GetRoot(isolate, I::kEmptyStringRootIndex);
|
||||
return Local<String>(reinterpret_cast<String*>(slot));
|
||||
}
|
||||
|
||||
|
@ -103,7 +103,7 @@ MaybeObject* Accessors::ArraySetLength(JSObject* object, Object* value, void*) {
|
||||
// causes an infinite loop.
|
||||
if (!object->IsJSArray()) {
|
||||
return object->SetLocalPropertyIgnoreAttributes(
|
||||
isolate->heap()->length_symbol(), value, NONE);
|
||||
isolate->heap()->length_string(), value, NONE);
|
||||
}
|
||||
|
||||
value = FlattenNumber(value);
|
||||
@ -475,7 +475,7 @@ MaybeObject* Accessors::FunctionSetPrototype(JSObject* object,
|
||||
if (function_raw == NULL) return heap->undefined_value();
|
||||
if (!function_raw->should_have_prototype()) {
|
||||
// Since we hit this accessor, object will have no prototype property.
|
||||
return object->SetLocalPropertyIgnoreAttributes(heap->prototype_symbol(),
|
||||
return object->SetLocalPropertyIgnoreAttributes(heap->prototype_string(),
|
||||
value_raw,
|
||||
NONE);
|
||||
}
|
||||
@ -503,7 +503,7 @@ MaybeObject* Accessors::FunctionSetPrototype(JSObject* object,
|
||||
|
||||
if (is_observed && !old_value->SameValue(*value)) {
|
||||
JSObject::EnqueueChangeRecord(
|
||||
function, "updated", isolate->factory()->prototype_symbol(), old_value);
|
||||
function, "updated", isolate->factory()->prototype_string(), old_value);
|
||||
}
|
||||
|
||||
return *function;
|
||||
@ -630,7 +630,7 @@ MaybeObject* Accessors::FunctionGetArguments(Object* object, void*) {
|
||||
// If there is an arguments variable in the stack, we return that.
|
||||
Handle<ScopeInfo> scope_info(function->shared()->scope_info());
|
||||
int index = scope_info->StackSlotIndex(
|
||||
isolate->heap()->arguments_symbol());
|
||||
isolate->heap()->arguments_string());
|
||||
if (index >= 0) {
|
||||
Handle<Object> arguments(frame->GetExpression(index), isolate);
|
||||
if (!arguments->IsArgumentsMarker()) return *arguments;
|
||||
@ -826,7 +826,7 @@ MaybeObject* Accessors::ObjectSetPrototype(JSObject* receiver_raw,
|
||||
isolate);
|
||||
if (!new_value->SameValue(*old_value)) {
|
||||
JSObject::EnqueueChangeRecord(receiver, "prototype",
|
||||
isolate->factory()->Proto_symbol(),
|
||||
isolate->factory()->proto_string(),
|
||||
old_value);
|
||||
}
|
||||
return *hresult;
|
||||
|
79
src/api.cc
79
src/api.cc
@ -1785,7 +1785,7 @@ v8::Local<Value> v8::TryCatch::StackTrace() const {
|
||||
if (!raw_obj->IsJSObject()) return v8::Local<Value>();
|
||||
i::HandleScope scope(isolate_);
|
||||
i::Handle<i::JSObject> obj(i::JSObject::cast(raw_obj), isolate_);
|
||||
i::Handle<i::String> name = isolate_->factory()->stack_symbol();
|
||||
i::Handle<i::String> name = isolate_->factory()->stack_string();
|
||||
if (!obj->HasProperty(*name)) return v8::Local<Value>();
|
||||
i::Handle<i::Object> value = i::GetProperty(isolate_, obj, name);
|
||||
if (value.is_null()) return v8::Local<Value>();
|
||||
@ -1899,7 +1899,8 @@ static i::Handle<i::Object> CallV8HeapFunction(const char* name,
|
||||
i::Handle<i::Object> argv[],
|
||||
bool* has_pending_exception) {
|
||||
i::Isolate* isolate = i::Isolate::Current();
|
||||
i::Handle<i::String> fmt_str = isolate->factory()->LookupUtf8Symbol(name);
|
||||
i::Handle<i::String> fmt_str =
|
||||
isolate->factory()->InternalizeUtf8String(name);
|
||||
i::Object* object_fun =
|
||||
isolate->js_builtins_object()->GetPropertyNoExceptionThrown(*fmt_str);
|
||||
i::Handle<i::JSFunction> fun =
|
||||
@ -2292,7 +2293,7 @@ bool Value::IsDate() const {
|
||||
i::Isolate* isolate = i::Isolate::Current();
|
||||
if (IsDeadCheck(isolate, "v8::Value::IsDate()")) return false;
|
||||
i::Handle<i::Object> obj = Utils::OpenHandle(this);
|
||||
return obj->HasSpecificClassOf(isolate->heap()->Date_symbol());
|
||||
return obj->HasSpecificClassOf(isolate->heap()->Date_string());
|
||||
}
|
||||
|
||||
|
||||
@ -2300,7 +2301,7 @@ bool Value::IsStringObject() const {
|
||||
i::Isolate* isolate = i::Isolate::Current();
|
||||
if (IsDeadCheck(isolate, "v8::Value::IsStringObject()")) return false;
|
||||
i::Handle<i::Object> obj = Utils::OpenHandle(this);
|
||||
return obj->HasSpecificClassOf(isolate->heap()->String_symbol());
|
||||
return obj->HasSpecificClassOf(isolate->heap()->String_string());
|
||||
}
|
||||
|
||||
|
||||
@ -2308,16 +2309,16 @@ bool Value::IsNumberObject() const {
|
||||
i::Isolate* isolate = i::Isolate::Current();
|
||||
if (IsDeadCheck(isolate, "v8::Value::IsNumberObject()")) return false;
|
||||
i::Handle<i::Object> obj = Utils::OpenHandle(this);
|
||||
return obj->HasSpecificClassOf(isolate->heap()->Number_symbol());
|
||||
return obj->HasSpecificClassOf(isolate->heap()->Number_string());
|
||||
}
|
||||
|
||||
|
||||
static i::Object* LookupBuiltin(i::Isolate* isolate,
|
||||
const char* builtin_name) {
|
||||
i::Handle<i::String> symbol =
|
||||
isolate->factory()->LookupUtf8Symbol(builtin_name);
|
||||
i::Handle<i::String> string =
|
||||
isolate->factory()->InternalizeUtf8String(builtin_name);
|
||||
i::Handle<i::JSBuiltinsObject> builtins = isolate->js_builtins_object();
|
||||
return builtins->GetPropertyNoExceptionThrown(*symbol);
|
||||
return builtins->GetPropertyNoExceptionThrown(*string);
|
||||
}
|
||||
|
||||
|
||||
@ -2355,7 +2356,7 @@ bool Value::IsBooleanObject() const {
|
||||
i::Isolate* isolate = i::Isolate::Current();
|
||||
if (IsDeadCheck(isolate, "v8::Value::IsBooleanObject()")) return false;
|
||||
i::Handle<i::Object> obj = Utils::OpenHandle(this);
|
||||
return obj->HasSpecificClassOf(isolate->heap()->Boolean_symbol());
|
||||
return obj->HasSpecificClassOf(isolate->heap()->Boolean_string());
|
||||
}
|
||||
|
||||
|
||||
@ -2547,7 +2548,7 @@ void v8::Date::CheckCast(v8::Value* that) {
|
||||
i::Isolate* isolate = i::Isolate::Current();
|
||||
if (IsDeadCheck(isolate, "v8::Date::Cast()")) return;
|
||||
i::Handle<i::Object> obj = Utils::OpenHandle(that);
|
||||
ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Date_symbol()),
|
||||
ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Date_string()),
|
||||
"v8::Date::Cast()",
|
||||
"Could not convert to date");
|
||||
}
|
||||
@ -2557,7 +2558,7 @@ void v8::StringObject::CheckCast(v8::Value* that) {
|
||||
i::Isolate* isolate = i::Isolate::Current();
|
||||
if (IsDeadCheck(isolate, "v8::StringObject::Cast()")) return;
|
||||
i::Handle<i::Object> obj = Utils::OpenHandle(that);
|
||||
ApiCheck(obj->HasSpecificClassOf(isolate->heap()->String_symbol()),
|
||||
ApiCheck(obj->HasSpecificClassOf(isolate->heap()->String_string()),
|
||||
"v8::StringObject::Cast()",
|
||||
"Could not convert to StringObject");
|
||||
}
|
||||
@ -2567,7 +2568,7 @@ void v8::NumberObject::CheckCast(v8::Value* that) {
|
||||
i::Isolate* isolate = i::Isolate::Current();
|
||||
if (IsDeadCheck(isolate, "v8::NumberObject::Cast()")) return;
|
||||
i::Handle<i::Object> obj = Utils::OpenHandle(that);
|
||||
ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Number_symbol()),
|
||||
ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Number_string()),
|
||||
"v8::NumberObject::Cast()",
|
||||
"Could not convert to NumberObject");
|
||||
}
|
||||
@ -2577,7 +2578,7 @@ void v8::BooleanObject::CheckCast(v8::Value* that) {
|
||||
i::Isolate* isolate = i::Isolate::Current();
|
||||
if (IsDeadCheck(isolate, "v8::BooleanObject::Cast()")) return;
|
||||
i::Handle<i::Object> obj = Utils::OpenHandle(that);
|
||||
ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Boolean_symbol()),
|
||||
ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Boolean_string()),
|
||||
"v8::BooleanObject::Cast()",
|
||||
"Could not convert to BooleanObject");
|
||||
}
|
||||
@ -3367,10 +3368,11 @@ bool v8::Object::SetHiddenValue(v8::Handle<v8::String> key,
|
||||
i::HandleScope scope(isolate);
|
||||
i::Handle<i::JSObject> self = Utils::OpenHandle(this);
|
||||
i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
|
||||
i::Handle<i::String> key_symbol = isolate->factory()->LookupSymbol(key_obj);
|
||||
i::Handle<i::String> key_string =
|
||||
isolate->factory()->InternalizeString(key_obj);
|
||||
i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
|
||||
i::Handle<i::Object> result =
|
||||
i::JSObject::SetHiddenProperty(self, key_symbol, value_obj);
|
||||
i::JSObject::SetHiddenProperty(self, key_string, value_obj);
|
||||
return *result == *self;
|
||||
}
|
||||
|
||||
@ -3382,8 +3384,8 @@ v8::Local<v8::Value> v8::Object::GetHiddenValue(v8::Handle<v8::String> key) {
|
||||
ENTER_V8(isolate);
|
||||
i::Handle<i::JSObject> self = Utils::OpenHandle(this);
|
||||
i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
|
||||
i::Handle<i::String> key_symbol = FACTORY->LookupSymbol(key_obj);
|
||||
i::Handle<i::Object> result(self->GetHiddenProperty(*key_symbol), isolate);
|
||||
i::Handle<i::String> key_string = FACTORY->InternalizeString(key_obj);
|
||||
i::Handle<i::Object> result(self->GetHiddenProperty(*key_string), isolate);
|
||||
if (result->IsUndefined()) return v8::Local<v8::Value>();
|
||||
return Utils::ToLocal(result);
|
||||
}
|
||||
@ -3396,8 +3398,8 @@ bool v8::Object::DeleteHiddenValue(v8::Handle<v8::String> key) {
|
||||
i::HandleScope scope(isolate);
|
||||
i::Handle<i::JSObject> self = Utils::OpenHandle(this);
|
||||
i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
|
||||
i::Handle<i::String> key_symbol = FACTORY->LookupSymbol(key_obj);
|
||||
self->DeleteHiddenProperty(*key_symbol);
|
||||
i::Handle<i::String> key_string = FACTORY->InternalizeString(key_obj);
|
||||
self->DeleteHiddenProperty(*key_string);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -4827,7 +4829,7 @@ Local<String> v8::String::Empty() {
|
||||
return v8::Local<String>();
|
||||
}
|
||||
LOG_API(isolate, "String::Empty()");
|
||||
return Utils::ToLocal(isolate->factory()->empty_symbol());
|
||||
return Utils::ToLocal(isolate->factory()->empty_string());
|
||||
}
|
||||
|
||||
|
||||
@ -4952,7 +4954,7 @@ bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
|
||||
}
|
||||
CHECK(resource && resource->data());
|
||||
bool result = obj->MakeExternal(resource);
|
||||
if (result && !obj->IsSymbol()) {
|
||||
if (result && !obj->IsInternalizedString()) {
|
||||
isolate->heap()->external_string_table()->AddString(*obj);
|
||||
}
|
||||
return result;
|
||||
@ -4989,7 +4991,7 @@ bool v8::String::MakeExternal(
|
||||
}
|
||||
CHECK(resource && resource->data());
|
||||
bool result = obj->MakeExternal(resource);
|
||||
if (result && !obj->IsSymbol()) {
|
||||
if (result && !obj->IsInternalizedString()) {
|
||||
isolate->heap()->external_string_table()->AddString(*obj);
|
||||
}
|
||||
return result;
|
||||
@ -5127,8 +5129,9 @@ void v8::Date::DateTimeConfigurationChangeNotification() {
|
||||
|
||||
i::HandleScope scope(isolate);
|
||||
// Get the function ResetDateCache (defined in date.js).
|
||||
i::Handle<i::String> func_name_str = isolate->factory()->LookupOneByteSymbol(
|
||||
STATIC_ASCII_VECTOR("ResetDateCache"));
|
||||
i::Handle<i::String> func_name_str =
|
||||
isolate->factory()->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("ResetDateCache"));
|
||||
i::MaybeObject* result =
|
||||
isolate->js_builtins_object()->GetProperty(*func_name_str);
|
||||
i::Object* object_func;
|
||||
@ -5158,7 +5161,7 @@ static i::Handle<i::String> RegExpFlagsToString(RegExp::Flags flags) {
|
||||
if ((flags & RegExp::kMultiline) != 0) flags_buf[num_flags++] = 'm';
|
||||
if ((flags & RegExp::kIgnoreCase) != 0) flags_buf[num_flags++] = 'i';
|
||||
ASSERT(num_flags <= static_cast<int>(ARRAY_SIZE(flags_buf)));
|
||||
return FACTORY->LookupOneByteSymbol(
|
||||
return FACTORY->InternalizeOneByteString(
|
||||
i::Vector<const uint8_t>(flags_buf, num_flags));
|
||||
}
|
||||
|
||||
@ -5263,7 +5266,7 @@ Local<String> v8::String::NewSymbol(const char* data, int length) {
|
||||
LOG_API(isolate, "String::NewSymbol(char)");
|
||||
ENTER_V8(isolate);
|
||||
if (length == -1) length = i::StrLength(data);
|
||||
i::Handle<i::String> result = isolate->factory()->LookupUtf8Symbol(
|
||||
i::Handle<i::String> result = isolate->factory()->InternalizeUtf8String(
|
||||
i::Vector<const char>(data, length));
|
||||
return Utils::ToLocal(result);
|
||||
}
|
||||
@ -5975,7 +5978,7 @@ Local<Value> Debug::GetMirror(v8::Handle<v8::Value> obj) {
|
||||
i::Debug* isolate_debug = isolate->debug();
|
||||
isolate_debug->Load();
|
||||
i::Handle<i::JSObject> debug(isolate_debug->debug_context()->global_object());
|
||||
i::Handle<i::String> name = isolate->factory()->LookupOneByteSymbol(
|
||||
i::Handle<i::String> name = isolate->factory()->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("MakeMirror"));
|
||||
i::Handle<i::Object> fun_obj = i::GetProperty(isolate, debug, name);
|
||||
i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(fun_obj);
|
||||
@ -6038,11 +6041,11 @@ Handle<String> CpuProfileNode::GetFunctionName() const {
|
||||
const i::CodeEntry* entry = node->entry();
|
||||
if (!entry->has_name_prefix()) {
|
||||
return Handle<String>(ToApi<String>(
|
||||
isolate->factory()->LookupUtf8Symbol(entry->name())));
|
||||
isolate->factory()->InternalizeUtf8String(entry->name())));
|
||||
} else {
|
||||
return Handle<String>(ToApi<String>(isolate->factory()->NewConsString(
|
||||
isolate->factory()->LookupUtf8Symbol(entry->name_prefix()),
|
||||
isolate->factory()->LookupUtf8Symbol(entry->name()))));
|
||||
isolate->factory()->InternalizeUtf8String(entry->name_prefix()),
|
||||
isolate->factory()->InternalizeUtf8String(entry->name()))));
|
||||
}
|
||||
}
|
||||
|
||||
@ -6051,7 +6054,7 @@ Handle<String> CpuProfileNode::GetScriptResourceName() const {
|
||||
i::Isolate* isolate = i::Isolate::Current();
|
||||
IsDeadCheck(isolate, "v8::CpuProfileNode::GetScriptResourceName");
|
||||
const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
|
||||
return Handle<String>(ToApi<String>(isolate->factory()->LookupUtf8Symbol(
|
||||
return Handle<String>(ToApi<String>(isolate->factory()->InternalizeUtf8String(
|
||||
node->entry()->resource_name())));
|
||||
}
|
||||
|
||||
@ -6137,7 +6140,7 @@ Handle<String> CpuProfile::GetTitle() const {
|
||||
i::Isolate* isolate = i::Isolate::Current();
|
||||
IsDeadCheck(isolate, "v8::CpuProfile::GetTitle");
|
||||
const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
|
||||
return Handle<String>(ToApi<String>(isolate->factory()->LookupUtf8Symbol(
|
||||
return Handle<String>(ToApi<String>(isolate->factory()->InternalizeUtf8String(
|
||||
profile->title())));
|
||||
}
|
||||
|
||||
@ -6234,12 +6237,12 @@ Handle<Value> HeapGraphEdge::GetName() const {
|
||||
case i::HeapGraphEdge::kInternal:
|
||||
case i::HeapGraphEdge::kProperty:
|
||||
case i::HeapGraphEdge::kShortcut:
|
||||
return Handle<String>(ToApi<String>(isolate->factory()->LookupUtf8Symbol(
|
||||
edge->name())));
|
||||
return Handle<String>(ToApi<String>(
|
||||
isolate->factory()->InternalizeUtf8String(edge->name())));
|
||||
case i::HeapGraphEdge::kElement:
|
||||
case i::HeapGraphEdge::kHidden:
|
||||
return Handle<Number>(ToApi<Number>(isolate->factory()->NewNumberFromInt(
|
||||
edge->index())));
|
||||
return Handle<Number>(ToApi<Number>(
|
||||
isolate->factory()->NewNumberFromInt(edge->index())));
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
return v8::Undefined();
|
||||
@ -6278,7 +6281,7 @@ HeapGraphNode::Type HeapGraphNode::GetType() const {
|
||||
Handle<String> HeapGraphNode::GetName() const {
|
||||
i::Isolate* isolate = i::Isolate::Current();
|
||||
IsDeadCheck(isolate, "v8::HeapGraphNode::GetName");
|
||||
return Handle<String>(ToApi<String>(isolate->factory()->LookupUtf8Symbol(
|
||||
return Handle<String>(ToApi<String>(isolate->factory()->InternalizeUtf8String(
|
||||
ToInternal(this)->name())));
|
||||
}
|
||||
|
||||
@ -6357,7 +6360,7 @@ unsigned HeapSnapshot::GetUid() const {
|
||||
Handle<String> HeapSnapshot::GetTitle() const {
|
||||
i::Isolate* isolate = i::Isolate::Current();
|
||||
IsDeadCheck(isolate, "v8::HeapSnapshot::GetTitle");
|
||||
return Handle<String>(ToApi<String>(isolate->factory()->LookupUtf8Symbol(
|
||||
return Handle<String>(ToApi<String>(isolate->factory()->InternalizeUtf8String(
|
||||
ToInternal(this)->title())));
|
||||
}
|
||||
|
||||
|
@ -682,7 +682,7 @@ void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
|
||||
// Load the empty string into r2, remove the receiver from the
|
||||
// stack, and jump back to the case where the argument is a string.
|
||||
__ bind(&no_arguments);
|
||||
__ LoadRoot(argument, Heap::kEmptyStringRootIndex);
|
||||
__ LoadRoot(argument, Heap::kempty_stringRootIndex);
|
||||
__ Drop(1);
|
||||
__ b(&argument_is_string);
|
||||
|
||||
|
@ -1505,12 +1505,13 @@ static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm,
|
||||
__ cmp(r3, Operand(ODDBALL_TYPE));
|
||||
__ b(eq, &return_not_equal);
|
||||
|
||||
// Now that we have the types we might as well check for symbol-symbol.
|
||||
// Ensure that no non-strings have the symbol bit set.
|
||||
STATIC_ASSERT(LAST_TYPE < kNotStringTag + kIsSymbolMask);
|
||||
STATIC_ASSERT(kSymbolTag != 0);
|
||||
// Now that we have the types we might as well check for
|
||||
// internalized-internalized.
|
||||
// Ensure that no non-strings have the internalized bit set.
|
||||
STATIC_ASSERT(LAST_TYPE < kNotStringTag + kIsInternalizedMask);
|
||||
STATIC_ASSERT(kInternalizedTag != 0);
|
||||
__ and_(r2, r2, Operand(r3));
|
||||
__ tst(r2, Operand(kIsSymbolMask));
|
||||
__ tst(r2, Operand(kIsInternalizedMask));
|
||||
__ b(ne, &return_not_equal);
|
||||
}
|
||||
|
||||
@ -1547,29 +1548,29 @@ static void EmitCheckForTwoHeapNumbers(MacroAssembler* masm,
|
||||
}
|
||||
|
||||
|
||||
// Fast negative check for symbol-to-symbol equality.
|
||||
static void EmitCheckForSymbolsOrObjects(MacroAssembler* masm,
|
||||
Register lhs,
|
||||
Register rhs,
|
||||
Label* possible_strings,
|
||||
Label* not_both_strings) {
|
||||
// Fast negative check for internalized-to-internalized equality.
|
||||
static void EmitCheckForInternalizedStringsOrObjects(MacroAssembler* masm,
|
||||
Register lhs,
|
||||
Register rhs,
|
||||
Label* possible_strings,
|
||||
Label* not_both_strings) {
|
||||
ASSERT((lhs.is(r0) && rhs.is(r1)) ||
|
||||
(lhs.is(r1) && rhs.is(r0)));
|
||||
|
||||
// r2 is object type of rhs.
|
||||
// Ensure that no non-strings have the symbol bit set.
|
||||
// Ensure that no non-strings have the internalized bit set.
|
||||
Label object_test;
|
||||
STATIC_ASSERT(kSymbolTag != 0);
|
||||
STATIC_ASSERT(kInternalizedTag != 0);
|
||||
__ tst(r2, Operand(kIsNotStringMask));
|
||||
__ b(ne, &object_test);
|
||||
__ tst(r2, Operand(kIsSymbolMask));
|
||||
__ tst(r2, Operand(kIsInternalizedMask));
|
||||
__ b(eq, possible_strings);
|
||||
__ CompareObjectType(lhs, r3, r3, FIRST_NONSTRING_TYPE);
|
||||
__ b(ge, not_both_strings);
|
||||
__ tst(r3, Operand(kIsSymbolMask));
|
||||
__ tst(r3, Operand(kIsInternalizedMask));
|
||||
__ b(eq, possible_strings);
|
||||
|
||||
// Both are symbols. We already checked they weren't the same pointer
|
||||
// Both are internalized. We already checked they weren't the same pointer
|
||||
// so they are not equal.
|
||||
__ mov(r0, Operand(NOT_EQUAL));
|
||||
__ Ret();
|
||||
@ -1716,7 +1717,7 @@ static void ICCompareStub_CheckInputType(MacroAssembler* masm,
|
||||
__ CheckMap(input, scratch, Heap::kHeapNumberMapRootIndex, fail,
|
||||
DONT_DO_SMI_CHECK);
|
||||
}
|
||||
// We could be strict about symbol/string here, but as long as
|
||||
// We could be strict about internalized/non-internalized here, but as long as
|
||||
// hydrogen doesn't care, the stub doesn't have to care either.
|
||||
__ bind(&ok);
|
||||
}
|
||||
@ -1814,27 +1815,29 @@ void ICCompareStub::GenerateGeneric(MacroAssembler* masm) {
|
||||
EmitStrictTwoHeapObjectCompare(masm, lhs, rhs);
|
||||
}
|
||||
|
||||
Label check_for_symbols;
|
||||
Label check_for_internalized_strings;
|
||||
Label flat_string_check;
|
||||
// Check for heap-number-heap-number comparison. Can jump to slow case,
|
||||
// or load both doubles into r0, r1, r2, r3 and jump to the code that handles
|
||||
// that case. If the inputs are not doubles then jumps to check_for_symbols.
|
||||
// that case. If the inputs are not doubles then jumps to
|
||||
// check_for_internalized_strings.
|
||||
// In this case r2 will contain the type of rhs_. Never falls through.
|
||||
EmitCheckForTwoHeapNumbers(masm,
|
||||
lhs,
|
||||
rhs,
|
||||
&both_loaded_as_doubles,
|
||||
&check_for_symbols,
|
||||
&check_for_internalized_strings,
|
||||
&flat_string_check);
|
||||
|
||||
__ bind(&check_for_symbols);
|
||||
__ bind(&check_for_internalized_strings);
|
||||
// In the strict case the EmitStrictTwoHeapObjectCompare already took care of
|
||||
// symbols.
|
||||
// internalized strings.
|
||||
if (cc == eq && !strict()) {
|
||||
// Returns an answer for two symbols or two detectable objects.
|
||||
// Returns an answer for two internalized strings or two detectable objects.
|
||||
// Otherwise jumps to string case or not both strings case.
|
||||
// Assumes that r2 is the type of rhs_ on entry.
|
||||
EmitCheckForSymbolsOrObjects(masm, lhs, rhs, &flat_string_check, &slow);
|
||||
EmitCheckForInternalizedStringsOrObjects(
|
||||
masm, lhs, rhs, &flat_string_check, &slow);
|
||||
}
|
||||
|
||||
// Check for both being sequential ASCII strings, and inline if that is the
|
||||
@ -4501,7 +4504,7 @@ void ArrayLengthStub::Generate(MacroAssembler* masm) {
|
||||
// -- r0 : key
|
||||
// -- r1 : receiver
|
||||
// -----------------------------------
|
||||
__ cmp(r0, Operand(masm->isolate()->factory()->length_symbol()));
|
||||
__ cmp(r0, Operand(masm->isolate()->factory()->length_string()));
|
||||
__ b(ne, &miss);
|
||||
receiver = r1;
|
||||
} else {
|
||||
@ -4530,7 +4533,7 @@ void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
|
||||
// -- r0 : key
|
||||
// -- r1 : receiver
|
||||
// -----------------------------------
|
||||
__ cmp(r0, Operand(masm->isolate()->factory()->prototype_symbol()));
|
||||
__ cmp(r0, Operand(masm->isolate()->factory()->prototype_string()));
|
||||
__ b(ne, &miss);
|
||||
receiver = r1;
|
||||
} else {
|
||||
@ -4559,7 +4562,7 @@ void StringLengthStub::Generate(MacroAssembler* masm) {
|
||||
// -- r0 : key
|
||||
// -- r1 : receiver
|
||||
// -----------------------------------
|
||||
__ cmp(r0, Operand(masm->isolate()->factory()->length_symbol()));
|
||||
__ cmp(r0, Operand(masm->isolate()->factory()->length_string()));
|
||||
__ b(ne, &miss);
|
||||
receiver = r1;
|
||||
} else {
|
||||
@ -4597,7 +4600,7 @@ void StoreArrayLengthStub::Generate(MacroAssembler* masm) {
|
||||
// -- r1 : key
|
||||
// -- r2 : receiver
|
||||
// -----------------------------------
|
||||
__ cmp(r1, Operand(masm->isolate()->factory()->length_symbol()));
|
||||
__ cmp(r1, Operand(masm->isolate()->factory()->length_string()));
|
||||
__ b(ne, &miss);
|
||||
receiver = r2;
|
||||
value = r0;
|
||||
@ -5159,7 +5162,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
// (3) Cons string. Check that it's flat.
|
||||
// Replace subject with first string and reload instance type.
|
||||
__ ldr(r0, FieldMemOperand(subject, ConsString::kSecondOffset));
|
||||
__ CompareRoot(r0, Heap::kEmptyStringRootIndex);
|
||||
__ CompareRoot(r0, Heap::kempty_stringRootIndex);
|
||||
__ b(ne, &runtime);
|
||||
__ ldr(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
|
||||
|
||||
@ -6029,7 +6032,7 @@ void StringHelper::GenerateCopyCharactersLong(MacroAssembler* masm,
|
||||
}
|
||||
|
||||
|
||||
void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
|
||||
void StringHelper::GenerateTwoCharacterStringTableProbe(MacroAssembler* masm,
|
||||
Register c1,
|
||||
Register c2,
|
||||
Register scratch1,
|
||||
@ -6042,7 +6045,7 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
|
||||
Register scratch = scratch3;
|
||||
|
||||
// Make sure that both characters are not digits as such strings has a
|
||||
// different hash algorithm. Don't try to look for these in the symbol table.
|
||||
// different hash algorithm. Don't try to look for these in the string table.
|
||||
Label not_array_index;
|
||||
__ sub(scratch, c1, Operand(static_cast<int>('0')));
|
||||
__ cmp(scratch, Operand(static_cast<int>('9' - '0')));
|
||||
@ -6070,43 +6073,43 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
|
||||
// chars: two character string, char 1 in byte 0 and char 2 in byte 1.
|
||||
// hash: hash of two character string.
|
||||
|
||||
// Load symbol table
|
||||
// Load address of first element of the symbol table.
|
||||
Register symbol_table = c2;
|
||||
__ LoadRoot(symbol_table, Heap::kSymbolTableRootIndex);
|
||||
// Load string table
|
||||
// Load address of first element of the string table.
|
||||
Register string_table = c2;
|
||||
__ LoadRoot(string_table, Heap::kStringTableRootIndex);
|
||||
|
||||
Register undefined = scratch4;
|
||||
__ LoadRoot(undefined, Heap::kUndefinedValueRootIndex);
|
||||
|
||||
// Calculate capacity mask from the symbol table capacity.
|
||||
// Calculate capacity mask from the string table capacity.
|
||||
Register mask = scratch2;
|
||||
__ ldr(mask, FieldMemOperand(symbol_table, SymbolTable::kCapacityOffset));
|
||||
__ ldr(mask, FieldMemOperand(string_table, StringTable::kCapacityOffset));
|
||||
__ mov(mask, Operand(mask, ASR, 1));
|
||||
__ sub(mask, mask, Operand(1));
|
||||
|
||||
// Calculate untagged address of the first element of the symbol table.
|
||||
Register first_symbol_table_element = symbol_table;
|
||||
__ add(first_symbol_table_element, symbol_table,
|
||||
Operand(SymbolTable::kElementsStartOffset - kHeapObjectTag));
|
||||
// Calculate untagged address of the first element of the string table.
|
||||
Register first_string_table_element = string_table;
|
||||
__ add(first_string_table_element, string_table,
|
||||
Operand(StringTable::kElementsStartOffset - kHeapObjectTag));
|
||||
|
||||
// Registers
|
||||
// chars: two character string, char 1 in byte 0 and char 2 in byte 1.
|
||||
// hash: hash of two character string
|
||||
// mask: capacity mask
|
||||
// first_symbol_table_element: address of the first element of
|
||||
// the symbol table
|
||||
// first_string_table_element: address of the first element of
|
||||
// the string table
|
||||
// undefined: the undefined object
|
||||
// scratch: -
|
||||
|
||||
// Perform a number of probes in the symbol table.
|
||||
// Perform a number of probes in the string table.
|
||||
const int kProbes = 4;
|
||||
Label found_in_symbol_table;
|
||||
Label found_in_string_table;
|
||||
Label next_probe[kProbes];
|
||||
Register candidate = scratch5; // Scratch register contains candidate.
|
||||
for (int i = 0; i < kProbes; i++) {
|
||||
// Calculate entry in symbol table.
|
||||
// Calculate entry in string table.
|
||||
if (i > 0) {
|
||||
__ add(candidate, hash, Operand(SymbolTable::GetProbeOffset(i)));
|
||||
__ add(candidate, hash, Operand(StringTable::GetProbeOffset(i)));
|
||||
} else {
|
||||
__ mov(candidate, hash);
|
||||
}
|
||||
@ -6114,9 +6117,9 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
|
||||
__ and_(candidate, candidate, Operand(mask));
|
||||
|
||||
// Load the entry from the symble table.
|
||||
STATIC_ASSERT(SymbolTable::kEntrySize == 1);
|
||||
STATIC_ASSERT(StringTable::kEntrySize == 1);
|
||||
__ ldr(candidate,
|
||||
MemOperand(first_symbol_table_element,
|
||||
MemOperand(first_string_table_element,
|
||||
candidate,
|
||||
LSL,
|
||||
kPointerSizeLog2));
|
||||
@ -6132,7 +6135,7 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
|
||||
if (FLAG_debug_code) {
|
||||
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
|
||||
__ cmp(ip, candidate);
|
||||
__ Assert(eq, "oddball in symbol table is not undefined or the hole");
|
||||
__ Assert(eq, "oddball in string table is not undefined or the hole");
|
||||
}
|
||||
__ jmp(&next_probe[i]);
|
||||
|
||||
@ -6152,7 +6155,7 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
|
||||
// Assumes that word load is little endian.
|
||||
__ ldrh(scratch, FieldMemOperand(candidate, SeqOneByteString::kHeaderSize));
|
||||
__ cmp(chars, scratch);
|
||||
__ b(eq, &found_in_symbol_table);
|
||||
__ b(eq, &found_in_string_table);
|
||||
__ bind(&next_probe[i]);
|
||||
}
|
||||
|
||||
@ -6161,7 +6164,7 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
|
||||
|
||||
// Scratch register contains result when we fall through to here.
|
||||
Register result = candidate;
|
||||
__ bind(&found_in_symbol_table);
|
||||
__ bind(&found_in_string_table);
|
||||
__ Move(r0, result);
|
||||
}
|
||||
|
||||
@ -6290,7 +6293,7 @@ void SubStringStub::Generate(MacroAssembler* masm) {
|
||||
__ b(ne, &sliced_string);
|
||||
// Cons string. Check whether it is flat, then fetch first part.
|
||||
__ ldr(r5, FieldMemOperand(r0, ConsString::kSecondOffset));
|
||||
__ CompareRoot(r5, Heap::kEmptyStringRootIndex);
|
||||
__ CompareRoot(r5, Heap::kempty_stringRootIndex);
|
||||
__ b(ne, &runtime);
|
||||
__ ldr(r5, FieldMemOperand(r0, ConsString::kFirstOffset));
|
||||
// Update instance type.
|
||||
@ -6663,8 +6666,8 @@ void StringAddStub::Generate(MacroAssembler* masm) {
|
||||
// Adding two lengths can't overflow.
|
||||
STATIC_ASSERT(String::kMaxLength < String::kMaxLength * 2);
|
||||
__ add(r6, r2, Operand(r3));
|
||||
// Use the symbol table when adding two one character strings, as it
|
||||
// helps later optimizations to return a symbol here.
|
||||
// Use the string table when adding two one character strings, as it
|
||||
// helps later optimizations to return a string here.
|
||||
__ cmp(r6, Operand(2));
|
||||
__ b(ne, &longer_than_two);
|
||||
|
||||
@ -6682,10 +6685,10 @@ void StringAddStub::Generate(MacroAssembler* masm) {
|
||||
__ ldrb(r2, FieldMemOperand(r0, SeqOneByteString::kHeaderSize));
|
||||
__ ldrb(r3, FieldMemOperand(r1, SeqOneByteString::kHeaderSize));
|
||||
|
||||
// Try to lookup two character string in symbol table. If it is not found
|
||||
// Try to lookup two character string in string table. If it is not found
|
||||
// just allocate a new one.
|
||||
Label make_two_character_string;
|
||||
StringHelper::GenerateTwoCharacterSymbolTableProbe(
|
||||
StringHelper::GenerateTwoCharacterStringTableProbe(
|
||||
masm, r2, r3, r6, r7, r4, r5, r9, &make_two_character_string);
|
||||
__ IncrementCounter(counters->string_add_native(), 1, r2, r3);
|
||||
__ add(sp, sp, Operand(2 * kPointerSize));
|
||||
@ -7026,8 +7029,8 @@ void ICCompareStub::GenerateNumbers(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void ICCompareStub::GenerateSymbols(MacroAssembler* masm) {
|
||||
ASSERT(state_ == CompareIC::SYMBOL);
|
||||
void ICCompareStub::GenerateInternalizedStrings(MacroAssembler* masm) {
|
||||
ASSERT(state_ == CompareIC::INTERNALIZED_STRING);
|
||||
Label miss;
|
||||
|
||||
// Registers containing left and right operands respectively.
|
||||
@ -7039,17 +7042,17 @@ void ICCompareStub::GenerateSymbols(MacroAssembler* masm) {
|
||||
// Check that both operands are heap objects.
|
||||
__ JumpIfEitherSmi(left, right, &miss);
|
||||
|
||||
// Check that both operands are symbols.
|
||||
// Check that both operands are internalized strings.
|
||||
__ ldr(tmp1, FieldMemOperand(left, HeapObject::kMapOffset));
|
||||
__ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
|
||||
__ ldrb(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset));
|
||||
__ ldrb(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset));
|
||||
STATIC_ASSERT(kSymbolTag != 0);
|
||||
STATIC_ASSERT(kInternalizedTag != 0);
|
||||
__ and_(tmp1, tmp1, Operand(tmp2));
|
||||
__ tst(tmp1, Operand(kIsSymbolMask));
|
||||
__ tst(tmp1, Operand(kIsInternalizedMask));
|
||||
__ b(eq, &miss);
|
||||
|
||||
// Symbols are compared by identity.
|
||||
// Internalized strings are compared by identity.
|
||||
__ cmp(left, right);
|
||||
// Make sure r0 is non-zero. At this point input operands are
|
||||
// guaranteed to be non-zero.
|
||||
@ -7101,13 +7104,13 @@ void ICCompareStub::GenerateStrings(MacroAssembler* masm) {
|
||||
|
||||
// Handle not identical strings.
|
||||
|
||||
// Check that both strings are symbols. If they are, we're done
|
||||
// Check that both strings are internalized strings. If they are, we're done
|
||||
// because we already know they are not identical.
|
||||
if (equality) {
|
||||
ASSERT(GetCondition() == eq);
|
||||
STATIC_ASSERT(kSymbolTag != 0);
|
||||
STATIC_ASSERT(kInternalizedTag != 0);
|
||||
__ and_(tmp3, tmp1, Operand(tmp2));
|
||||
__ tst(tmp3, Operand(kIsSymbolMask));
|
||||
__ tst(tmp3, Operand(kIsInternalizedMask));
|
||||
// Make sure r0 is non-zero. At this point input operands are
|
||||
// guaranteed to be non-zero.
|
||||
ASSERT(right.is(r0));
|
||||
@ -7290,11 +7293,11 @@ void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm,
|
||||
__ cmp(entity_name, tmp);
|
||||
__ b(eq, &the_hole);
|
||||
|
||||
// Check if the entry name is not a symbol.
|
||||
// Check if the entry name is not an internalized string.
|
||||
__ ldr(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset));
|
||||
__ ldrb(entity_name,
|
||||
FieldMemOperand(entity_name, Map::kInstanceTypeOffset));
|
||||
__ tst(entity_name, Operand(kIsSymbolMask));
|
||||
__ tst(entity_name, Operand(kIsInternalizedMask));
|
||||
__ b(eq, miss);
|
||||
|
||||
__ bind(&the_hole);
|
||||
@ -7463,11 +7466,11 @@ void StringDictionaryLookupStub::Generate(MacroAssembler* masm) {
|
||||
__ b(eq, &in_dictionary);
|
||||
|
||||
if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) {
|
||||
// Check if the entry name is not a symbol.
|
||||
// Check if the entry name is not an internalized string.
|
||||
__ ldr(entry_key, FieldMemOperand(entry_key, HeapObject::kMapOffset));
|
||||
__ ldrb(entry_key,
|
||||
FieldMemOperand(entry_key, Map::kInstanceTypeOffset));
|
||||
__ tst(entry_key, Operand(kIsSymbolMask));
|
||||
__ tst(entry_key, Operand(kIsInternalizedMask));
|
||||
__ b(eq, &maybe_in_dictionary);
|
||||
}
|
||||
}
|
||||
|
@ -172,14 +172,14 @@ class StringHelper : public AllStatic {
|
||||
int flags);
|
||||
|
||||
|
||||
// Probe the symbol table for a two character string. If the string is
|
||||
// Probe the string table for a two character string. If the string is
|
||||
// not found by probing a jump to the label not_found is performed. This jump
|
||||
// does not guarantee that the string is not in the symbol table. If the
|
||||
// does not guarantee that the string is not in the string table. If the
|
||||
// string is found the code falls through with the string in register r0.
|
||||
// Contents of both c1 and c2 registers are modified. At the exit c1 is
|
||||
// guaranteed to contain halfword with low and high bytes equal to
|
||||
// initial contents of c1 and c2 respectively.
|
||||
static void GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
|
||||
static void GenerateTwoCharacterStringTableProbe(MacroAssembler* masm,
|
||||
Register c1,
|
||||
Register c2,
|
||||
Register scratch1,
|
||||
|
@ -468,7 +468,7 @@ void StringCharLoadGenerator::Generate(MacroAssembler* masm,
|
||||
// the string.
|
||||
__ bind(&cons_string);
|
||||
__ ldr(result, FieldMemOperand(string, ConsString::kSecondOffset));
|
||||
__ CompareRoot(result, Heap::kEmptyStringRootIndex);
|
||||
__ CompareRoot(result, Heap::kempty_stringRootIndex);
|
||||
__ b(ne, call_runtime);
|
||||
// Get the first of the two strings and load its instance type.
|
||||
__ ldr(string, FieldMemOperand(string, ConsString::kFirstOffset));
|
||||
|
@ -1631,7 +1631,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value()));
|
||||
// Fall through.
|
||||
case ObjectLiteral::Property::COMPUTED:
|
||||
if (key->handle()->IsSymbol()) {
|
||||
if (key->handle()->IsInternalizedString()) {
|
||||
if (property->emit_store()) {
|
||||
VisitForAccumulatorValue(value);
|
||||
__ mov(r2, Operand(key->handle()));
|
||||
@ -2691,7 +2691,7 @@ void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
|
||||
__ cmp(r2, ip);
|
||||
__ b(eq, if_false);
|
||||
|
||||
// Look for valueOf symbol in the descriptor array, and indicate false if
|
||||
// Look for valueOf name in the descriptor array, and indicate false if
|
||||
// found. Since we omit an enumeration index check, if it is added via a
|
||||
// transition that shares its descriptor array, this is a false positive.
|
||||
Label entry, loop, done;
|
||||
@ -2716,10 +2716,10 @@ void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
|
||||
__ add(r2, r2, Operand(r3, LSL, kPointerSizeLog2 - kSmiTagSize));
|
||||
|
||||
// Loop through all the keys in the descriptor array. If one of these is the
|
||||
// symbol valueOf the result is false.
|
||||
// The use of ip to store the valueOf symbol asumes that it is not otherwise
|
||||
// string "valueOf" the result is false.
|
||||
// The use of ip to store the valueOf string assumes that it is not otherwise
|
||||
// used in the loop below.
|
||||
__ mov(ip, Operand(FACTORY->value_of_symbol()));
|
||||
__ mov(ip, Operand(FACTORY->value_of_string()));
|
||||
__ jmp(&entry);
|
||||
__ bind(&loop);
|
||||
__ ldr(r3, MemOperand(r4, 0));
|
||||
@ -2954,12 +2954,12 @@ void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
|
||||
|
||||
// Functions have class 'Function'.
|
||||
__ bind(&function);
|
||||
__ LoadRoot(r0, Heap::kfunction_class_symbolRootIndex);
|
||||
__ LoadRoot(r0, Heap::kfunction_class_stringRootIndex);
|
||||
__ jmp(&done);
|
||||
|
||||
// Objects with a non-function constructor have class 'Object'.
|
||||
__ bind(&non_function_constructor);
|
||||
__ LoadRoot(r0, Heap::kObject_symbolRootIndex);
|
||||
__ LoadRoot(r0, Heap::kObject_stringRootIndex);
|
||||
__ jmp(&done);
|
||||
|
||||
// Non-JS objects have class null.
|
||||
@ -3324,7 +3324,7 @@ void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
|
||||
__ bind(&index_out_of_range);
|
||||
// When the index is out of range, the spec requires us to return
|
||||
// the empty string.
|
||||
__ LoadRoot(result, Heap::kEmptyStringRootIndex);
|
||||
__ LoadRoot(result, Heap::kempty_stringRootIndex);
|
||||
__ jmp(&done);
|
||||
|
||||
__ bind(&need_conversion);
|
||||
@ -3633,7 +3633,7 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
|
||||
__ ldr(array_length, FieldMemOperand(array, JSArray::kLengthOffset));
|
||||
__ SmiUntag(array_length, SetCC);
|
||||
__ b(ne, &non_trivial_array);
|
||||
__ LoadRoot(r0, Heap::kEmptyStringRootIndex);
|
||||
__ LoadRoot(r0, Heap::kempty_stringRootIndex);
|
||||
__ b(&done);
|
||||
|
||||
__ bind(&non_trivial_array);
|
||||
@ -4246,13 +4246,13 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
||||
}
|
||||
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||
|
||||
if (check->Equals(isolate()->heap()->number_symbol())) {
|
||||
if (check->Equals(isolate()->heap()->number_string())) {
|
||||
__ JumpIfSmi(r0, if_true);
|
||||
__ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
|
||||
__ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
|
||||
__ cmp(r0, ip);
|
||||
Split(eq, if_true, if_false, fall_through);
|
||||
} else if (check->Equals(isolate()->heap()->string_symbol())) {
|
||||
} else if (check->Equals(isolate()->heap()->string_string())) {
|
||||
__ JumpIfSmi(r0, if_false);
|
||||
// Check for undetectable objects => false.
|
||||
__ CompareObjectType(r0, r0, r1, FIRST_NONSTRING_TYPE);
|
||||
@ -4260,16 +4260,16 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
||||
__ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset));
|
||||
__ tst(r1, Operand(1 << Map::kIsUndetectable));
|
||||
Split(eq, if_true, if_false, fall_through);
|
||||
} else if (check->Equals(isolate()->heap()->boolean_symbol())) {
|
||||
} else if (check->Equals(isolate()->heap()->boolean_string())) {
|
||||
__ CompareRoot(r0, Heap::kTrueValueRootIndex);
|
||||
__ b(eq, if_true);
|
||||
__ CompareRoot(r0, Heap::kFalseValueRootIndex);
|
||||
Split(eq, if_true, if_false, fall_through);
|
||||
} else if (FLAG_harmony_typeof &&
|
||||
check->Equals(isolate()->heap()->null_symbol())) {
|
||||
check->Equals(isolate()->heap()->null_string())) {
|
||||
__ CompareRoot(r0, Heap::kNullValueRootIndex);
|
||||
Split(eq, if_true, if_false, fall_through);
|
||||
} else if (check->Equals(isolate()->heap()->undefined_symbol())) {
|
||||
} else if (check->Equals(isolate()->heap()->undefined_string())) {
|
||||
__ CompareRoot(r0, Heap::kUndefinedValueRootIndex);
|
||||
__ b(eq, if_true);
|
||||
__ JumpIfSmi(r0, if_false);
|
||||
@ -4279,14 +4279,14 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
||||
__ tst(r1, Operand(1 << Map::kIsUndetectable));
|
||||
Split(ne, if_true, if_false, fall_through);
|
||||
|
||||
} else if (check->Equals(isolate()->heap()->function_symbol())) {
|
||||
} else if (check->Equals(isolate()->heap()->function_string())) {
|
||||
__ JumpIfSmi(r0, if_false);
|
||||
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
|
||||
__ CompareObjectType(r0, r0, r1, JS_FUNCTION_TYPE);
|
||||
__ b(eq, if_true);
|
||||
__ cmp(r1, Operand(JS_FUNCTION_PROXY_TYPE));
|
||||
Split(eq, if_true, if_false, fall_through);
|
||||
} else if (check->Equals(isolate()->heap()->object_symbol())) {
|
||||
} else if (check->Equals(isolate()->heap()->object_string())) {
|
||||
__ JumpIfSmi(r0, if_false);
|
||||
if (!FLAG_harmony_typeof) {
|
||||
__ CompareRoot(r0, Heap::kNullValueRootIndex);
|
||||
|
@ -303,30 +303,30 @@ static void GenerateFastArrayLoad(MacroAssembler* masm,
|
||||
}
|
||||
|
||||
|
||||
// Checks whether a key is an array index string or a symbol string.
|
||||
// Falls through if a key is a symbol.
|
||||
// Checks whether a key is an array index string or an internalized string.
|
||||
// Falls through if a key is an internalized string.
|
||||
static void GenerateKeyStringCheck(MacroAssembler* masm,
|
||||
Register key,
|
||||
Register map,
|
||||
Register hash,
|
||||
Label* index_string,
|
||||
Label* not_symbol) {
|
||||
Label* not_internalized) {
|
||||
// The key is not a smi.
|
||||
// Is it a string?
|
||||
__ CompareObjectType(key, map, hash, FIRST_NONSTRING_TYPE);
|
||||
__ b(ge, not_symbol);
|
||||
__ b(ge, not_internalized);
|
||||
|
||||
// Is the string an array index, with cached numeric value?
|
||||
__ ldr(hash, FieldMemOperand(key, String::kHashFieldOffset));
|
||||
__ tst(hash, Operand(String::kContainsCachedArrayIndexMask));
|
||||
__ b(eq, index_string);
|
||||
|
||||
// Is the string a symbol?
|
||||
// Is the string internalized?
|
||||
// map: key map
|
||||
__ ldrb(hash, FieldMemOperand(map, Map::kInstanceTypeOffset));
|
||||
STATIC_ASSERT(kSymbolTag != 0);
|
||||
__ tst(hash, Operand(kIsSymbolMask));
|
||||
__ b(eq, not_symbol);
|
||||
STATIC_ASSERT(kInternalizedTag != 0);
|
||||
__ tst(hash, Operand(kIsInternalizedMask));
|
||||
__ b(eq, not_internalized);
|
||||
}
|
||||
|
||||
|
||||
@ -585,7 +585,7 @@ void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
|
||||
__ bind(&check_string);
|
||||
GenerateKeyStringCheck(masm, r2, r0, r3, &index_string, &slow_call);
|
||||
|
||||
// The key is known to be a symbol.
|
||||
// The key is known to be internalized.
|
||||
// If the receiver is a regular JS object with slow properties then do
|
||||
// a quick inline probe of the receiver's dictionary.
|
||||
// Otherwise do the monomorphic cache probe.
|
||||
@ -613,7 +613,7 @@ void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
|
||||
__ bind(&slow_call);
|
||||
// This branch is taken if:
|
||||
// - the receiver requires boxing or access check,
|
||||
// - the key is neither smi nor symbol,
|
||||
// - the key is neither smi nor an internalized string,
|
||||
// - the value loaded is not a function,
|
||||
// - there is hope that the runtime will create a monomorphic call stub
|
||||
// that will get fetched next time.
|
||||
@ -987,7 +987,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
int mask = KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask;
|
||||
__ And(r3, r3, Operand(mask));
|
||||
|
||||
// Load the key (consisting of map and symbol) from the cache and
|
||||
// Load the key (consisting of map and internalized string) from the cache and
|
||||
// check for match.
|
||||
Label load_in_object_property;
|
||||
static const int kEntriesPerBucket = KeyedLookupCache::kEntriesPerBucket;
|
||||
@ -1004,13 +1004,13 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
__ ldr(r5, MemOperand(r4, kPointerSize * 2, PostIndex));
|
||||
__ cmp(r2, r5);
|
||||
__ b(ne, &try_next_entry);
|
||||
__ ldr(r5, MemOperand(r4, -kPointerSize)); // Load symbol
|
||||
__ ldr(r5, MemOperand(r4, -kPointerSize)); // Load string
|
||||
__ cmp(r0, r5);
|
||||
__ b(eq, &hit_on_nth_entry[i]);
|
||||
__ bind(&try_next_entry);
|
||||
}
|
||||
|
||||
// Last entry: Load map and move r4 to symbol.
|
||||
// Last entry: Load map and move r4 to string.
|
||||
__ ldr(r5, MemOperand(r4, kPointerSize, PostIndex));
|
||||
__ cmp(r2, r5);
|
||||
__ b(ne, &slow);
|
||||
@ -1072,8 +1072,8 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
GenerateGlobalInstanceTypeCheck(masm, r2, &slow);
|
||||
// Load the property to r0.
|
||||
GenerateDictionaryLoad(masm, &slow, r3, r0, r0, r2, r4);
|
||||
__ IncrementCounter(isolate->counters()->keyed_load_generic_symbol(),
|
||||
1, r2, r3);
|
||||
__ IncrementCounter(
|
||||
isolate->counters()->keyed_load_generic_symbol(), 1, r2, r3);
|
||||
__ Ret();
|
||||
|
||||
__ bind(&index_string);
|
||||
|
@ -2680,12 +2680,12 @@ void LCodeGen::EmitClassOfTest(Label* is_true,
|
||||
__ ldr(temp, FieldMemOperand(temp, JSFunction::kSharedFunctionInfoOffset));
|
||||
__ ldr(temp, FieldMemOperand(temp,
|
||||
SharedFunctionInfo::kInstanceClassNameOffset));
|
||||
// The class name we are testing against is a symbol because it's a literal.
|
||||
// The name in the constructor is a symbol because of the way the context is
|
||||
// booted. This routine isn't expected to work for random API-created
|
||||
// The class name we are testing against is internalized since it's a literal.
|
||||
// The name in the constructor is internalized because of the way the context
|
||||
// is booted. This routine isn't expected to work for random API-created
|
||||
// classes and it doesn't have to because you can't access it with natives
|
||||
// syntax. Since both sides are symbols it is sufficient to use an identity
|
||||
// comparison.
|
||||
// syntax. Since both sides are internalized it is sufficient to use an
|
||||
// identity comparison.
|
||||
__ cmp(temp, Operand(class_name));
|
||||
// End with the answer in flags.
|
||||
}
|
||||
@ -6042,14 +6042,14 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
|
||||
Handle<String> type_name) {
|
||||
Condition final_branch_condition = kNoCondition;
|
||||
Register scratch = scratch0();
|
||||
if (type_name->Equals(heap()->number_symbol())) {
|
||||
if (type_name->Equals(heap()->number_string())) {
|
||||
__ JumpIfSmi(input, true_label);
|
||||
__ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset));
|
||||
__ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
|
||||
__ cmp(input, Operand(ip));
|
||||
final_branch_condition = eq;
|
||||
|
||||
} else if (type_name->Equals(heap()->string_symbol())) {
|
||||
} else if (type_name->Equals(heap()->string_string())) {
|
||||
__ JumpIfSmi(input, false_label);
|
||||
__ CompareObjectType(input, input, scratch, FIRST_NONSTRING_TYPE);
|
||||
__ b(ge, false_label);
|
||||
@ -6057,17 +6057,17 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
|
||||
__ tst(ip, Operand(1 << Map::kIsUndetectable));
|
||||
final_branch_condition = eq;
|
||||
|
||||
} else if (type_name->Equals(heap()->boolean_symbol())) {
|
||||
} else if (type_name->Equals(heap()->boolean_string())) {
|
||||
__ CompareRoot(input, Heap::kTrueValueRootIndex);
|
||||
__ b(eq, true_label);
|
||||
__ CompareRoot(input, Heap::kFalseValueRootIndex);
|
||||
final_branch_condition = eq;
|
||||
|
||||
} else if (FLAG_harmony_typeof && type_name->Equals(heap()->null_symbol())) {
|
||||
} else if (FLAG_harmony_typeof && type_name->Equals(heap()->null_string())) {
|
||||
__ CompareRoot(input, Heap::kNullValueRootIndex);
|
||||
final_branch_condition = eq;
|
||||
|
||||
} else if (type_name->Equals(heap()->undefined_symbol())) {
|
||||
} else if (type_name->Equals(heap()->undefined_string())) {
|
||||
__ CompareRoot(input, Heap::kUndefinedValueRootIndex);
|
||||
__ b(eq, true_label);
|
||||
__ JumpIfSmi(input, false_label);
|
||||
@ -6077,7 +6077,7 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
|
||||
__ tst(ip, Operand(1 << Map::kIsUndetectable));
|
||||
final_branch_condition = ne;
|
||||
|
||||
} else if (type_name->Equals(heap()->function_symbol())) {
|
||||
} else if (type_name->Equals(heap()->function_string())) {
|
||||
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
|
||||
__ JumpIfSmi(input, false_label);
|
||||
__ CompareObjectType(input, scratch, input, JS_FUNCTION_TYPE);
|
||||
@ -6085,7 +6085,7 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
|
||||
__ cmp(input, Operand(JS_FUNCTION_PROXY_TYPE));
|
||||
final_branch_condition = eq;
|
||||
|
||||
} else if (type_name->Equals(heap()->object_symbol())) {
|
||||
} else if (type_name->Equals(heap()->object_string())) {
|
||||
__ JumpIfSmi(input, false_label);
|
||||
if (!FLAG_harmony_typeof) {
|
||||
__ CompareRoot(input, Heap::kNullValueRootIndex);
|
||||
|
@ -130,14 +130,14 @@ static void ProbeTable(Isolate* isolate,
|
||||
// the property. This function may return false negatives, so miss_label
|
||||
// must always call a backup property check that is complete.
|
||||
// This function is safe to call if the receiver has fast properties.
|
||||
// Name must be a symbol and receiver must be a heap object.
|
||||
// Name must be internalized and receiver must be a heap object.
|
||||
static void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
|
||||
Label* miss_label,
|
||||
Register receiver,
|
||||
Handle<String> name,
|
||||
Register scratch0,
|
||||
Register scratch1) {
|
||||
ASSERT(name->IsSymbol());
|
||||
ASSERT(name->IsInternalizedString());
|
||||
Counters* counters = masm->isolate()->counters();
|
||||
__ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1);
|
||||
__ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
|
||||
@ -1102,8 +1102,8 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
|
||||
if (!current->HasFastProperties() &&
|
||||
!current->IsJSGlobalObject() &&
|
||||
!current->IsJSGlobalProxy()) {
|
||||
if (!name->IsSymbol()) {
|
||||
name = factory()->LookupSymbol(name);
|
||||
if (!name->IsInternalizedString()) {
|
||||
name = factory()->InternalizeString(name);
|
||||
}
|
||||
ASSERT(current->property_dictionary()->FindEntry(*name) ==
|
||||
StringDictionary::kNotFound);
|
||||
@ -1995,7 +1995,7 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall(
|
||||
|
||||
if (index_out_of_range.is_linked()) {
|
||||
__ bind(&index_out_of_range);
|
||||
__ LoadRoot(r0, Heap::kEmptyStringRootIndex);
|
||||
__ LoadRoot(r0, Heap::kempty_stringRootIndex);
|
||||
__ Drop(argc + 1);
|
||||
__ Ret();
|
||||
}
|
||||
@ -2422,7 +2422,7 @@ void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
|
||||
break;
|
||||
|
||||
case STRING_CHECK:
|
||||
// Check that the object is a two-byte string or a symbol.
|
||||
// Check that the object is a string.
|
||||
__ CompareObjectType(r1, r3, r3, FIRST_NONSTRING_TYPE);
|
||||
__ b(ge, &miss);
|
||||
// Check that the maps starting from the prototype haven't changed.
|
||||
|
12
src/ast.cc
12
src/ast.cc
@ -97,7 +97,7 @@ VariableProxy::VariableProxy(Isolate* isolate,
|
||||
position_(position),
|
||||
interface_(interface) {
|
||||
// Names must be canonicalized for fast equality checks.
|
||||
ASSERT(name->IsSymbol());
|
||||
ASSERT(name->IsInternalizedString());
|
||||
}
|
||||
|
||||
|
||||
@ -182,8 +182,8 @@ ObjectLiteral::Property::Property(Literal* key,
|
||||
key_ = key;
|
||||
value_ = value;
|
||||
Object* k = *key->handle();
|
||||
if (k->IsSymbol() &&
|
||||
isolate->heap()->Proto_symbol()->Equals(String::cast(k))) {
|
||||
if (k->IsInternalizedString() &&
|
||||
isolate->heap()->proto_string()->Equals(String::cast(k))) {
|
||||
kind_ = PROTOTYPE;
|
||||
} else if (value_->AsMaterializedLiteral() != NULL) {
|
||||
kind_ = MATERIALIZED_LITERAL;
|
||||
@ -483,9 +483,9 @@ void CaseClause::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
|
||||
if (info.IsUninitialized()) info = TypeInfo::Unknown();
|
||||
if (info.IsSmi()) {
|
||||
compare_type_ = SMI_ONLY;
|
||||
} else if (info.IsSymbol()) {
|
||||
compare_type_ = SYMBOL_ONLY;
|
||||
} else if (info.IsNonSymbol()) {
|
||||
} else if (info.IsInternalizedString()) {
|
||||
compare_type_ = NAME_ONLY;
|
||||
} else if (info.IsNonInternalizedString()) {
|
||||
compare_type_ = STRING_ONLY;
|
||||
} else if (info.IsNonPrimitive()) {
|
||||
compare_type_ = OBJECT_ONLY;
|
||||
|
@ -968,7 +968,7 @@ class CaseClause: public ZoneObject {
|
||||
TypeFeedbackId CompareId() { return compare_id_; }
|
||||
void RecordTypeFeedback(TypeFeedbackOracle* oracle);
|
||||
bool IsSmiCompare() { return compare_type_ == SMI_ONLY; }
|
||||
bool IsSymbolCompare() { return compare_type_ == SYMBOL_ONLY; }
|
||||
bool IsNameCompare() { return compare_type_ == NAME_ONLY; }
|
||||
bool IsStringCompare() { return compare_type_ == STRING_ONLY; }
|
||||
bool IsObjectCompare() { return compare_type_ == OBJECT_ONLY; }
|
||||
|
||||
@ -980,7 +980,7 @@ class CaseClause: public ZoneObject {
|
||||
enum CompareTypeFeedback {
|
||||
NONE,
|
||||
SMI_ONLY,
|
||||
SYMBOL_ONLY,
|
||||
NAME_ONLY,
|
||||
STRING_ONLY,
|
||||
OBJECT_ONLY
|
||||
};
|
||||
@ -1171,7 +1171,7 @@ class Literal: public Expression {
|
||||
DECLARE_NODE_TYPE(Literal)
|
||||
|
||||
virtual bool IsPropertyName() {
|
||||
if (handle_->IsSymbol()) {
|
||||
if (handle_->IsInternalizedString()) {
|
||||
uint32_t ignored;
|
||||
return !String::cast(*handle_)->AsArrayIndex(&ignored);
|
||||
}
|
||||
|
@ -360,11 +360,11 @@ static Handle<JSFunction> InstallFunction(Handle<JSObject> target,
|
||||
bool is_ecma_native) {
|
||||
Isolate* isolate = target->GetIsolate();
|
||||
Factory* factory = isolate->factory();
|
||||
Handle<String> symbol = factory->LookupUtf8Symbol(name);
|
||||
Handle<String> internalized_name = factory->InternalizeUtf8String(name);
|
||||
Handle<Code> call_code = Handle<Code>(isolate->builtins()->builtin(call));
|
||||
Handle<JSFunction> function = prototype.is_null() ?
|
||||
factory->NewFunctionWithoutPrototype(symbol, call_code) :
|
||||
factory->NewFunctionWithPrototype(symbol,
|
||||
factory->NewFunctionWithoutPrototype(internalized_name, call_code) :
|
||||
factory->NewFunctionWithPrototype(internalized_name,
|
||||
type,
|
||||
instance_size,
|
||||
prototype,
|
||||
@ -379,9 +379,9 @@ static Handle<JSFunction> InstallFunction(Handle<JSObject> target,
|
||||
}
|
||||
CHECK_NOT_EMPTY_HANDLE(isolate,
|
||||
JSObject::SetLocalPropertyIgnoreAttributes(
|
||||
target, symbol, function, attributes));
|
||||
target, internalized_name, function, attributes));
|
||||
if (is_ecma_native) {
|
||||
function->shared()->set_instance_class_name(*symbol);
|
||||
function->shared()->set_instance_class_name(*internalized_name);
|
||||
}
|
||||
function->shared()->set_native(true);
|
||||
return function;
|
||||
@ -407,19 +407,19 @@ void Genesis::SetFunctionInstanceDescriptor(
|
||||
map->set_instance_descriptors(*descriptors);
|
||||
|
||||
{ // Add length.
|
||||
CallbacksDescriptor d(*factory()->length_symbol(), *length, attribs);
|
||||
CallbacksDescriptor d(*factory()->length_string(), *length, attribs);
|
||||
map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
{ // Add name.
|
||||
CallbacksDescriptor d(*factory()->name_symbol(), *name, attribs);
|
||||
CallbacksDescriptor d(*factory()->name_string(), *name, attribs);
|
||||
map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
{ // Add arguments.
|
||||
CallbacksDescriptor d(*factory()->arguments_symbol(), *args, attribs);
|
||||
CallbacksDescriptor d(*factory()->arguments_string(), *args, attribs);
|
||||
map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
{ // Add caller.
|
||||
CallbacksDescriptor d(*factory()->caller_symbol(), *caller, attribs);
|
||||
CallbacksDescriptor d(*factory()->caller_string(), *caller, attribs);
|
||||
map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
if (prototypeMode != DONT_ADD_PROTOTYPE) {
|
||||
@ -427,7 +427,7 @@ void Genesis::SetFunctionInstanceDescriptor(
|
||||
if (prototypeMode == ADD_WRITEABLE_PROTOTYPE) {
|
||||
attribs = static_cast<PropertyAttributes>(attribs & ~READ_ONLY);
|
||||
}
|
||||
CallbacksDescriptor d(*factory()->prototype_symbol(), *prototype, attribs);
|
||||
CallbacksDescriptor d(*factory()->prototype_string(), *prototype, attribs);
|
||||
map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
}
|
||||
@ -472,7 +472,7 @@ Handle<JSFunction> Genesis::CreateEmptyFunction(Isolate* isolate) {
|
||||
Factory* factory = isolate->factory();
|
||||
Heap* heap = isolate->heap();
|
||||
|
||||
Handle<String> object_name = Handle<String>(heap->Object_symbol());
|
||||
Handle<String> object_name = Handle<String>(heap->Object_string());
|
||||
|
||||
{ // --- O b j e c t ---
|
||||
Handle<JSFunction> object_fun =
|
||||
@ -498,7 +498,7 @@ Handle<JSFunction> Genesis::CreateEmptyFunction(Isolate* isolate) {
|
||||
object_prototype_map->set_instance_descriptors(*prototype_descriptors);
|
||||
|
||||
{ // Add __proto__.
|
||||
CallbacksDescriptor d(heap->Proto_symbol(), *object_prototype, attribs);
|
||||
CallbacksDescriptor d(heap->proto_string(), *object_prototype, attribs);
|
||||
object_prototype_map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
|
||||
@ -511,10 +511,10 @@ Handle<JSFunction> Genesis::CreateEmptyFunction(Isolate* isolate) {
|
||||
|
||||
// Allocate the empty function as the prototype for function ECMAScript
|
||||
// 262 15.3.4.
|
||||
Handle<String> symbol =
|
||||
factory->LookupOneByteSymbol(STATIC_ASCII_VECTOR("Empty"));
|
||||
Handle<String> empty_string =
|
||||
factory->InternalizeOneByteString(STATIC_ASCII_VECTOR("Empty"));
|
||||
Handle<JSFunction> empty_function =
|
||||
factory->NewFunctionWithoutPrototype(symbol, CLASSIC_MODE);
|
||||
factory->NewFunctionWithoutPrototype(empty_string, CLASSIC_MODE);
|
||||
|
||||
// --- E m p t y ---
|
||||
Handle<Code> code =
|
||||
@ -566,19 +566,19 @@ void Genesis::SetStrictFunctionInstanceDescriptor(
|
||||
map->set_instance_descriptors(*descriptors);
|
||||
|
||||
{ // Add length.
|
||||
CallbacksDescriptor d(*factory()->length_symbol(), *length, attribs);
|
||||
CallbacksDescriptor d(*factory()->length_string(), *length, attribs);
|
||||
map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
{ // Add name.
|
||||
CallbacksDescriptor d(*factory()->name_symbol(), *name, attribs);
|
||||
CallbacksDescriptor d(*factory()->name_string(), *name, attribs);
|
||||
map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
{ // Add arguments.
|
||||
CallbacksDescriptor d(*factory()->arguments_symbol(), *arguments, attribs);
|
||||
CallbacksDescriptor d(*factory()->arguments_string(), *arguments, attribs);
|
||||
map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
{ // Add caller.
|
||||
CallbacksDescriptor d(*factory()->caller_symbol(), *caller, attribs);
|
||||
CallbacksDescriptor d(*factory()->caller_string(), *caller, attribs);
|
||||
map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
if (prototypeMode != DONT_ADD_PROTOTYPE) {
|
||||
@ -586,7 +586,7 @@ void Genesis::SetStrictFunctionInstanceDescriptor(
|
||||
if (prototypeMode != ADD_WRITEABLE_PROTOTYPE) {
|
||||
attribs = static_cast<PropertyAttributes>(attribs | READ_ONLY);
|
||||
}
|
||||
CallbacksDescriptor d(*factory()->prototype_symbol(), *prototype, attribs);
|
||||
CallbacksDescriptor d(*factory()->prototype_string(), *prototype, attribs);
|
||||
map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
}
|
||||
@ -595,7 +595,7 @@ void Genesis::SetStrictFunctionInstanceDescriptor(
|
||||
// ECMAScript 5th Edition, 13.2.3
|
||||
Handle<JSFunction> Genesis::GetThrowTypeErrorFunction() {
|
||||
if (throw_type_error_function.is_null()) {
|
||||
Handle<String> name = factory()->LookupOneByteSymbol(
|
||||
Handle<String> name = factory()->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("ThrowTypeError"));
|
||||
throw_type_error_function =
|
||||
factory()->NewFunctionWithoutPrototype(name, CLASSIC_MODE);
|
||||
@ -671,8 +671,8 @@ static void SetAccessors(Handle<Map> map,
|
||||
|
||||
|
||||
void Genesis::PoisonArgumentsAndCaller(Handle<Map> map) {
|
||||
SetAccessors(map, factory()->arguments_symbol(), GetThrowTypeErrorFunction());
|
||||
SetAccessors(map, factory()->caller_symbol(), GetThrowTypeErrorFunction());
|
||||
SetAccessors(map, factory()->arguments_string(), GetThrowTypeErrorFunction());
|
||||
SetAccessors(map, factory()->caller_string(), GetThrowTypeErrorFunction());
|
||||
}
|
||||
|
||||
|
||||
@ -748,7 +748,7 @@ Handle<JSGlobalProxy> Genesis::CreateNewGlobals(
|
||||
}
|
||||
|
||||
if (js_global_template.is_null()) {
|
||||
Handle<String> name = Handle<String>(heap()->empty_symbol());
|
||||
Handle<String> name = Handle<String>(heap()->empty_string());
|
||||
Handle<Code> code = Handle<Code>(isolate()->builtins()->builtin(
|
||||
Builtins::kIllegal));
|
||||
js_global_function =
|
||||
@ -761,7 +761,7 @@ Handle<JSGlobalProxy> Genesis::CreateNewGlobals(
|
||||
JSObject::cast(js_global_function->instance_prototype()));
|
||||
CHECK_NOT_EMPTY_HANDLE(isolate(),
|
||||
JSObject::SetLocalPropertyIgnoreAttributes(
|
||||
prototype, factory()->constructor_symbol(),
|
||||
prototype, factory()->constructor_string(),
|
||||
isolate()->object_function(), NONE));
|
||||
} else {
|
||||
Handle<FunctionTemplateInfo> js_global_constructor(
|
||||
@ -782,7 +782,7 @@ Handle<JSGlobalProxy> Genesis::CreateNewGlobals(
|
||||
// Step 2: create or re-initialize the global proxy object.
|
||||
Handle<JSFunction> global_proxy_function;
|
||||
if (global_template.IsEmpty()) {
|
||||
Handle<String> name = Handle<String>(heap()->empty_symbol());
|
||||
Handle<String> name = Handle<String>(heap()->empty_string());
|
||||
Handle<Code> code = Handle<Code>(isolate()->builtins()->builtin(
|
||||
Builtins::kIllegal));
|
||||
global_proxy_function =
|
||||
@ -798,7 +798,7 @@ Handle<JSGlobalProxy> Genesis::CreateNewGlobals(
|
||||
factory()->OuterGlobalObject);
|
||||
}
|
||||
|
||||
Handle<String> global_name = factory()->LookupOneByteSymbol(
|
||||
Handle<String> global_name = factory()->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("global"));
|
||||
global_proxy_function->shared()->set_instance_class_name(*global_name);
|
||||
global_proxy_function->initial_map()->set_is_access_check_needed(true);
|
||||
@ -839,7 +839,7 @@ void Genesis::HookUpInnerGlobal(Handle<GlobalObject> inner_global) {
|
||||
static const PropertyAttributes attributes =
|
||||
static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE);
|
||||
ForceSetProperty(builtins_global,
|
||||
factory()->LookupOneByteSymbol(
|
||||
factory()->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("global")),
|
||||
inner_global,
|
||||
attributes);
|
||||
@ -871,7 +871,7 @@ bool Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
|
||||
Factory* factory = isolate->factory();
|
||||
Heap* heap = isolate->heap();
|
||||
|
||||
Handle<String> object_name = Handle<String>(heap->Object_symbol());
|
||||
Handle<String> object_name = Handle<String>(heap->Object_string());
|
||||
CHECK_NOT_EMPTY_HANDLE(isolate,
|
||||
JSObject::SetLocalPropertyIgnoreAttributes(
|
||||
inner_global, object_name,
|
||||
@ -907,7 +907,7 @@ bool Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
|
||||
initial_map->set_instance_descriptors(*array_descriptors);
|
||||
|
||||
{ // Add length.
|
||||
CallbacksDescriptor d(*factory->length_symbol(), *array_length, attribs);
|
||||
CallbacksDescriptor d(*factory->length_string(), *array_length, attribs);
|
||||
array_function->initial_map()->AppendDescriptor(&d, witness);
|
||||
}
|
||||
|
||||
@ -956,7 +956,7 @@ bool Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
|
||||
string_map->set_instance_descriptors(*string_descriptors);
|
||||
|
||||
{ // Add length.
|
||||
CallbacksDescriptor d(*factory->length_symbol(), *string_length, attribs);
|
||||
CallbacksDescriptor d(*factory->length_string(), *string_length, attribs);
|
||||
string_map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
}
|
||||
@ -993,28 +993,28 @@ bool Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
|
||||
|
||||
{
|
||||
// ECMA-262, section 15.10.7.1.
|
||||
FieldDescriptor field(heap->source_symbol(),
|
||||
FieldDescriptor field(heap->source_string(),
|
||||
JSRegExp::kSourceFieldIndex,
|
||||
final);
|
||||
initial_map->AppendDescriptor(&field, witness);
|
||||
}
|
||||
{
|
||||
// ECMA-262, section 15.10.7.2.
|
||||
FieldDescriptor field(heap->global_symbol(),
|
||||
FieldDescriptor field(heap->global_string(),
|
||||
JSRegExp::kGlobalFieldIndex,
|
||||
final);
|
||||
initial_map->AppendDescriptor(&field, witness);
|
||||
}
|
||||
{
|
||||
// ECMA-262, section 15.10.7.3.
|
||||
FieldDescriptor field(heap->ignore_case_symbol(),
|
||||
FieldDescriptor field(heap->ignore_case_string(),
|
||||
JSRegExp::kIgnoreCaseFieldIndex,
|
||||
final);
|
||||
initial_map->AppendDescriptor(&field, witness);
|
||||
}
|
||||
{
|
||||
// ECMA-262, section 15.10.7.4.
|
||||
FieldDescriptor field(heap->multiline_symbol(),
|
||||
FieldDescriptor field(heap->multiline_string(),
|
||||
JSRegExp::kMultilineFieldIndex,
|
||||
final);
|
||||
initial_map->AppendDescriptor(&field, witness);
|
||||
@ -1023,7 +1023,7 @@ bool Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
|
||||
// ECMA-262, section 15.10.7.5.
|
||||
PropertyAttributes writable =
|
||||
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
|
||||
FieldDescriptor field(heap->last_index_symbol(),
|
||||
FieldDescriptor field(heap->last_index_string(),
|
||||
JSRegExp::kLastIndexFieldIndex,
|
||||
writable);
|
||||
initial_map->AppendDescriptor(&field, witness);
|
||||
@ -1041,7 +1041,7 @@ bool Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
|
||||
proto_map->set_prototype(native_context()->initial_object_prototype());
|
||||
Handle<JSObject> proto = factory->NewJSObjectFromMap(proto_map);
|
||||
proto->InObjectPropertyAtPut(JSRegExp::kSourceFieldIndex,
|
||||
heap->query_colon_symbol());
|
||||
heap->query_colon_string());
|
||||
proto->InObjectPropertyAtPut(JSRegExp::kGlobalFieldIndex,
|
||||
heap->false_value());
|
||||
proto->InObjectPropertyAtPut(JSRegExp::kIgnoreCaseFieldIndex,
|
||||
@ -1078,7 +1078,7 @@ bool Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
|
||||
// Make sure we can recognize argument objects at runtime.
|
||||
// This is done by introducing an anonymous function with
|
||||
// class_name equals 'Arguments'.
|
||||
Handle<String> symbol = factory->LookupOneByteSymbol(
|
||||
Handle<String> arguments_string = factory->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("Arguments"));
|
||||
Handle<Code> code = Handle<Code>(
|
||||
isolate->builtins()->builtin(Builtins::kIllegal));
|
||||
@ -1087,14 +1087,14 @@ bool Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
|
||||
JSObject::cast(native_context()->object_function()->prototype()));
|
||||
|
||||
Handle<JSFunction> function =
|
||||
factory->NewFunctionWithPrototype(symbol,
|
||||
factory->NewFunctionWithPrototype(arguments_string,
|
||||
JS_OBJECT_TYPE,
|
||||
JSObject::kHeaderSize,
|
||||
prototype,
|
||||
code,
|
||||
false);
|
||||
ASSERT(!function->has_initial_map());
|
||||
function->shared()->set_instance_class_name(*symbol);
|
||||
function->shared()->set_instance_class_name(*arguments_string);
|
||||
function->shared()->set_expected_nof_properties(2);
|
||||
Handle<JSObject> result = factory->NewJSObject(function);
|
||||
|
||||
@ -1103,20 +1103,20 @@ bool Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
|
||||
// callee must be added as the second property.
|
||||
CHECK_NOT_EMPTY_HANDLE(isolate,
|
||||
JSObject::SetLocalPropertyIgnoreAttributes(
|
||||
result, factory->length_symbol(),
|
||||
result, factory->length_string(),
|
||||
factory->undefined_value(), DONT_ENUM));
|
||||
CHECK_NOT_EMPTY_HANDLE(isolate,
|
||||
JSObject::SetLocalPropertyIgnoreAttributes(
|
||||
result, factory->callee_symbol(),
|
||||
result, factory->callee_string(),
|
||||
factory->undefined_value(), DONT_ENUM));
|
||||
|
||||
#ifdef DEBUG
|
||||
LookupResult lookup(isolate);
|
||||
result->LocalLookup(heap->callee_symbol(), &lookup);
|
||||
result->LocalLookup(heap->callee_string(), &lookup);
|
||||
ASSERT(lookup.IsField());
|
||||
ASSERT(lookup.GetFieldIndex().field_index() == Heap::kArgumentsCalleeIndex);
|
||||
|
||||
result->LocalLookup(heap->length_symbol(), &lookup);
|
||||
result->LocalLookup(heap->length_string(), &lookup);
|
||||
ASSERT(lookup.IsField());
|
||||
ASSERT(lookup.GetFieldIndex().field_index() == Heap::kArgumentsLengthIndex);
|
||||
|
||||
@ -1177,17 +1177,17 @@ bool Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
|
||||
map->set_instance_descriptors(*descriptors);
|
||||
|
||||
{ // length
|
||||
FieldDescriptor d(*factory->length_symbol(), 0, DONT_ENUM);
|
||||
FieldDescriptor d(*factory->length_string(), 0, DONT_ENUM);
|
||||
map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
{ // callee
|
||||
CallbacksDescriptor d(*factory->callee_symbol(),
|
||||
CallbacksDescriptor d(*factory->callee_string(),
|
||||
*callee,
|
||||
attributes);
|
||||
map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
{ // caller
|
||||
CallbacksDescriptor d(*factory->caller_symbol(),
|
||||
CallbacksDescriptor d(*factory->caller_string(),
|
||||
*caller,
|
||||
attributes);
|
||||
map->AppendDescriptor(&d, witness);
|
||||
@ -1209,12 +1209,12 @@ bool Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
|
||||
// Add length property only for strict mode boilerplate.
|
||||
CHECK_NOT_EMPTY_HANDLE(isolate,
|
||||
JSObject::SetLocalPropertyIgnoreAttributes(
|
||||
result, factory->length_symbol(),
|
||||
result, factory->length_string(),
|
||||
factory->undefined_value(), DONT_ENUM));
|
||||
|
||||
#ifdef DEBUG
|
||||
LookupResult lookup(isolate);
|
||||
result->LocalLookup(heap->length_symbol(), &lookup);
|
||||
result->LocalLookup(heap->length_string(), &lookup);
|
||||
ASSERT(lookup.IsField());
|
||||
ASSERT(lookup.GetFieldIndex().field_index() == Heap::kArgumentsLengthIndex);
|
||||
|
||||
@ -1231,14 +1231,14 @@ bool Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
|
||||
Handle<Code> code = Handle<Code>(
|
||||
isolate->builtins()->builtin(Builtins::kIllegal));
|
||||
Handle<JSFunction> context_extension_fun =
|
||||
factory->NewFunction(factory->empty_symbol(),
|
||||
factory->NewFunction(factory->empty_string(),
|
||||
JS_CONTEXT_EXTENSION_OBJECT_TYPE,
|
||||
JSObject::kHeaderSize,
|
||||
code,
|
||||
true);
|
||||
|
||||
Handle<String> name =
|
||||
factory->LookupOneByteSymbol(STATIC_ASCII_VECTOR("context_extension"));
|
||||
Handle<String> name = factory->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("context_extension"));
|
||||
context_extension_fun->shared()->set_instance_class_name(*name);
|
||||
native_context()->set_context_extension_function(*context_extension_fun);
|
||||
}
|
||||
@ -1250,7 +1250,7 @@ bool Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
|
||||
Handle<Code>(isolate->builtins()->builtin(
|
||||
Builtins::kHandleApiCallAsFunction));
|
||||
Handle<JSFunction> delegate =
|
||||
factory->NewFunction(factory->empty_symbol(), JS_OBJECT_TYPE,
|
||||
factory->NewFunction(factory->empty_string(), JS_OBJECT_TYPE,
|
||||
JSObject::kHeaderSize, code, true);
|
||||
native_context()->set_call_as_function_delegate(*delegate);
|
||||
delegate->shared()->DontAdaptArguments();
|
||||
@ -1262,7 +1262,7 @@ bool Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
|
||||
Handle<Code>(isolate->builtins()->builtin(
|
||||
Builtins::kHandleApiCallAsConstructor));
|
||||
Handle<JSFunction> delegate =
|
||||
factory->NewFunction(factory->empty_symbol(), JS_OBJECT_TYPE,
|
||||
factory->NewFunction(factory->empty_string(), JS_OBJECT_TYPE,
|
||||
JSObject::kHeaderSize, code, true);
|
||||
native_context()->set_call_as_constructor_delegate(*delegate);
|
||||
delegate->shared()->DontAdaptArguments();
|
||||
@ -1418,7 +1418,7 @@ bool Genesis::CompileScriptCached(Isolate* isolate,
|
||||
|
||||
#define INSTALL_NATIVE(Type, name, var) \
|
||||
Handle<String> var##_name = \
|
||||
factory()->LookupOneByteSymbol(STATIC_ASCII_VECTOR(name)); \
|
||||
factory()->InternalizeOneByteString(STATIC_ASCII_VECTOR(name)); \
|
||||
Object* var##_native = \
|
||||
native_context()->builtins()->GetPropertyNoExceptionThrown( \
|
||||
*var##_name); \
|
||||
@ -1508,7 +1508,7 @@ Handle<JSFunction> Genesis::InstallInternalArray(
|
||||
|
||||
{ // Add length.
|
||||
CallbacksDescriptor d(
|
||||
*factory()->length_symbol(), *array_length, attribs);
|
||||
*factory()->length_string(), *array_length, attribs);
|
||||
array_function->initial_map()->AppendDescriptor(&d, witness);
|
||||
}
|
||||
|
||||
@ -1525,12 +1525,12 @@ bool Genesis::InstallNatives() {
|
||||
Handle<Code> code = Handle<Code>(
|
||||
isolate()->builtins()->builtin(Builtins::kIllegal));
|
||||
Handle<JSFunction> builtins_fun =
|
||||
factory()->NewFunction(factory()->empty_symbol(),
|
||||
factory()->NewFunction(factory()->empty_string(),
|
||||
JS_BUILTINS_OBJECT_TYPE,
|
||||
JSBuiltinsObject::kSize, code, true);
|
||||
|
||||
Handle<String> name =
|
||||
factory()->LookupOneByteSymbol(STATIC_ASCII_VECTOR("builtins"));
|
||||
factory()->InternalizeOneByteString(STATIC_ASCII_VECTOR("builtins"));
|
||||
builtins_fun->shared()->set_instance_class_name(*name);
|
||||
builtins_fun->initial_map()->set_dictionary_map(true);
|
||||
builtins_fun->initial_map()->set_prototype(heap()->null_value());
|
||||
@ -1549,12 +1549,12 @@ bool Genesis::InstallNatives() {
|
||||
// global object.
|
||||
static const PropertyAttributes attributes =
|
||||
static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE);
|
||||
Handle<String> global_symbol =
|
||||
factory()->LookupOneByteSymbol(STATIC_ASCII_VECTOR("global"));
|
||||
Handle<String> global_string =
|
||||
factory()->InternalizeOneByteString(STATIC_ASCII_VECTOR("global"));
|
||||
Handle<Object> global_obj(native_context()->global_object(), isolate());
|
||||
CHECK_NOT_EMPTY_HANDLE(isolate(),
|
||||
JSObject::SetLocalPropertyIgnoreAttributes(
|
||||
builtins, global_symbol, global_obj, attributes));
|
||||
builtins, global_string, global_obj, attributes));
|
||||
|
||||
// Set up the reference from the global object to the builtins object.
|
||||
JSGlobalObject::cast(native_context()->global_object())->
|
||||
@ -1562,7 +1562,7 @@ bool Genesis::InstallNatives() {
|
||||
|
||||
// Create a bridge function that has context in the native context.
|
||||
Handle<JSFunction> bridge =
|
||||
factory()->NewFunction(factory()->empty_symbol(),
|
||||
factory()->NewFunction(factory()->empty_string(),
|
||||
factory()->undefined_value());
|
||||
ASSERT(bridge->context() == *isolate()->native_context());
|
||||
|
||||
@ -1593,48 +1593,51 @@ bool Genesis::InstallNatives() {
|
||||
Handle<Foreign> script_source(
|
||||
factory()->NewForeign(&Accessors::ScriptSource));
|
||||
Handle<Foreign> script_name(factory()->NewForeign(&Accessors::ScriptName));
|
||||
Handle<String> id_symbol(factory()->LookupOneByteSymbol(
|
||||
Handle<String> id_string(factory()->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("id")));
|
||||
Handle<Foreign> script_id(factory()->NewForeign(&Accessors::ScriptId));
|
||||
Handle<String> line_offset_symbol(
|
||||
factory()->LookupOneByteSymbol(STATIC_ASCII_VECTOR("line_offset")));
|
||||
Handle<String> line_offset_string(
|
||||
factory()->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("line_offset")));
|
||||
Handle<Foreign> script_line_offset(
|
||||
factory()->NewForeign(&Accessors::ScriptLineOffset));
|
||||
Handle<String> column_offset_symbol(
|
||||
factory()->LookupOneByteSymbol(STATIC_ASCII_VECTOR("column_offset")));
|
||||
Handle<String> column_offset_string(
|
||||
factory()->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("column_offset")));
|
||||
Handle<Foreign> script_column_offset(
|
||||
factory()->NewForeign(&Accessors::ScriptColumnOffset));
|
||||
Handle<String> data_symbol(factory()->LookupOneByteSymbol(
|
||||
Handle<String> data_string(factory()->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("data")));
|
||||
Handle<Foreign> script_data(factory()->NewForeign(&Accessors::ScriptData));
|
||||
Handle<String> type_symbol(factory()->LookupOneByteSymbol(
|
||||
Handle<String> type_string(factory()->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("type")));
|
||||
Handle<Foreign> script_type(factory()->NewForeign(&Accessors::ScriptType));
|
||||
Handle<String> compilation_type_symbol(
|
||||
factory()->LookupOneByteSymbol(
|
||||
Handle<String> compilation_type_string(
|
||||
factory()->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("compilation_type")));
|
||||
Handle<Foreign> script_compilation_type(
|
||||
factory()->NewForeign(&Accessors::ScriptCompilationType));
|
||||
Handle<String> line_ends_symbol(factory()->LookupOneByteSymbol(
|
||||
Handle<String> line_ends_string(factory()->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("line_ends")));
|
||||
Handle<Foreign> script_line_ends(
|
||||
factory()->NewForeign(&Accessors::ScriptLineEnds));
|
||||
Handle<String> context_data_symbol(
|
||||
factory()->LookupOneByteSymbol(STATIC_ASCII_VECTOR("context_data")));
|
||||
Handle<String> context_data_string(
|
||||
factory()->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("context_data")));
|
||||
Handle<Foreign> script_context_data(
|
||||
factory()->NewForeign(&Accessors::ScriptContextData));
|
||||
Handle<String> eval_from_script_symbol(
|
||||
factory()->LookupOneByteSymbol(
|
||||
Handle<String> eval_from_script_string(
|
||||
factory()->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("eval_from_script")));
|
||||
Handle<Foreign> script_eval_from_script(
|
||||
factory()->NewForeign(&Accessors::ScriptEvalFromScript));
|
||||
Handle<String> eval_from_script_position_symbol(
|
||||
factory()->LookupOneByteSymbol(
|
||||
Handle<String> eval_from_script_position_string(
|
||||
factory()->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("eval_from_script_position")));
|
||||
Handle<Foreign> script_eval_from_script_position(
|
||||
factory()->NewForeign(&Accessors::ScriptEvalFromScriptPosition));
|
||||
Handle<String> eval_from_function_name_symbol(
|
||||
factory()->LookupOneByteSymbol(
|
||||
Handle<String> eval_from_function_name_string(
|
||||
factory()->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("eval_from_function_name")));
|
||||
Handle<Foreign> script_eval_from_function_name(
|
||||
factory()->NewForeign(&Accessors::ScriptEvalFromFunctionName));
|
||||
@ -1644,67 +1647,67 @@ bool Genesis::InstallNatives() {
|
||||
|
||||
{
|
||||
CallbacksDescriptor d(
|
||||
*factory()->source_symbol(), *script_source, attribs);
|
||||
*factory()->source_string(), *script_source, attribs);
|
||||
script_map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
|
||||
{
|
||||
CallbacksDescriptor d(*factory()->name_symbol(), *script_name, attribs);
|
||||
CallbacksDescriptor d(*factory()->name_string(), *script_name, attribs);
|
||||
script_map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
|
||||
{
|
||||
CallbacksDescriptor d(*id_symbol, *script_id, attribs);
|
||||
CallbacksDescriptor d(*id_string, *script_id, attribs);
|
||||
script_map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
|
||||
{
|
||||
CallbacksDescriptor d(*line_offset_symbol, *script_line_offset, attribs);
|
||||
CallbacksDescriptor d(*line_offset_string, *script_line_offset, attribs);
|
||||
script_map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
|
||||
{
|
||||
CallbacksDescriptor d(
|
||||
*column_offset_symbol, *script_column_offset, attribs);
|
||||
*column_offset_string, *script_column_offset, attribs);
|
||||
script_map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
|
||||
{
|
||||
CallbacksDescriptor d(*data_symbol, *script_data, attribs);
|
||||
CallbacksDescriptor d(*data_string, *script_data, attribs);
|
||||
script_map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
|
||||
{
|
||||
CallbacksDescriptor d(*type_symbol, *script_type, attribs);
|
||||
CallbacksDescriptor d(*type_string, *script_type, attribs);
|
||||
script_map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
|
||||
{
|
||||
CallbacksDescriptor d(
|
||||
*compilation_type_symbol, *script_compilation_type, attribs);
|
||||
*compilation_type_string, *script_compilation_type, attribs);
|
||||
script_map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
|
||||
{
|
||||
CallbacksDescriptor d(*line_ends_symbol, *script_line_ends, attribs);
|
||||
CallbacksDescriptor d(*line_ends_string, *script_line_ends, attribs);
|
||||
script_map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
|
||||
{
|
||||
CallbacksDescriptor d(
|
||||
*context_data_symbol, *script_context_data, attribs);
|
||||
*context_data_string, *script_context_data, attribs);
|
||||
script_map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
|
||||
{
|
||||
CallbacksDescriptor d(
|
||||
*eval_from_script_symbol, *script_eval_from_script, attribs);
|
||||
*eval_from_script_string, *script_eval_from_script, attribs);
|
||||
script_map->AppendDescriptor(&d, witness);
|
||||
}
|
||||
|
||||
{
|
||||
CallbacksDescriptor d(
|
||||
*eval_from_script_position_symbol,
|
||||
*eval_from_script_position_string,
|
||||
*script_eval_from_script_position,
|
||||
attribs);
|
||||
script_map->AppendDescriptor(&d, witness);
|
||||
@ -1712,7 +1715,7 @@ bool Genesis::InstallNatives() {
|
||||
|
||||
{
|
||||
CallbacksDescriptor d(
|
||||
*eval_from_function_name_symbol,
|
||||
*eval_from_function_name_string,
|
||||
*script_eval_from_function_name,
|
||||
attribs);
|
||||
script_map->AppendDescriptor(&d, witness);
|
||||
@ -1784,7 +1787,7 @@ bool Genesis::InstallNatives() {
|
||||
HeapObject::cast(string_function->initial_map()->prototype())->map());
|
||||
|
||||
// Install Function.prototype.call and apply.
|
||||
{ Handle<String> key = factory()->function_class_symbol();
|
||||
{ Handle<String> key = factory()->function_class_string();
|
||||
Handle<JSFunction> function =
|
||||
Handle<JSFunction>::cast(
|
||||
GetProperty(isolate(), isolate()->global_object(), key));
|
||||
@ -1848,7 +1851,7 @@ bool Genesis::InstallNatives() {
|
||||
JSFunction* array_function = native_context()->array_function();
|
||||
Handle<DescriptorArray> array_descriptors(
|
||||
array_function->initial_map()->instance_descriptors());
|
||||
String* length = heap()->length_symbol();
|
||||
String* length = heap()->length_string();
|
||||
int old = array_descriptors->SearchWithCache(
|
||||
length, array_function->initial_map());
|
||||
ASSERT(old != DescriptorArray::kNotFound);
|
||||
@ -1858,14 +1861,14 @@ bool Genesis::InstallNatives() {
|
||||
initial_map->AppendDescriptor(&desc, witness);
|
||||
}
|
||||
{
|
||||
FieldDescriptor index_field(heap()->index_symbol(),
|
||||
FieldDescriptor index_field(heap()->index_string(),
|
||||
JSRegExpResult::kIndexIndex,
|
||||
NONE);
|
||||
initial_map->AppendDescriptor(&index_field, witness);
|
||||
}
|
||||
|
||||
{
|
||||
FieldDescriptor input_field(heap()->input_symbol(),
|
||||
FieldDescriptor input_field(heap()->input_string(),
|
||||
JSRegExpResult::kInputIndex,
|
||||
NONE);
|
||||
initial_map->AppendDescriptor(&input_field, witness);
|
||||
@ -1921,14 +1924,14 @@ static Handle<JSObject> ResolveBuiltinIdHolder(
|
||||
Handle<GlobalObject> global(native_context->global_object());
|
||||
const char* period_pos = strchr(holder_expr, '.');
|
||||
if (period_pos == NULL) {
|
||||
return Handle<JSObject>::cast(
|
||||
GetProperty(isolate, global, factory->LookupUtf8Symbol(holder_expr)));
|
||||
return Handle<JSObject>::cast(GetProperty(
|
||||
isolate, global, factory->InternalizeUtf8String(holder_expr)));
|
||||
}
|
||||
ASSERT_EQ(".prototype", period_pos);
|
||||
Vector<const char> property(holder_expr,
|
||||
static_cast<int>(period_pos - holder_expr));
|
||||
Handle<JSFunction> function = Handle<JSFunction>::cast(
|
||||
GetProperty(isolate, global, factory->LookupUtf8Symbol(property)));
|
||||
GetProperty(isolate, global, factory->InternalizeUtf8String(property)));
|
||||
return Handle<JSObject>(JSObject::cast(function->prototype()));
|
||||
}
|
||||
|
||||
@ -1937,7 +1940,7 @@ static void InstallBuiltinFunctionId(Handle<JSObject> holder,
|
||||
const char* function_name,
|
||||
BuiltinFunctionId id) {
|
||||
Factory* factory = holder->GetIsolate()->factory();
|
||||
Handle<String> name = factory->LookupUtf8Symbol(function_name);
|
||||
Handle<String> name = factory->InternalizeUtf8String(function_name);
|
||||
Object* function_object = holder->GetProperty(*name)->ToObjectUnchecked();
|
||||
Handle<JSFunction> function(JSFunction::cast(function_object));
|
||||
function->shared()->set_function_data(Smi::FromInt(id));
|
||||
@ -2027,7 +2030,8 @@ void Genesis::InstallSpecialObjects(Handle<Context> native_context) {
|
||||
native_context->global_object()));
|
||||
// Expose the natives in global if a name for it is specified.
|
||||
if (FLAG_expose_natives_as != NULL && strlen(FLAG_expose_natives_as) != 0) {
|
||||
Handle<String> natives = factory->LookupUtf8Symbol(FLAG_expose_natives_as);
|
||||
Handle<String> natives =
|
||||
factory->InternalizeUtf8String(FLAG_expose_natives_as);
|
||||
CHECK_NOT_EMPTY_HANDLE(isolate,
|
||||
JSObject::SetLocalPropertyIgnoreAttributes(
|
||||
global, natives,
|
||||
@ -2037,10 +2041,10 @@ void Genesis::InstallSpecialObjects(Handle<Context> native_context) {
|
||||
|
||||
Handle<Object> Error = GetProperty(global, "Error");
|
||||
if (Error->IsJSObject()) {
|
||||
Handle<String> name =
|
||||
factory->LookupOneByteSymbol(STATIC_ASCII_VECTOR("stackTraceLimit"));
|
||||
Handle<Smi> stack_trace_limit(Smi::FromInt(FLAG_stack_trace_limit),
|
||||
isolate);
|
||||
Handle<String> name = factory->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("stackTraceLimit"));
|
||||
Handle<Smi> stack_trace_limit(
|
||||
Smi::FromInt(FLAG_stack_trace_limit), isolate);
|
||||
CHECK_NOT_EMPTY_HANDLE(isolate,
|
||||
JSObject::SetLocalPropertyIgnoreAttributes(
|
||||
Handle<JSObject>::cast(Error), name,
|
||||
@ -2061,9 +2065,9 @@ void Genesis::InstallSpecialObjects(Handle<Context> native_context) {
|
||||
native_context->security_token());
|
||||
|
||||
Handle<String> debug_string =
|
||||
factory->LookupUtf8Symbol(FLAG_expose_debug_as);
|
||||
Handle<Object> global_proxy(debug->debug_context()->global_proxy(),
|
||||
isolate);
|
||||
factory->InternalizeUtf8String(FLAG_expose_debug_as);
|
||||
Handle<Object> global_proxy(
|
||||
debug->debug_context()->global_proxy(), isolate);
|
||||
CHECK_NOT_EMPTY_HANDLE(isolate,
|
||||
JSObject::SetLocalPropertyIgnoreAttributes(
|
||||
global, debug_string, global_proxy, DONT_ENUM));
|
||||
@ -2205,7 +2209,8 @@ bool Genesis::InstallJSBuiltins(Handle<JSBuiltinsObject> builtins) {
|
||||
HandleScope scope(isolate());
|
||||
for (int i = 0; i < Builtins::NumberOfJavaScriptBuiltins(); i++) {
|
||||
Builtins::JavaScript id = static_cast<Builtins::JavaScript>(i);
|
||||
Handle<String> name = factory()->LookupUtf8Symbol(Builtins::GetName(id));
|
||||
Handle<String> name =
|
||||
factory()->InternalizeUtf8String(Builtins::GetName(id));
|
||||
Object* function_object = builtins->GetPropertyNoExceptionThrown(*name);
|
||||
Handle<JSFunction> function
|
||||
= Handle<JSFunction>(JSFunction::cast(function_object));
|
||||
|
@ -171,7 +171,7 @@ void CodeStubGraphBuilder<FastCloneShallowObjectStub>::BuildCodeStub() {
|
||||
HInstruction* value =
|
||||
AddInstruction(new(zone) HLoadNamedField(boilerplate, true, i));
|
||||
AddInstruction(new(zone) HStoreNamedField(object,
|
||||
factory->empty_symbol(),
|
||||
factory->empty_string(),
|
||||
value,
|
||||
true, i));
|
||||
AddSimulate(BailoutId::StubEntry());
|
||||
@ -290,14 +290,14 @@ void CodeStubGraphBuilder<TransitionElementsKindStub>::BuildCodeStub() {
|
||||
to_kind, array_length);
|
||||
|
||||
AddInstruction(new(zone) HStoreNamedField(js_array,
|
||||
factory->elements_field_symbol(),
|
||||
factory->elements_field_string(),
|
||||
new_elements, true,
|
||||
JSArray::kElementsOffset));
|
||||
AddSimulate(BailoutId::StubEntry());
|
||||
|
||||
if_builder.End();
|
||||
|
||||
AddInstruction(new(zone) HStoreNamedField(js_array, factory->length_symbol(),
|
||||
AddInstruction(new(zone) HStoreNamedField(js_array, factory->length_string(),
|
||||
map, true, JSArray::kMapOffset));
|
||||
AddSimulate(BailoutId::StubEntry());
|
||||
|
||||
|
@ -295,8 +295,8 @@ void ICCompareStub::AddToSpecialCache(Handle<Code> new_object) {
|
||||
Factory* factory = isolate->factory();
|
||||
return Map::UpdateCodeCache(known_map_,
|
||||
strict() ?
|
||||
factory->strict_compare_ic_symbol() :
|
||||
factory->compare_ic_symbol(),
|
||||
factory->strict_compare_ic_string() :
|
||||
factory->compare_ic_string(),
|
||||
new_object);
|
||||
}
|
||||
|
||||
@ -307,10 +307,13 @@ bool ICCompareStub::FindCodeInSpecialCache(Code** code_out, Isolate* isolate) {
|
||||
static_cast<Code::Kind>(GetCodeKind()),
|
||||
UNINITIALIZED);
|
||||
ASSERT(op_ == Token::EQ || op_ == Token::EQ_STRICT);
|
||||
String* symbol = strict() ?
|
||||
*factory->strict_compare_ic_symbol() :
|
||||
*factory->compare_ic_symbol();
|
||||
Handle<Object> probe(known_map_->FindInCodeCache(symbol, flags), isolate);
|
||||
Handle<Object> probe(
|
||||
known_map_->FindInCodeCache(
|
||||
strict() ?
|
||||
*factory->strict_compare_ic_string() :
|
||||
*factory->compare_ic_string(),
|
||||
flags),
|
||||
isolate);
|
||||
if (probe->IsCode()) {
|
||||
*code_out = Code::cast(*probe);
|
||||
#ifdef DEBUG
|
||||
@ -370,8 +373,8 @@ void ICCompareStub::Generate(MacroAssembler* masm) {
|
||||
case CompareIC::STRING:
|
||||
GenerateStrings(masm);
|
||||
break;
|
||||
case CompareIC::SYMBOL:
|
||||
GenerateSymbols(masm);
|
||||
case CompareIC::INTERNALIZED_STRING:
|
||||
GenerateInternalizedStrings(masm);
|
||||
break;
|
||||
case CompareIC::OBJECT:
|
||||
GenerateObjects(masm);
|
||||
|
@ -809,7 +809,7 @@ class ICCompareStub: public PlatformCodeStub {
|
||||
|
||||
void GenerateSmis(MacroAssembler* masm);
|
||||
void GenerateNumbers(MacroAssembler* masm);
|
||||
void GenerateSymbols(MacroAssembler* masm);
|
||||
void GenerateInternalizedStrings(MacroAssembler* masm);
|
||||
void GenerateStrings(MacroAssembler* masm);
|
||||
void GenerateObjects(MacroAssembler* masm);
|
||||
void GenerateMiss(MacroAssembler* masm);
|
||||
|
@ -481,9 +481,9 @@ double InternalStringToDouble(UnicodeCache* unicode_cache,
|
||||
sign = NEGATIVE;
|
||||
}
|
||||
|
||||
static const char kInfinitySymbol[] = "Infinity";
|
||||
if (*current == kInfinitySymbol[0]) {
|
||||
if (!SubStringEquals(¤t, end, kInfinitySymbol)) {
|
||||
static const char kInfinityString[] = "Infinity";
|
||||
if (*current == kInfinityString[0]) {
|
||||
if (!SubStringEquals(¤t, end, kInfinityString)) {
|
||||
return JunkStringValue();
|
||||
}
|
||||
|
||||
|
18
src/debug.cc
18
src/debug.cc
@ -842,7 +842,7 @@ bool Debug::Load() {
|
||||
isolate_->set_context(*context);
|
||||
|
||||
// Expose the builtins object in the debugger context.
|
||||
Handle<String> key = isolate_->factory()->LookupOneByteSymbol(
|
||||
Handle<String> key = isolate_->factory()->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("builtins"));
|
||||
Handle<GlobalObject> global = Handle<GlobalObject>(context->global_object());
|
||||
RETURN_IF_EMPTY_HANDLE_VALUE(
|
||||
@ -1109,13 +1109,13 @@ bool Debug::CheckBreakPoint(Handle<Object> break_point_object) {
|
||||
if (!break_point_object->IsJSObject()) return true;
|
||||
|
||||
// Get the function IsBreakPointTriggered (defined in debug-debugger.js).
|
||||
Handle<String> is_break_point_triggered_symbol =
|
||||
factory->LookupOneByteSymbol(
|
||||
Handle<String> is_break_point_triggered_string =
|
||||
factory->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("IsBreakPointTriggered"));
|
||||
Handle<JSFunction> check_break_point =
|
||||
Handle<JSFunction>(JSFunction::cast(
|
||||
debug_context()->global_object()->GetPropertyNoExceptionThrown(
|
||||
*is_break_point_triggered_symbol)));
|
||||
*is_break_point_triggered_string)));
|
||||
|
||||
// Get the break id as an object.
|
||||
Handle<Object> break_id = factory->NewNumberFromInt(Debug::break_id());
|
||||
@ -2441,7 +2441,7 @@ void Debug::ClearMirrorCache() {
|
||||
ASSERT(isolate_->context() == *Debug::debug_context());
|
||||
|
||||
// Clear the mirror cache.
|
||||
Handle<String> function_name = isolate_->factory()->LookupOneByteSymbol(
|
||||
Handle<String> function_name = isolate_->factory()->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("ClearMirrorCache"));
|
||||
Handle<Object> fun(
|
||||
isolate_->global_object()->GetPropertyNoExceptionThrown(*function_name),
|
||||
@ -2570,7 +2570,7 @@ Handle<Object> Debugger::MakeJSObject(Vector<const char> constructor_name,
|
||||
|
||||
// Create the execution state object.
|
||||
Handle<String> constructor_str =
|
||||
isolate_->factory()->LookupUtf8Symbol(constructor_name);
|
||||
isolate_->factory()->InternalizeUtf8String(constructor_name);
|
||||
Handle<Object> constructor(
|
||||
isolate_->global_object()->GetPropertyNoExceptionThrown(*constructor_str),
|
||||
isolate_);
|
||||
@ -2800,13 +2800,13 @@ void Debugger::OnAfterCompile(Handle<Script> script,
|
||||
// script. Make sure that these break points are set.
|
||||
|
||||
// Get the function UpdateScriptBreakPoints (defined in debug-debugger.js).
|
||||
Handle<String> update_script_break_points_symbol =
|
||||
isolate_->factory()->LookupOneByteSymbol(
|
||||
Handle<String> update_script_break_points_string =
|
||||
isolate_->factory()->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("UpdateScriptBreakPoints"));
|
||||
Handle<Object> update_script_break_points =
|
||||
Handle<Object>(
|
||||
debug->debug_context()->global_object()->GetPropertyNoExceptionThrown(
|
||||
*update_script_break_points_symbol),
|
||||
*update_script_break_points_string),
|
||||
isolate_);
|
||||
if (!update_script_break_points->IsJSFunction()) {
|
||||
return;
|
||||
|
@ -683,10 +683,8 @@ Handle<Object> Execution::CharAt(Handle<String> string, uint32_t index) {
|
||||
return factory->undefined_value();
|
||||
}
|
||||
|
||||
Handle<Object> char_at =
|
||||
GetProperty(isolate,
|
||||
isolate->js_builtins_object(),
|
||||
factory->char_at_symbol());
|
||||
Handle<Object> char_at = GetProperty(
|
||||
isolate, isolate->js_builtins_object(), factory->char_at_string());
|
||||
if (!char_at->IsJSFunction()) {
|
||||
return factory->undefined_value();
|
||||
}
|
||||
@ -787,7 +785,7 @@ Handle<String> Execution::GetStackTraceLine(Handle<Object> recv,
|
||||
args,
|
||||
&caught_exception);
|
||||
if (caught_exception || !result->IsString()) {
|
||||
return isolate->factory()->empty_symbol();
|
||||
return isolate->factory()->empty_string();
|
||||
}
|
||||
|
||||
return Handle<String>::cast(result);
|
||||
|
@ -99,7 +99,7 @@ v8::Handle<v8::Value> ExternalizeStringExtension::Externalize(
|
||||
SimpleAsciiStringResource* resource = new SimpleAsciiStringResource(
|
||||
reinterpret_cast<char*>(data), string->length());
|
||||
result = string->MakeExternal(resource);
|
||||
if (result && !string->IsSymbol()) {
|
||||
if (result && !string->IsInternalizedString()) {
|
||||
HEAP->external_string_table()->AddString(*string);
|
||||
}
|
||||
if (!result) delete resource;
|
||||
@ -109,7 +109,7 @@ v8::Handle<v8::Value> ExternalizeStringExtension::Externalize(
|
||||
SimpleTwoByteStringResource* resource = new SimpleTwoByteStringResource(
|
||||
data, string->length());
|
||||
result = string->MakeExternal(resource);
|
||||
if (result && !string->IsSymbol()) {
|
||||
if (result && !string->IsInternalizedString()) {
|
||||
HEAP->external_string_table()->AddString(*string);
|
||||
}
|
||||
if (!result) delete resource;
|
||||
|
@ -157,41 +157,39 @@ Handle<TypeFeedbackInfo> Factory::NewTypeFeedbackInfo() {
|
||||
}
|
||||
|
||||
|
||||
// Symbols are created in the old generation (data space).
|
||||
Handle<String> Factory::LookupUtf8Symbol(Vector<const char> string) {
|
||||
// Internalized strings are created in the old generation (data space).
|
||||
Handle<String> Factory::InternalizeUtf8String(Vector<const char> string) {
|
||||
CALL_HEAP_FUNCTION(isolate(),
|
||||
isolate()->heap()->LookupUtf8Symbol(string),
|
||||
isolate()->heap()->InternalizeUtf8String(string),
|
||||
String);
|
||||
}
|
||||
|
||||
// Symbols are created in the old generation (data space).
|
||||
Handle<String> Factory::LookupSymbol(Handle<String> string) {
|
||||
// Internalized strings are created in the old generation (data space).
|
||||
Handle<String> Factory::InternalizeString(Handle<String> string) {
|
||||
CALL_HEAP_FUNCTION(isolate(),
|
||||
isolate()->heap()->LookupSymbol(*string),
|
||||
isolate()->heap()->InternalizeString(*string),
|
||||
String);
|
||||
}
|
||||
|
||||
Handle<String> Factory::LookupOneByteSymbol(Vector<const uint8_t> string) {
|
||||
Handle<String> Factory::InternalizeOneByteString(Vector<const uint8_t> string) {
|
||||
CALL_HEAP_FUNCTION(isolate(),
|
||||
isolate()->heap()->LookupOneByteSymbol(string),
|
||||
isolate()->heap()->InternalizeOneByteString(string),
|
||||
String);
|
||||
}
|
||||
|
||||
|
||||
Handle<String> Factory::LookupOneByteSymbol(Handle<SeqOneByteString> string,
|
||||
int from,
|
||||
int length) {
|
||||
Handle<String> Factory::InternalizeOneByteString(
|
||||
Handle<SeqOneByteString> string, int from, int length) {
|
||||
CALL_HEAP_FUNCTION(isolate(),
|
||||
isolate()->heap()->LookupOneByteSymbol(string,
|
||||
from,
|
||||
length),
|
||||
isolate()->heap()->InternalizeOneByteString(
|
||||
string, from, length),
|
||||
String);
|
||||
}
|
||||
|
||||
|
||||
Handle<String> Factory::LookupTwoByteSymbol(Vector<const uc16> string) {
|
||||
Handle<String> Factory::InternalizeTwoByteString(Vector<const uc16> string) {
|
||||
CALL_HEAP_FUNCTION(isolate(),
|
||||
isolate()->heap()->LookupTwoByteSymbol(string),
|
||||
isolate()->heap()->InternalizeTwoByteString(string),
|
||||
String);
|
||||
}
|
||||
|
||||
@ -751,7 +749,7 @@ Handle<String> Factory::EmergencyNewError(const char* type,
|
||||
Handle<Object> Factory::NewError(const char* maker,
|
||||
const char* type,
|
||||
Handle<JSArray> args) {
|
||||
Handle<String> make_str = LookupUtf8Symbol(maker);
|
||||
Handle<String> make_str = InternalizeUtf8String(maker);
|
||||
Handle<Object> fun_obj(
|
||||
isolate()->js_builtins_object()->GetPropertyNoExceptionThrown(*make_str),
|
||||
isolate());
|
||||
@ -761,7 +759,7 @@ Handle<Object> Factory::NewError(const char* maker,
|
||||
return EmergencyNewError(type, args);
|
||||
}
|
||||
Handle<JSFunction> fun = Handle<JSFunction>::cast(fun_obj);
|
||||
Handle<Object> type_obj = LookupUtf8Symbol(type);
|
||||
Handle<Object> type_obj = InternalizeUtf8String(type);
|
||||
Handle<Object> argv[] = { type_obj, args };
|
||||
|
||||
// Invoke the JavaScript factory method. If an exception is thrown while
|
||||
@ -783,7 +781,7 @@ Handle<Object> Factory::NewError(Handle<String> message) {
|
||||
|
||||
Handle<Object> Factory::NewError(const char* constructor,
|
||||
Handle<String> message) {
|
||||
Handle<String> constr = LookupUtf8Symbol(constructor);
|
||||
Handle<String> constr = InternalizeUtf8String(constructor);
|
||||
Handle<JSFunction> fun = Handle<JSFunction>(
|
||||
JSFunction::cast(isolate()->js_builtins_object()->
|
||||
GetPropertyNoExceptionThrown(*constr)));
|
||||
@ -861,7 +859,7 @@ Handle<JSFunction> Factory::NewFunctionWithPrototype(Handle<String> name,
|
||||
// Currently safe because it is only invoked from Genesis.
|
||||
CHECK_NOT_EMPTY_HANDLE(isolate(),
|
||||
JSObject::SetLocalPropertyIgnoreAttributes(
|
||||
prototype, constructor_symbol(),
|
||||
prototype, constructor_string(),
|
||||
function, DONT_ENUM));
|
||||
return function;
|
||||
}
|
||||
@ -919,9 +917,9 @@ Handle<Code> Factory::CopyCode(Handle<Code> code, Vector<byte> reloc_info) {
|
||||
}
|
||||
|
||||
|
||||
Handle<String> Factory::SymbolFromString(Handle<String> value) {
|
||||
Handle<String> Factory::InternalizedStringFromString(Handle<String> value) {
|
||||
CALL_HEAP_FUNCTION(isolate(),
|
||||
isolate()->heap()->LookupSymbol(*value), String);
|
||||
isolate()->heap()->InternalizeString(*value), String);
|
||||
}
|
||||
|
||||
|
||||
@ -1267,7 +1265,7 @@ Handle<JSFunction> Factory::CreateApiFunction(
|
||||
ASSERT(type != INVALID_TYPE);
|
||||
|
||||
Handle<JSFunction> result =
|
||||
NewFunction(Factory::empty_symbol(),
|
||||
NewFunction(Factory::empty_string(),
|
||||
type,
|
||||
instance_size,
|
||||
code,
|
||||
@ -1452,9 +1450,9 @@ void Factory::ConfigureInstance(Handle<FunctionTemplateInfo> desc,
|
||||
|
||||
Handle<Object> Factory::GlobalConstantFor(Handle<String> name) {
|
||||
Heap* h = isolate()->heap();
|
||||
if (name->Equals(h->undefined_symbol())) return undefined_value();
|
||||
if (name->Equals(h->nan_symbol())) return nan_value();
|
||||
if (name->Equals(h->infinity_symbol())) return infinity_value();
|
||||
if (name->Equals(h->undefined_string())) return undefined_value();
|
||||
if (name->Equals(h->nan_string())) return nan_value();
|
||||
if (name->Equals(h->infinity_string())) return infinity_value();
|
||||
return Handle<Object>::null();
|
||||
}
|
||||
|
||||
|
@ -79,16 +79,16 @@ class Factory {
|
||||
|
||||
Handle<TypeFeedbackInfo> NewTypeFeedbackInfo();
|
||||
|
||||
Handle<String> LookupUtf8Symbol(Vector<const char> str);
|
||||
Handle<String> LookupUtf8Symbol(const char* str) {
|
||||
return LookupUtf8Symbol(CStrVector(str));
|
||||
Handle<String> InternalizeUtf8String(Vector<const char> str);
|
||||
Handle<String> InternalizeUtf8String(const char* str) {
|
||||
return InternalizeUtf8String(CStrVector(str));
|
||||
}
|
||||
Handle<String> LookupSymbol(Handle<String> str);
|
||||
Handle<String> LookupOneByteSymbol(Vector<const uint8_t> str);
|
||||
Handle<String> LookupOneByteSymbol(Handle<SeqOneByteString>,
|
||||
Handle<String> InternalizeString(Handle<String> str);
|
||||
Handle<String> InternalizeOneByteString(Vector<const uint8_t> str);
|
||||
Handle<String> InternalizeOneByteString(Handle<SeqOneByteString>,
|
||||
int from,
|
||||
int length);
|
||||
Handle<String> LookupTwoByteSymbol(Vector<const uc16> str);
|
||||
Handle<String> InternalizeTwoByteString(Vector<const uc16> str);
|
||||
|
||||
|
||||
// String creation functions. Most of the string creation functions take
|
||||
@ -195,8 +195,8 @@ class Factory {
|
||||
Handle<Context> previous,
|
||||
Handle<ScopeInfo> scope_info);
|
||||
|
||||
// Return the Symbol matching the passed in string.
|
||||
Handle<String> SymbolFromString(Handle<String> value);
|
||||
// Return the internalized version of the passed in string.
|
||||
Handle<String> InternalizedStringFromString(Handle<String> value);
|
||||
|
||||
// Allocate a new struct. The struct is pretenured (allocated directly in
|
||||
// the old generation).
|
||||
@ -434,16 +434,16 @@ class Factory {
|
||||
ROOT_LIST(ROOT_ACCESSOR)
|
||||
#undef ROOT_ACCESSOR_ACCESSOR
|
||||
|
||||
#define SYMBOL_ACCESSOR(name, str) \
|
||||
#define STRING_ACCESSOR(name, str) \
|
||||
inline Handle<String> name() { \
|
||||
return Handle<String>(BitCast<String**>( \
|
||||
&isolate()->heap()->roots_[Heap::k##name##RootIndex])); \
|
||||
}
|
||||
SYMBOL_LIST(SYMBOL_ACCESSOR)
|
||||
#undef SYMBOL_ACCESSOR
|
||||
INTERNALIZED_STRING_LIST(STRING_ACCESSOR)
|
||||
#undef STRING_ACCESSOR
|
||||
|
||||
Handle<String> hidden_symbol() {
|
||||
return Handle<String>(&isolate()->heap()->hidden_symbol_);
|
||||
Handle<String> hidden_string() {
|
||||
return Handle<String>(&isolate()->heap()->hidden_string_);
|
||||
}
|
||||
|
||||
Handle<SharedFunctionInfo> NewSharedFunctionInfo(
|
||||
|
@ -55,14 +55,14 @@ void FuncNameInferrer::PushEnclosingName(Handle<String> name) {
|
||||
|
||||
|
||||
void FuncNameInferrer::PushLiteralName(Handle<String> name) {
|
||||
if (IsOpen() && !isolate()->heap()->prototype_symbol()->Equals(*name)) {
|
||||
if (IsOpen() && !isolate()->heap()->prototype_string()->Equals(*name)) {
|
||||
names_stack_.Add(Name(name, kLiteralName), zone());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FuncNameInferrer::PushVariableName(Handle<String> name) {
|
||||
if (IsOpen() && !isolate()->heap()->result_symbol()->Equals(*name)) {
|
||||
if (IsOpen() && !isolate()->heap()->result_string()->Equals(*name)) {
|
||||
names_stack_.Add(Name(name, kVariableName), zone());
|
||||
}
|
||||
}
|
||||
@ -85,7 +85,7 @@ Handle<String> FuncNameInferrer::MakeNameFromStackHelper(int pos,
|
||||
if (prev->length() > 0) {
|
||||
Factory* factory = isolate()->factory();
|
||||
Handle<String> curr = factory->NewConsString(
|
||||
factory->dot_symbol(), names_stack_.at(pos).name);
|
||||
factory->dot_string(), names_stack_.at(pos).name);
|
||||
return MakeNameFromStackHelper(pos + 1,
|
||||
factory->NewConsString(prev, curr));
|
||||
} else {
|
||||
|
@ -276,7 +276,7 @@ Handle<Object> SetPropertyWithInterceptor(Handle<JSObject> object,
|
||||
Handle<Object> GetProperty(Handle<JSReceiver> obj,
|
||||
const char* name) {
|
||||
Isolate* isolate = obj->GetIsolate();
|
||||
Handle<String> str = isolate->factory()->LookupUtf8Symbol(name);
|
||||
Handle<String> str = isolate->factory()->InternalizeUtf8String(name);
|
||||
CALL_HEAP_FUNCTION(isolate, obj->GetProperty(*str), Object);
|
||||
}
|
||||
|
||||
@ -603,7 +603,7 @@ v8::Handle<v8::Array> GetKeysForIndexedInterceptor(Handle<JSReceiver> receiver,
|
||||
Handle<Object> GetScriptNameOrSourceURL(Handle<Script> script) {
|
||||
Isolate* isolate = script->GetIsolate();
|
||||
Handle<String> name_or_source_url_key =
|
||||
isolate->factory()->LookupOneByteSymbol(
|
||||
isolate->factory()->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("nameOrSourceURL"));
|
||||
Handle<JSValue> script_wrapper = GetScriptWrapper(script);
|
||||
Handle<Object> property = GetProperty(isolate,
|
||||
|
@ -112,32 +112,33 @@ bool inline Heap::IsOneByte(String* str, int chars) {
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* Heap::AllocateSymbolFromUtf8(Vector<const char> str,
|
||||
int chars,
|
||||
uint32_t hash_field) {
|
||||
MaybeObject* Heap::AllocateInternalizedStringFromUtf8(
|
||||
Vector<const char> str, int chars, uint32_t hash_field) {
|
||||
if (IsOneByte(str, chars)) {
|
||||
return AllocateOneByteSymbol(Vector<const uint8_t>::cast(str), hash_field);
|
||||
return AllocateOneByteInternalizedString(
|
||||
Vector<const uint8_t>::cast(str), hash_field);
|
||||
}
|
||||
return AllocateInternalSymbol<false>(str, chars, hash_field);
|
||||
return AllocateInternalizedStringImpl<false>(str, chars, hash_field);
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
MaybeObject* Heap::AllocateInternalSymbol(T t, int chars, uint32_t hash_field) {
|
||||
MaybeObject* Heap::AllocateInternalizedStringImpl(
|
||||
T t, int chars, uint32_t hash_field) {
|
||||
if (IsOneByte(t, chars)) {
|
||||
return AllocateInternalSymbol<true>(t, chars, hash_field);
|
||||
return AllocateInternalizedStringImpl<true>(t, chars, hash_field);
|
||||
}
|
||||
return AllocateInternalSymbol<false>(t, chars, hash_field);
|
||||
return AllocateInternalizedStringImpl<false>(t, chars, hash_field);
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* Heap::AllocateOneByteSymbol(Vector<const uint8_t> str,
|
||||
uint32_t hash_field) {
|
||||
MaybeObject* Heap::AllocateOneByteInternalizedString(Vector<const uint8_t> str,
|
||||
uint32_t hash_field) {
|
||||
if (str.length() > SeqOneByteString::kMaxLength) {
|
||||
return Failure::OutOfMemoryException(0x2);
|
||||
}
|
||||
// Compute map and object size.
|
||||
Map* map = ascii_symbol_map();
|
||||
Map* map = ascii_internalized_string_map();
|
||||
int size = SeqOneByteString::SizeFor(str.length());
|
||||
|
||||
// Allocate string.
|
||||
@ -165,13 +166,13 @@ MaybeObject* Heap::AllocateOneByteSymbol(Vector<const uint8_t> str,
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* Heap::AllocateTwoByteSymbol(Vector<const uc16> str,
|
||||
uint32_t hash_field) {
|
||||
MaybeObject* Heap::AllocateTwoByteInternalizedString(Vector<const uc16> str,
|
||||
uint32_t hash_field) {
|
||||
if (str.length() > SeqTwoByteString::kMaxLength) {
|
||||
return Failure::OutOfMemoryException(0x3);
|
||||
}
|
||||
// Compute map and object size.
|
||||
Map* map = symbol_map();
|
||||
Map* map = internalized_string_map();
|
||||
int size = SeqTwoByteString::SizeFor(str.length());
|
||||
|
||||
// Allocate string.
|
||||
|
@ -1019,7 +1019,7 @@ void V8HeapExplorer::ExtractJSObjectReferences(
|
||||
ExtractElementReferences(js_obj, entry);
|
||||
ExtractInternalReferences(js_obj, entry);
|
||||
SetPropertyReference(
|
||||
obj, entry, heap_->Proto_symbol(), js_obj->GetPrototype());
|
||||
obj, entry, heap_->proto_string(), js_obj->GetPrototype());
|
||||
if (obj->IsJSFunction()) {
|
||||
JSFunction* js_fun = JSFunction::cast(js_obj);
|
||||
Object* proto_or_map = js_fun->prototype_or_initial_map();
|
||||
@ -1027,13 +1027,13 @@ void V8HeapExplorer::ExtractJSObjectReferences(
|
||||
if (!proto_or_map->IsMap()) {
|
||||
SetPropertyReference(
|
||||
obj, entry,
|
||||
heap_->prototype_symbol(), proto_or_map,
|
||||
heap_->prototype_string(), proto_or_map,
|
||||
NULL,
|
||||
JSFunction::kPrototypeOrInitialMapOffset);
|
||||
} else {
|
||||
SetPropertyReference(
|
||||
obj, entry,
|
||||
heap_->prototype_symbol(), js_fun->prototype());
|
||||
heap_->prototype_string(), js_fun->prototype());
|
||||
}
|
||||
}
|
||||
SharedFunctionInfo* shared_info = js_fun->shared();
|
||||
@ -1323,7 +1323,7 @@ void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj, int entry) {
|
||||
String* k = descs->GetKey(i);
|
||||
if (index < js_obj->map()->inobject_properties()) {
|
||||
Object* value = js_obj->InObjectPropertyAt(index);
|
||||
if (k != heap_->hidden_symbol()) {
|
||||
if (k != heap_->hidden_string()) {
|
||||
SetPropertyReference(
|
||||
js_obj, entry,
|
||||
k, value,
|
||||
@ -1338,7 +1338,7 @@ void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj, int entry) {
|
||||
}
|
||||
} else {
|
||||
Object* value = js_obj->FastPropertyAt(index);
|
||||
if (k != heap_->hidden_symbol()) {
|
||||
if (k != heap_->hidden_string()) {
|
||||
SetPropertyReference(js_obj, entry, k, value);
|
||||
} else {
|
||||
TagObject(value, "(hidden properties)");
|
||||
@ -1388,7 +1388,7 @@ void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj, int entry) {
|
||||
Object* value = target->IsJSGlobalPropertyCell()
|
||||
? JSGlobalPropertyCell::cast(target)->value()
|
||||
: target;
|
||||
if (k != heap_->hidden_symbol()) {
|
||||
if (k != heap_->hidden_string()) {
|
||||
SetPropertyReference(js_obj, entry, String::cast(k), value);
|
||||
} else {
|
||||
TagObject(value, "(hidden properties)");
|
||||
@ -1438,15 +1438,15 @@ void V8HeapExplorer::ExtractInternalReferences(JSObject* js_obj, int entry) {
|
||||
|
||||
String* V8HeapExplorer::GetConstructorName(JSObject* object) {
|
||||
Heap* heap = object->GetHeap();
|
||||
if (object->IsJSFunction()) return heap->closure_symbol();
|
||||
if (object->IsJSFunction()) return heap->closure_string();
|
||||
String* constructor_name = object->constructor_name();
|
||||
if (constructor_name == heap->Object_symbol()) {
|
||||
if (constructor_name == heap->Object_string()) {
|
||||
// Look up an immediate "constructor" property, if it is a function,
|
||||
// return its name. This is for instances of binding objects, which
|
||||
// have prototype constructor type "Object".
|
||||
Object* constructor_prop = NULL;
|
||||
LookupResult result(heap->isolate());
|
||||
object->LocalLookupRealNamedProperty(heap->constructor_symbol(), &result);
|
||||
object->LocalLookupRealNamedProperty(heap->constructor_string(), &result);
|
||||
if (!result.IsFound()) return object->constructor_name();
|
||||
|
||||
constructor_prop = result.GetLazyValue();
|
||||
@ -1768,9 +1768,9 @@ const char* V8HeapExplorer::GetStrongGcSubrootName(Object* object) {
|
||||
#define STRUCT_MAP_NAME(NAME, Name, name) NAME_ENTRY(name##_map)
|
||||
STRUCT_LIST(STRUCT_MAP_NAME)
|
||||
#undef STRUCT_MAP_NAME
|
||||
#define SYMBOL_NAME(name, str) NAME_ENTRY(name)
|
||||
SYMBOL_LIST(SYMBOL_NAME)
|
||||
#undef SYMBOL_NAME
|
||||
#define STRING_NAME(name, str) NAME_ENTRY(name)
|
||||
INTERNALIZED_STRING_LIST(STRING_NAME)
|
||||
#undef STRING_NAME
|
||||
#undef NAME_ENTRY
|
||||
CHECK(!strong_gc_subroot_names_.is_empty());
|
||||
}
|
||||
|
296
src/heap.cc
296
src/heap.cc
@ -127,7 +127,7 @@ Heap::Heap()
|
||||
amount_of_external_allocated_memory_at_last_global_gc_(0),
|
||||
old_gen_exhausted_(false),
|
||||
store_buffer_rebuilder_(store_buffer()),
|
||||
hidden_symbol_(NULL),
|
||||
hidden_string_(NULL),
|
||||
global_gc_prologue_callback_(NULL),
|
||||
global_gc_epilogue_callback_(NULL),
|
||||
gc_safe_size_of_old_object_(NULL),
|
||||
@ -492,10 +492,10 @@ void Heap::GarbageCollectionEpilogue() {
|
||||
isolate_->counters()->alive_after_last_gc()->Set(
|
||||
static_cast<int>(SizeOfObjects()));
|
||||
|
||||
isolate_->counters()->symbol_table_capacity()->Set(
|
||||
symbol_table()->Capacity());
|
||||
isolate_->counters()->string_table_capacity()->Set(
|
||||
string_table()->Capacity());
|
||||
isolate_->counters()->number_of_symbols()->Set(
|
||||
symbol_table()->NumberOfElements());
|
||||
string_table()->NumberOfElements());
|
||||
|
||||
if (CommittedMemory() > 0) {
|
||||
isolate_->counters()->external_fragmentation_total()->AddSample(
|
||||
@ -704,24 +704,25 @@ void Heap::MoveElements(FixedArray* array,
|
||||
|
||||
|
||||
#ifdef VERIFY_HEAP
|
||||
// Helper class for verifying the symbol table.
|
||||
class SymbolTableVerifier : public ObjectVisitor {
|
||||
// Helper class for verifying the string table.
|
||||
class StringTableVerifier : public ObjectVisitor {
|
||||
public:
|
||||
void VisitPointers(Object** start, Object** end) {
|
||||
// Visit all HeapObject pointers in [start, end).
|
||||
for (Object** p = start; p < end; p++) {
|
||||
if ((*p)->IsHeapObject()) {
|
||||
// Check that the symbol is actually a symbol.
|
||||
CHECK((*p)->IsTheHole() || (*p)->IsUndefined() || (*p)->IsSymbol());
|
||||
// Check that the string is actually internalized.
|
||||
CHECK((*p)->IsTheHole() || (*p)->IsUndefined() ||
|
||||
(*p)->IsInternalizedString());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static void VerifySymbolTable() {
|
||||
SymbolTableVerifier verifier;
|
||||
HEAP->symbol_table()->IterateElements(&verifier);
|
||||
static void VerifyStringTable() {
|
||||
StringTableVerifier verifier;
|
||||
HEAP->string_table()->IterateElements(&verifier);
|
||||
}
|
||||
#endif // VERIFY_HEAP
|
||||
|
||||
@ -876,7 +877,7 @@ bool Heap::PerformGarbageCollection(GarbageCollector collector,
|
||||
|
||||
#ifdef VERIFY_HEAP
|
||||
if (FLAG_verify_heap) {
|
||||
VerifySymbolTable();
|
||||
VerifyStringTable();
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1001,7 +1002,7 @@ bool Heap::PerformGarbageCollection(GarbageCollector collector,
|
||||
|
||||
#ifdef VERIFY_HEAP
|
||||
if (FLAG_verify_heap) {
|
||||
VerifySymbolTable();
|
||||
VerifyStringTable();
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1618,10 +1619,11 @@ void Heap::ProcessWeakReferences(WeakObjectRetainer* retainer) {
|
||||
void Heap::VisitExternalResources(v8::ExternalResourceVisitor* visitor) {
|
||||
AssertNoAllocation no_allocation;
|
||||
|
||||
// Both the external string table and the symbol table may contain
|
||||
// Both the external string table and the string table may contain
|
||||
// external strings, but neither lists them exhaustively, nor is the
|
||||
// intersection set empty. Therefore we iterate over the external string
|
||||
// table first, ignoring symbols, and then over the symbol table.
|
||||
// table first, ignoring internalized strings, and then over the
|
||||
// internalized string table.
|
||||
|
||||
class ExternalStringTableVisitorAdapter : public ObjectVisitor {
|
||||
public:
|
||||
@ -1629,9 +1631,9 @@ void Heap::VisitExternalResources(v8::ExternalResourceVisitor* visitor) {
|
||||
v8::ExternalResourceVisitor* visitor) : visitor_(visitor) {}
|
||||
virtual void VisitPointers(Object** start, Object** end) {
|
||||
for (Object** p = start; p < end; p++) {
|
||||
// Visit non-symbol external strings,
|
||||
// since symbols are listed in the symbol table.
|
||||
if (!(*p)->IsSymbol()) {
|
||||
// Visit non-internalized external strings,
|
||||
// since internalized strings are listed in the string table.
|
||||
if (!(*p)->IsInternalizedString()) {
|
||||
ASSERT((*p)->IsExternalString());
|
||||
visitor_->VisitExternalString(Utils::ToLocal(
|
||||
Handle<String>(String::cast(*p))));
|
||||
@ -1644,14 +1646,14 @@ void Heap::VisitExternalResources(v8::ExternalResourceVisitor* visitor) {
|
||||
|
||||
external_string_table_.Iterate(&external_string_table_visitor);
|
||||
|
||||
class SymbolTableVisitorAdapter : public ObjectVisitor {
|
||||
class StringTableVisitorAdapter : public ObjectVisitor {
|
||||
public:
|
||||
explicit SymbolTableVisitorAdapter(
|
||||
explicit StringTableVisitorAdapter(
|
||||
v8::ExternalResourceVisitor* visitor) : visitor_(visitor) {}
|
||||
virtual void VisitPointers(Object** start, Object** end) {
|
||||
for (Object** p = start; p < end; p++) {
|
||||
if ((*p)->IsExternalString()) {
|
||||
ASSERT((*p)->IsSymbol());
|
||||
ASSERT((*p)->IsInternalizedString());
|
||||
visitor_->VisitExternalString(Utils::ToLocal(
|
||||
Handle<String>(String::cast(*p))));
|
||||
}
|
||||
@ -1659,9 +1661,9 @@ void Heap::VisitExternalResources(v8::ExternalResourceVisitor* visitor) {
|
||||
}
|
||||
private:
|
||||
v8::ExternalResourceVisitor* visitor_;
|
||||
} symbol_table_visitor(visitor);
|
||||
} string_table_visitor(visitor);
|
||||
|
||||
symbol_table()->IterateElements(&symbol_table_visitor);
|
||||
string_table()->IterateElements(&string_table_visitor);
|
||||
}
|
||||
|
||||
|
||||
@ -2271,11 +2273,11 @@ const Heap::StringTypeTable Heap::string_type_table[] = {
|
||||
};
|
||||
|
||||
|
||||
const Heap::ConstantSymbolTable Heap::constant_symbol_table[] = {
|
||||
#define CONSTANT_SYMBOL_ELEMENT(name, contents) \
|
||||
const Heap::ConstantStringTable Heap::constant_string_table[] = {
|
||||
#define CONSTANT_STRING_ELEMENT(name, contents) \
|
||||
{contents, k##name##RootIndex},
|
||||
SYMBOL_LIST(CONSTANT_SYMBOL_ELEMENT)
|
||||
#undef CONSTANT_SYMBOL_ELEMENT
|
||||
INTERNALIZED_STRING_LIST(CONSTANT_STRING_ELEMENT)
|
||||
#undef CONSTANT_STRING_ELEMENT
|
||||
};
|
||||
|
||||
|
||||
@ -2738,17 +2740,17 @@ bool Heap::CreateInitialObjects() {
|
||||
set_infinity_value(HeapNumber::cast(obj));
|
||||
|
||||
// The hole has not been created yet, but we want to put something
|
||||
// predictable in the gaps in the symbol table, so lets make that Smi zero.
|
||||
// predictable in the gaps in the string table, so lets make that Smi zero.
|
||||
set_the_hole_value(reinterpret_cast<Oddball*>(Smi::FromInt(0)));
|
||||
|
||||
// Allocate initial symbol table.
|
||||
{ MaybeObject* maybe_obj = SymbolTable::Allocate(kInitialSymbolTableSize);
|
||||
// Allocate initial string table.
|
||||
{ MaybeObject* maybe_obj = StringTable::Allocate(kInitialStringTableSize);
|
||||
if (!maybe_obj->ToObject(&obj)) return false;
|
||||
}
|
||||
// Don't use set_symbol_table() due to asserts.
|
||||
roots_[kSymbolTableRootIndex] = obj;
|
||||
// Don't use set_string_table() due to asserts.
|
||||
roots_[kStringTableRootIndex] = obj;
|
||||
|
||||
// Finish initializing oddballs after creating symboltable.
|
||||
// Finish initializing oddballs after creating the string table.
|
||||
{ MaybeObject* maybe_obj =
|
||||
undefined_value()->Initialize("undefined",
|
||||
nan_value(),
|
||||
@ -2804,31 +2806,25 @@ bool Heap::CreateInitialObjects() {
|
||||
}
|
||||
set_termination_exception(obj);
|
||||
|
||||
// Allocate the empty string.
|
||||
{ MaybeObject* maybe_obj = AllocateRawOneByteString(0, TENURED);
|
||||
if (!maybe_obj->ToObject(&obj)) return false;
|
||||
}
|
||||
set_empty_string(String::cast(obj));
|
||||
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(constant_symbol_table); i++) {
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(constant_string_table); i++) {
|
||||
{ MaybeObject* maybe_obj =
|
||||
LookupUtf8Symbol(constant_symbol_table[i].contents);
|
||||
InternalizeUtf8String(constant_string_table[i].contents);
|
||||
if (!maybe_obj->ToObject(&obj)) return false;
|
||||
}
|
||||
roots_[constant_symbol_table[i].index] = String::cast(obj);
|
||||
roots_[constant_string_table[i].index] = String::cast(obj);
|
||||
}
|
||||
|
||||
// Allocate the hidden symbol which is used to identify the hidden properties
|
||||
// Allocate the hidden string which is used to identify the hidden properties
|
||||
// in JSObjects. The hash code has a special value so that it will not match
|
||||
// the empty string when searching for the property. It cannot be part of the
|
||||
// loop above because it needs to be allocated manually with the special
|
||||
// hash code in place. The hash code for the hidden_symbol is zero to ensure
|
||||
// hash code in place. The hash code for the hidden_string is zero to ensure
|
||||
// that it will always be at the first entry in property descriptors.
|
||||
{ MaybeObject* maybe_obj =
|
||||
AllocateOneByteSymbol(OneByteVector("", 0), String::kEmptyStringHash);
|
||||
{ MaybeObject* maybe_obj = AllocateOneByteInternalizedString(
|
||||
OneByteVector("", 0), String::kEmptyStringHash);
|
||||
if (!maybe_obj->ToObject(&obj)) return false;
|
||||
}
|
||||
hidden_symbol_ = String::cast(obj);
|
||||
hidden_string_ = String::cast(obj);
|
||||
|
||||
// Allocate the foreign for __proto__.
|
||||
{ MaybeObject* maybe_obj =
|
||||
@ -2950,7 +2946,7 @@ bool Heap::RootCanBeWrittenAfterInitialization(Heap::RootListIndex root_index) {
|
||||
kConstructStubDeoptPCOffsetRootIndex,
|
||||
kGetterStubDeoptPCOffsetRootIndex,
|
||||
kSetterStubDeoptPCOffsetRootIndex,
|
||||
kSymbolTableRootIndex,
|
||||
kStringTableRootIndex,
|
||||
};
|
||||
|
||||
for (unsigned int i = 0; i < ARRAY_SIZE(writable_roots); i++) {
|
||||
@ -2966,10 +2962,10 @@ Object* RegExpResultsCache::Lookup(Heap* heap,
|
||||
Object* key_pattern,
|
||||
ResultsCacheType type) {
|
||||
FixedArray* cache;
|
||||
if (!key_string->IsSymbol()) return Smi::FromInt(0);
|
||||
if (!key_string->IsInternalizedString()) return Smi::FromInt(0);
|
||||
if (type == STRING_SPLIT_SUBSTRINGS) {
|
||||
ASSERT(key_pattern->IsString());
|
||||
if (!key_pattern->IsSymbol()) return Smi::FromInt(0);
|
||||
if (!key_pattern->IsInternalizedString()) return Smi::FromInt(0);
|
||||
cache = heap->string_split_cache();
|
||||
} else {
|
||||
ASSERT(type == REGEXP_MULTIPLE_INDICES);
|
||||
@ -3000,10 +2996,10 @@ void RegExpResultsCache::Enter(Heap* heap,
|
||||
FixedArray* value_array,
|
||||
ResultsCacheType type) {
|
||||
FixedArray* cache;
|
||||
if (!key_string->IsSymbol()) return;
|
||||
if (!key_string->IsInternalizedString()) return;
|
||||
if (type == STRING_SPLIT_SUBSTRINGS) {
|
||||
ASSERT(key_pattern->IsString());
|
||||
if (!key_pattern->IsSymbol()) return;
|
||||
if (!key_pattern->IsInternalizedString()) return;
|
||||
cache = heap->string_split_cache();
|
||||
} else {
|
||||
ASSERT(type == REGEXP_MULTIPLE_INDICES);
|
||||
@ -3035,14 +3031,14 @@ void RegExpResultsCache::Enter(Heap* heap,
|
||||
}
|
||||
}
|
||||
// If the array is a reasonably short list of substrings, convert it into a
|
||||
// list of symbols.
|
||||
// list of internalized strings.
|
||||
if (type == STRING_SPLIT_SUBSTRINGS && value_array->length() < 100) {
|
||||
for (int i = 0; i < value_array->length(); i++) {
|
||||
String* str = String::cast(value_array->get(i));
|
||||
Object* symbol;
|
||||
MaybeObject* maybe_symbol = heap->LookupSymbol(str);
|
||||
if (maybe_symbol->ToObject(&symbol)) {
|
||||
value_array->set(i, symbol);
|
||||
Object* internalized_str;
|
||||
MaybeObject* maybe_string = heap->InternalizeString(str);
|
||||
if (maybe_string->ToObject(&internalized_str)) {
|
||||
value_array->set(i, internalized_str);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3275,7 +3271,7 @@ MaybeObject* Heap::AllocateSharedFunctionInfo(Object* name) {
|
||||
Code* construct_stub =
|
||||
isolate_->builtins()->builtin(Builtins::kJSConstructStubGeneric);
|
||||
share->set_construct_stub(construct_stub);
|
||||
share->set_instance_class_name(Object_symbol());
|
||||
share->set_instance_class_name(Object_string());
|
||||
share->set_function_data(undefined_value(), SKIP_WRITE_BARRIER);
|
||||
share->set_script(undefined_value(), SKIP_WRITE_BARRIER);
|
||||
share->set_debug_info(undefined_value(), SKIP_WRITE_BARRIER);
|
||||
@ -3341,12 +3337,12 @@ MUST_USE_RESULT static inline MaybeObject* MakeOrFindTwoCharacterString(
|
||||
Heap* heap,
|
||||
uint16_t c1,
|
||||
uint16_t c2) {
|
||||
String* symbol;
|
||||
String* result;
|
||||
// Numeric strings have a different hash algorithm not known by
|
||||
// LookupTwoCharsSymbolIfExists, so we skip this step for such strings.
|
||||
// LookupTwoCharsStringIfExists, so we skip this step for such strings.
|
||||
if ((!Between(c1, '0', '9') || !Between(c2, '0', '9')) &&
|
||||
heap->symbol_table()->LookupTwoCharsSymbolIfExists(c1, c2, &symbol)) {
|
||||
return symbol;
|
||||
heap->string_table()->LookupTwoCharsStringIfExists(c1, c2, &result)) {
|
||||
return result;
|
||||
// Now we know the length is 2, we might as well make use of that fact
|
||||
// when building the new string.
|
||||
} else if (static_cast<unsigned>(c1 | c2) <= String::kMaxOneByteCharCodeU) {
|
||||
@ -3387,7 +3383,7 @@ MaybeObject* Heap::AllocateConsString(String* first, String* second) {
|
||||
int length = first_length + second_length;
|
||||
|
||||
// Optimization for 2-byte strings often used as keys in a decompression
|
||||
// dictionary. Check whether we already have the string in the symbol
|
||||
// dictionary. Check whether we already have the string in the string
|
||||
// table to prevent creation of many unneccesary strings.
|
||||
if (length == 2) {
|
||||
uint16_t c1 = first->Get(0);
|
||||
@ -3502,8 +3498,8 @@ MaybeObject* Heap::AllocateSubString(String* buffer,
|
||||
return LookupSingleCharacterStringFromCode(buffer->Get(start));
|
||||
} else if (length == 2) {
|
||||
// Optimization for 2-byte strings often used as keys in a decompression
|
||||
// dictionary. Check whether we already have the string in the symbol
|
||||
// table to prevent creation of many unneccesary strings.
|
||||
// dictionary. Check whether we already have the string in the string
|
||||
// table to prevent creation of many unnecessary strings.
|
||||
uint16_t c1 = buffer->Get(start);
|
||||
uint16_t c2 = buffer->Get(start + 1);
|
||||
return MakeOrFindTwoCharacterString(this, c1, c2);
|
||||
@ -3650,7 +3646,7 @@ MaybeObject* Heap::LookupSingleCharacterStringFromCode(uint16_t code) {
|
||||
buffer[0] = static_cast<uint8_t>(code);
|
||||
Object* result;
|
||||
MaybeObject* maybe_result =
|
||||
LookupOneByteSymbol(Vector<const uint8_t>(buffer, 1));
|
||||
InternalizeOneByteString(Vector<const uint8_t>(buffer, 1));
|
||||
|
||||
if (!maybe_result->ToObject(&result)) return maybe_result;
|
||||
single_character_string_cache()->set(code, result);
|
||||
@ -3959,7 +3955,7 @@ MaybeObject* Heap::AllocateFunctionPrototype(JSFunction* function) {
|
||||
// constructor to the function.
|
||||
MaybeObject* maybe_failure =
|
||||
JSObject::cast(prototype)->SetLocalPropertyIgnoreAttributes(
|
||||
constructor_symbol(), function, DONT_ENUM);
|
||||
constructor_string(), function, DONT_ENUM);
|
||||
if (maybe_failure->IsFailure()) return maybe_failure;
|
||||
|
||||
return prototype;
|
||||
@ -4098,7 +4094,7 @@ MaybeObject* Heap::AllocateInitialMap(JSFunction* fun) {
|
||||
DescriptorArray::WhitenessWitness witness(descriptors);
|
||||
for (int i = 0; i < count; i++) {
|
||||
String* name = fun->shared()->GetThisPropertyAssignmentName(i);
|
||||
ASSERT(name->IsSymbol());
|
||||
ASSERT(name->IsInternalizedString());
|
||||
FieldDescriptor field(name, i, NONE, i + 1);
|
||||
descriptors->Set(i, &field, witness);
|
||||
}
|
||||
@ -4528,7 +4524,8 @@ MaybeObject* Heap::ReinitializeJSReceiver(
|
||||
SharedFunctionInfo* shared = NULL;
|
||||
if (type == JS_FUNCTION_TYPE) {
|
||||
String* name;
|
||||
maybe = LookupOneByteSymbol(STATIC_ASCII_VECTOR("<freezing call trap>"));
|
||||
maybe =
|
||||
InternalizeOneByteString(STATIC_ASCII_VECTOR("<freezing call trap>"));
|
||||
if (!maybe->To<String>(&name)) return maybe;
|
||||
maybe = AllocateSharedFunctionInfo(name);
|
||||
if (!maybe->To<SharedFunctionInfo>(&shared)) return maybe;
|
||||
@ -4662,25 +4659,27 @@ MaybeObject* Heap::AllocateStringFromTwoByte(Vector<const uc16> string,
|
||||
}
|
||||
|
||||
|
||||
Map* Heap::SymbolMapForString(String* string) {
|
||||
// If the string is in new space it cannot be used as a symbol.
|
||||
Map* Heap::InternalizedStringMapForString(String* string) {
|
||||
// If the string is in new space it cannot be used as internalized.
|
||||
if (InNewSpace(string)) return NULL;
|
||||
|
||||
// Find the corresponding symbol map for strings.
|
||||
// Find the corresponding internalized string map for strings.
|
||||
switch (string->map()->instance_type()) {
|
||||
case STRING_TYPE: return symbol_map();
|
||||
case ASCII_STRING_TYPE: return ascii_symbol_map();
|
||||
case CONS_STRING_TYPE: return cons_symbol_map();
|
||||
case CONS_ASCII_STRING_TYPE: return cons_ascii_symbol_map();
|
||||
case EXTERNAL_STRING_TYPE: return external_symbol_map();
|
||||
case EXTERNAL_ASCII_STRING_TYPE: return external_ascii_symbol_map();
|
||||
case STRING_TYPE: return internalized_string_map();
|
||||
case ASCII_STRING_TYPE: return ascii_internalized_string_map();
|
||||
case CONS_STRING_TYPE: return cons_internalized_string_map();
|
||||
case CONS_ASCII_STRING_TYPE: return cons_ascii_internalized_string_map();
|
||||
case EXTERNAL_STRING_TYPE: return external_internalized_string_map();
|
||||
case EXTERNAL_ASCII_STRING_TYPE:
|
||||
return external_ascii_internalized_string_map();
|
||||
case EXTERNAL_STRING_WITH_ASCII_DATA_TYPE:
|
||||
return external_symbol_with_ascii_data_map();
|
||||
case SHORT_EXTERNAL_STRING_TYPE: return short_external_symbol_map();
|
||||
return external_internalized_string_with_ascii_data_map();
|
||||
case SHORT_EXTERNAL_STRING_TYPE:
|
||||
return short_external_internalized_string_map();
|
||||
case SHORT_EXTERNAL_ASCII_STRING_TYPE:
|
||||
return short_external_ascii_symbol_map();
|
||||
return short_external_ascii_internalized_string_map();
|
||||
case SHORT_EXTERNAL_STRING_WITH_ASCII_DATA_TYPE:
|
||||
return short_external_symbol_with_ascii_data_map();
|
||||
return short_external_internalized_string_with_ascii_data_map();
|
||||
default: return NULL; // No match found.
|
||||
}
|
||||
}
|
||||
@ -4734,9 +4733,8 @@ static inline void WriteTwoByteData(String* s, uint16_t* chars, int len) {
|
||||
|
||||
|
||||
template<bool is_one_byte, typename T>
|
||||
MaybeObject* Heap::AllocateInternalSymbol(T t,
|
||||
int chars,
|
||||
uint32_t hash_field) {
|
||||
MaybeObject* Heap::AllocateInternalizedStringImpl(
|
||||
T t, int chars, uint32_t hash_field) {
|
||||
ASSERT(chars >= 0);
|
||||
// Compute map and object size.
|
||||
int size;
|
||||
@ -4746,13 +4744,13 @@ MaybeObject* Heap::AllocateInternalSymbol(T t,
|
||||
if (chars > SeqOneByteString::kMaxLength) {
|
||||
return Failure::OutOfMemoryException(0x9);
|
||||
}
|
||||
map = ascii_symbol_map();
|
||||
map = ascii_internalized_string_map();
|
||||
size = SeqOneByteString::SizeFor(chars);
|
||||
} else {
|
||||
if (chars > SeqTwoByteString::kMaxLength) {
|
||||
return Failure::OutOfMemoryException(0xa);
|
||||
}
|
||||
map = symbol_map();
|
||||
map = internalized_string_map();
|
||||
size = SeqTwoByteString::SizeFor(chars);
|
||||
}
|
||||
|
||||
@ -4783,13 +4781,13 @@ MaybeObject* Heap::AllocateInternalSymbol(T t,
|
||||
|
||||
// Need explicit instantiations.
|
||||
template
|
||||
MaybeObject* Heap::AllocateInternalSymbol<true>(String*, int, uint32_t);
|
||||
MaybeObject* Heap::AllocateInternalizedStringImpl<true>(String*, int, uint32_t);
|
||||
template
|
||||
MaybeObject* Heap::AllocateInternalSymbol<false>(String*, int, uint32_t);
|
||||
MaybeObject* Heap::AllocateInternalizedStringImpl<false>(
|
||||
String*, int, uint32_t);
|
||||
template
|
||||
MaybeObject* Heap::AllocateInternalSymbol<false>(Vector<const char>,
|
||||
int,
|
||||
uint32_t);
|
||||
MaybeObject* Heap::AllocateInternalizedStringImpl<false>(
|
||||
Vector<const char>, int, uint32_t);
|
||||
|
||||
|
||||
MaybeObject* Heap::AllocateRawOneByteString(int length,
|
||||
@ -5661,93 +5659,93 @@ void Heap::Verify() {
|
||||
#endif
|
||||
|
||||
|
||||
MaybeObject* Heap::LookupUtf8Symbol(Vector<const char> string) {
|
||||
Object* symbol = NULL;
|
||||
MaybeObject* Heap::InternalizeUtf8String(Vector<const char> string) {
|
||||
Object* result = NULL;
|
||||
Object* new_table;
|
||||
{ MaybeObject* maybe_new_table =
|
||||
symbol_table()->LookupUtf8Symbol(string, &symbol);
|
||||
string_table()->LookupUtf8String(string, &result);
|
||||
if (!maybe_new_table->ToObject(&new_table)) return maybe_new_table;
|
||||
}
|
||||
// Can't use set_symbol_table because SymbolTable::cast knows that
|
||||
// SymbolTable is a singleton and checks for identity.
|
||||
roots_[kSymbolTableRootIndex] = new_table;
|
||||
ASSERT(symbol != NULL);
|
||||
return symbol;
|
||||
// Can't use set_string_table because StringTable::cast knows that
|
||||
// StringTable is a singleton and checks for identity.
|
||||
roots_[kStringTableRootIndex] = new_table;
|
||||
ASSERT(result != NULL);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* Heap::LookupOneByteSymbol(Vector<const uint8_t> string) {
|
||||
Object* symbol = NULL;
|
||||
MaybeObject* Heap::InternalizeOneByteString(Vector<const uint8_t> string) {
|
||||
Object* result = NULL;
|
||||
Object* new_table;
|
||||
{ MaybeObject* maybe_new_table =
|
||||
symbol_table()->LookupOneByteSymbol(string, &symbol);
|
||||
string_table()->LookupOneByteString(string, &result);
|
||||
if (!maybe_new_table->ToObject(&new_table)) return maybe_new_table;
|
||||
}
|
||||
// Can't use set_symbol_table because SymbolTable::cast knows that
|
||||
// SymbolTable is a singleton and checks for identity.
|
||||
roots_[kSymbolTableRootIndex] = new_table;
|
||||
ASSERT(symbol != NULL);
|
||||
return symbol;
|
||||
// Can't use set_string_table because StringTable::cast knows that
|
||||
// StringTable is a singleton and checks for identity.
|
||||
roots_[kStringTableRootIndex] = new_table;
|
||||
ASSERT(result != NULL);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* Heap::LookupOneByteSymbol(Handle<SeqOneByteString> string,
|
||||
MaybeObject* Heap::InternalizeOneByteString(Handle<SeqOneByteString> string,
|
||||
int from,
|
||||
int length) {
|
||||
Object* symbol = NULL;
|
||||
Object* result = NULL;
|
||||
Object* new_table;
|
||||
{ MaybeObject* maybe_new_table =
|
||||
symbol_table()->LookupSubStringOneByteSymbol(string,
|
||||
string_table()->LookupSubStringOneByteString(string,
|
||||
from,
|
||||
length,
|
||||
&symbol);
|
||||
&result);
|
||||
if (!maybe_new_table->ToObject(&new_table)) return maybe_new_table;
|
||||
}
|
||||
// Can't use set_symbol_table because SymbolTable::cast knows that
|
||||
// SymbolTable is a singleton and checks for identity.
|
||||
roots_[kSymbolTableRootIndex] = new_table;
|
||||
ASSERT(symbol != NULL);
|
||||
return symbol;
|
||||
// Can't use set_string_table because StringTable::cast knows that
|
||||
// StringTable is a singleton and checks for identity.
|
||||
roots_[kStringTableRootIndex] = new_table;
|
||||
ASSERT(result != NULL);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* Heap::LookupTwoByteSymbol(Vector<const uc16> string) {
|
||||
Object* symbol = NULL;
|
||||
MaybeObject* Heap::InternalizeTwoByteString(Vector<const uc16> string) {
|
||||
Object* result = NULL;
|
||||
Object* new_table;
|
||||
{ MaybeObject* maybe_new_table =
|
||||
symbol_table()->LookupTwoByteSymbol(string, &symbol);
|
||||
string_table()->LookupTwoByteString(string, &result);
|
||||
if (!maybe_new_table->ToObject(&new_table)) return maybe_new_table;
|
||||
}
|
||||
// Can't use set_symbol_table because SymbolTable::cast knows that
|
||||
// SymbolTable is a singleton and checks for identity.
|
||||
roots_[kSymbolTableRootIndex] = new_table;
|
||||
ASSERT(symbol != NULL);
|
||||
return symbol;
|
||||
// Can't use set_string_table because StringTable::cast knows that
|
||||
// StringTable is a singleton and checks for identity.
|
||||
roots_[kStringTableRootIndex] = new_table;
|
||||
ASSERT(result != NULL);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* Heap::LookupSymbol(String* string) {
|
||||
if (string->IsSymbol()) return string;
|
||||
Object* symbol = NULL;
|
||||
MaybeObject* Heap::InternalizeString(String* string) {
|
||||
if (string->IsInternalizedString()) return string;
|
||||
Object* result = NULL;
|
||||
Object* new_table;
|
||||
{ MaybeObject* maybe_new_table =
|
||||
symbol_table()->LookupString(string, &symbol);
|
||||
string_table()->LookupString(string, &result);
|
||||
if (!maybe_new_table->ToObject(&new_table)) return maybe_new_table;
|
||||
}
|
||||
// Can't use set_symbol_table because SymbolTable::cast knows that
|
||||
// SymbolTable is a singleton and checks for identity.
|
||||
roots_[kSymbolTableRootIndex] = new_table;
|
||||
ASSERT(symbol != NULL);
|
||||
return symbol;
|
||||
// Can't use set_string_table because StringTable::cast knows that
|
||||
// StringTable is a singleton and checks for identity.
|
||||
roots_[kStringTableRootIndex] = new_table;
|
||||
ASSERT(result != NULL);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool Heap::LookupSymbolIfExists(String* string, String** symbol) {
|
||||
if (string->IsSymbol()) {
|
||||
*symbol = string;
|
||||
bool Heap::InternalizeStringIfExists(String* string, String** result) {
|
||||
if (string->IsInternalizedString()) {
|
||||
*result = string;
|
||||
return true;
|
||||
}
|
||||
return symbol_table()->LookupSymbolIfExists(string, symbol);
|
||||
return string_table()->LookupStringIfExists(string, result);
|
||||
}
|
||||
|
||||
|
||||
@ -5975,8 +5973,8 @@ void Heap::IterateRoots(ObjectVisitor* v, VisitMode mode) {
|
||||
|
||||
|
||||
void Heap::IterateWeakRoots(ObjectVisitor* v, VisitMode mode) {
|
||||
v->VisitPointer(reinterpret_cast<Object**>(&roots_[kSymbolTableRootIndex]));
|
||||
v->Synchronize(VisitorSynchronization::kSymbolTable);
|
||||
v->VisitPointer(reinterpret_cast<Object**>(&roots_[kStringTableRootIndex]));
|
||||
v->Synchronize(VisitorSynchronization::kStringTable);
|
||||
if (mode != VISIT_ALL_IN_SCAVENGE &&
|
||||
mode != VISIT_ALL_IN_SWEEP_NEWSPACE) {
|
||||
// Scavenge collections have special processing for this.
|
||||
@ -5991,8 +5989,8 @@ void Heap::IterateStrongRoots(ObjectVisitor* v, VisitMode mode) {
|
||||
v->VisitPointers(&roots_[0], &roots_[kStrongRootListLength]);
|
||||
v->Synchronize(VisitorSynchronization::kStrongRootList);
|
||||
|
||||
v->VisitPointer(BitCast<Object**>(&hidden_symbol_));
|
||||
v->Synchronize(VisitorSynchronization::kSymbol);
|
||||
v->VisitPointer(BitCast<Object**>(&hidden_string_));
|
||||
v->Synchronize(VisitorSynchronization::kInternalizedString);
|
||||
|
||||
isolate_->bootstrapper()->Iterate(v);
|
||||
v->Synchronize(VisitorSynchronization::kBootstrapper);
|
||||
@ -7169,9 +7167,9 @@ int KeyedLookupCache::Lookup(Map* map, String* name) {
|
||||
|
||||
|
||||
void KeyedLookupCache::Update(Map* map, String* name, int field_offset) {
|
||||
String* symbol;
|
||||
if (HEAP->LookupSymbolIfExists(name, &symbol)) {
|
||||
int index = (Hash(map, symbol) & kHashMask);
|
||||
String* internalized_name;
|
||||
if (HEAP->InternalizeStringIfExists(name, &internalized_name)) {
|
||||
int index = (Hash(map, internalized_name) & kHashMask);
|
||||
// After a GC there will be free slots, so we use them in order (this may
|
||||
// help to get the most frequently used one in position 0).
|
||||
for (int i = 0; i< kEntriesPerBucket; i++) {
|
||||
@ -7179,7 +7177,7 @@ void KeyedLookupCache::Update(Map* map, String* name, int field_offset) {
|
||||
Object* free_entry_indicator = NULL;
|
||||
if (key.map == free_entry_indicator) {
|
||||
key.map = map;
|
||||
key.name = symbol;
|
||||
key.name = internalized_name;
|
||||
field_offsets_[index + i] = field_offset;
|
||||
return;
|
||||
}
|
||||
@ -7196,7 +7194,7 @@ void KeyedLookupCache::Update(Map* map, String* name, int field_offset) {
|
||||
// Write the new first entry.
|
||||
Key& key = keys_[index];
|
||||
key.map = map;
|
||||
key.name = symbol;
|
||||
key.name = internalized_name;
|
||||
field_offsets_[index] = field_offset;
|
||||
}
|
||||
}
|
||||
@ -7329,7 +7327,7 @@ void ErrorObjectList::DeferredFormatStackTrace(Isolate* isolate) {
|
||||
if (nested_ || list_.is_empty() || isolate->has_pending_exception()) return;
|
||||
nested_ = true;
|
||||
HandleScope scope(isolate);
|
||||
Handle<String> stack_key = isolate->factory()->stack_symbol();
|
||||
Handle<String> stack_key = isolate->factory()->stack_string();
|
||||
int write_index = 0;
|
||||
int budget = kBudgetPerGC;
|
||||
for (int i = 0; i < list_.length(); i++) {
|
||||
@ -7353,7 +7351,7 @@ void ErrorObjectList::DeferredFormatStackTrace(Isolate* isolate) {
|
||||
Object* getter_obj = AccessorPair::cast(callback)->getter();
|
||||
if (!getter_obj->IsJSFunction()) continue;
|
||||
getter_fun = JSFunction::cast(getter_obj);
|
||||
String* key = isolate->heap()->hidden_stack_trace_symbol();
|
||||
String* key = isolate->heap()->hidden_stack_trace_string();
|
||||
if (key != getter_fun->GetHiddenProperty(key)) continue;
|
||||
}
|
||||
|
||||
|
308
src/heap.h
308
src/heap.h
@ -61,8 +61,6 @@ namespace internal {
|
||||
V(Map, global_property_cell_map, GlobalPropertyCellMap) \
|
||||
V(Map, shared_function_info_map, SharedFunctionInfoMap) \
|
||||
V(Map, meta_map, MetaMap) \
|
||||
V(Map, ascii_symbol_map, AsciiSymbolMap) \
|
||||
V(Map, ascii_string_map, AsciiStringMap) \
|
||||
V(Map, heap_number_map, HeapNumberMap) \
|
||||
V(Map, native_context_map, NativeContextMap) \
|
||||
V(Map, fixed_array_map, FixedArrayMap) \
|
||||
@ -74,7 +72,6 @@ namespace internal {
|
||||
V(Map, hash_table_map, HashTableMap) \
|
||||
V(FixedArray, empty_fixed_array, EmptyFixedArray) \
|
||||
V(ByteArray, empty_byte_array, EmptyByteArray) \
|
||||
V(String, empty_string, EmptyString) \
|
||||
V(DescriptorArray, empty_descriptor_array, EmptyDescriptorArray) \
|
||||
V(Smi, stack_limit, StackLimit) \
|
||||
V(Oddball, arguments_marker, ArgumentsMarker) \
|
||||
@ -91,28 +88,40 @@ namespace internal {
|
||||
V(Object, termination_exception, TerminationException) \
|
||||
V(Smi, hash_seed, HashSeed) \
|
||||
V(Map, string_map, StringMap) \
|
||||
V(Map, symbol_map, SymbolMap) \
|
||||
V(Map, ascii_string_map, AsciiStringMap) \
|
||||
V(Map, cons_string_map, ConsStringMap) \
|
||||
V(Map, cons_ascii_string_map, ConsAsciiStringMap) \
|
||||
V(Map, sliced_string_map, SlicedStringMap) \
|
||||
V(Map, sliced_ascii_string_map, SlicedAsciiStringMap) \
|
||||
V(Map, cons_symbol_map, ConsSymbolMap) \
|
||||
V(Map, cons_ascii_symbol_map, ConsAsciiSymbolMap) \
|
||||
V(Map, external_symbol_map, ExternalSymbolMap) \
|
||||
V(Map, external_symbol_with_ascii_data_map, ExternalSymbolWithAsciiDataMap) \
|
||||
V(Map, external_ascii_symbol_map, ExternalAsciiSymbolMap) \
|
||||
V(Map, external_string_map, ExternalStringMap) \
|
||||
V(Map, external_string_with_ascii_data_map, ExternalStringWithAsciiDataMap) \
|
||||
V(Map, external_ascii_string_map, ExternalAsciiStringMap) \
|
||||
V(Map, short_external_symbol_map, ShortExternalSymbolMap) \
|
||||
V(Map, \
|
||||
short_external_symbol_with_ascii_data_map, \
|
||||
ShortExternalSymbolWithAsciiDataMap) \
|
||||
V(Map, short_external_ascii_symbol_map, ShortExternalAsciiSymbolMap) \
|
||||
V(Map, short_external_string_map, ShortExternalStringMap) \
|
||||
V(Map, \
|
||||
short_external_string_with_ascii_data_map, \
|
||||
ShortExternalStringWithAsciiDataMap) \
|
||||
V(Map, internalized_string_map, InternalizedStringMap) \
|
||||
V(Map, ascii_internalized_string_map, AsciiInternalizedStringMap) \
|
||||
V(Map, cons_internalized_string_map, ConsInternalizedStringMap) \
|
||||
V(Map, cons_ascii_internalized_string_map, ConsAsciiInternalizedStringMap) \
|
||||
V(Map, \
|
||||
external_internalized_string_map, \
|
||||
ExternalInternalizedStringMap) \
|
||||
V(Map, \
|
||||
external_internalized_string_with_ascii_data_map, \
|
||||
ExternalInternalizedStringWithAsciiDataMap) \
|
||||
V(Map, \
|
||||
external_ascii_internalized_string_map, \
|
||||
ExternalAsciiInternalizedStringMap) \
|
||||
V(Map, \
|
||||
short_external_internalized_string_map, \
|
||||
ShortExternalInternalizedStringMap) \
|
||||
V(Map, \
|
||||
short_external_internalized_string_with_ascii_data_map, \
|
||||
ShortExternalInternalizedStringWithAsciiDataMap) \
|
||||
V(Map, \
|
||||
short_external_ascii_internalized_string_map, \
|
||||
ShortExternalAsciiInternalizedStringMap) \
|
||||
V(Map, short_external_ascii_string_map, ShortExternalAsciiStringMap) \
|
||||
V(Map, undetectable_string_map, UndetectableStringMap) \
|
||||
V(Map, undetectable_ascii_string_map, UndetectableAsciiStringMap) \
|
||||
@ -160,103 +169,103 @@ namespace internal {
|
||||
|
||||
#define ROOT_LIST(V) \
|
||||
STRONG_ROOT_LIST(V) \
|
||||
V(SymbolTable, symbol_table, SymbolTable)
|
||||
V(StringTable, string_table, StringTable)
|
||||
|
||||
#define SYMBOL_LIST(V) \
|
||||
V(Array_symbol, "Array") \
|
||||
V(Object_symbol, "Object") \
|
||||
V(Proto_symbol, "__proto__") \
|
||||
V(StringImpl_symbol, "StringImpl") \
|
||||
V(arguments_symbol, "arguments") \
|
||||
V(Arguments_symbol, "Arguments") \
|
||||
V(call_symbol, "call") \
|
||||
V(apply_symbol, "apply") \
|
||||
V(caller_symbol, "caller") \
|
||||
V(boolean_symbol, "boolean") \
|
||||
V(Boolean_symbol, "Boolean") \
|
||||
V(callee_symbol, "callee") \
|
||||
V(constructor_symbol, "constructor") \
|
||||
V(code_symbol, ".code") \
|
||||
V(result_symbol, ".result") \
|
||||
V(dot_for_symbol, ".for.") \
|
||||
V(catch_var_symbol, ".catch-var") \
|
||||
V(empty_symbol, "") \
|
||||
V(eval_symbol, "eval") \
|
||||
V(function_symbol, "function") \
|
||||
V(length_symbol, "length") \
|
||||
V(module_symbol, "module") \
|
||||
V(name_symbol, "name") \
|
||||
V(native_symbol, "native") \
|
||||
V(null_symbol, "null") \
|
||||
V(number_symbol, "number") \
|
||||
V(Number_symbol, "Number") \
|
||||
V(nan_symbol, "NaN") \
|
||||
V(RegExp_symbol, "RegExp") \
|
||||
V(source_symbol, "source") \
|
||||
V(global_symbol, "global") \
|
||||
V(ignore_case_symbol, "ignoreCase") \
|
||||
V(multiline_symbol, "multiline") \
|
||||
V(input_symbol, "input") \
|
||||
V(index_symbol, "index") \
|
||||
V(last_index_symbol, "lastIndex") \
|
||||
V(object_symbol, "object") \
|
||||
V(prototype_symbol, "prototype") \
|
||||
V(string_symbol, "string") \
|
||||
V(String_symbol, "String") \
|
||||
V(Date_symbol, "Date") \
|
||||
V(this_symbol, "this") \
|
||||
V(to_string_symbol, "toString") \
|
||||
V(char_at_symbol, "CharAt") \
|
||||
V(undefined_symbol, "undefined") \
|
||||
V(value_of_symbol, "valueOf") \
|
||||
V(stack_symbol, "stack") \
|
||||
V(InitializeVarGlobal_symbol, "InitializeVarGlobal") \
|
||||
V(InitializeConstGlobal_symbol, "InitializeConstGlobal") \
|
||||
V(KeyedLoadElementMonomorphic_symbol, \
|
||||
#define INTERNALIZED_STRING_LIST(V) \
|
||||
V(Array_string, "Array") \
|
||||
V(Object_string, "Object") \
|
||||
V(proto_string, "__proto__") \
|
||||
V(StringImpl_string, "StringImpl") \
|
||||
V(arguments_string, "arguments") \
|
||||
V(Arguments_string, "Arguments") \
|
||||
V(call_string, "call") \
|
||||
V(apply_string, "apply") \
|
||||
V(caller_string, "caller") \
|
||||
V(boolean_string, "boolean") \
|
||||
V(Boolean_string, "Boolean") \
|
||||
V(callee_string, "callee") \
|
||||
V(constructor_string, "constructor") \
|
||||
V(code_string, ".code") \
|
||||
V(result_string, ".result") \
|
||||
V(dot_for_string, ".for.") \
|
||||
V(catch_var_string, ".catch-var") \
|
||||
V(empty_string, "") \
|
||||
V(eval_string, "eval") \
|
||||
V(function_string, "function") \
|
||||
V(length_string, "length") \
|
||||
V(module_string, "module") \
|
||||
V(name_string, "name") \
|
||||
V(native_string, "native") \
|
||||
V(null_string, "null") \
|
||||
V(number_string, "number") \
|
||||
V(Number_string, "Number") \
|
||||
V(nan_string, "NaN") \
|
||||
V(RegExp_string, "RegExp") \
|
||||
V(source_string, "source") \
|
||||
V(global_string, "global") \
|
||||
V(ignore_case_string, "ignoreCase") \
|
||||
V(multiline_string, "multiline") \
|
||||
V(input_string, "input") \
|
||||
V(index_string, "index") \
|
||||
V(last_index_string, "lastIndex") \
|
||||
V(object_string, "object") \
|
||||
V(prototype_string, "prototype") \
|
||||
V(string_string, "string") \
|
||||
V(String_string, "String") \
|
||||
V(Date_string, "Date") \
|
||||
V(this_string, "this") \
|
||||
V(to_string_string, "toString") \
|
||||
V(char_at_string, "CharAt") \
|
||||
V(undefined_string, "undefined") \
|
||||
V(value_of_string, "valueOf") \
|
||||
V(stack_string, "stack") \
|
||||
V(InitializeVarGlobal_string, "InitializeVarGlobal") \
|
||||
V(InitializeConstGlobal_string, "InitializeConstGlobal") \
|
||||
V(KeyedLoadElementMonomorphic_string, \
|
||||
"KeyedLoadElementMonomorphic") \
|
||||
V(KeyedStoreElementMonomorphic_symbol, \
|
||||
V(KeyedStoreElementMonomorphic_string, \
|
||||
"KeyedStoreElementMonomorphic") \
|
||||
V(KeyedStoreAndGrowElementMonomorphic_symbol, \
|
||||
V(KeyedStoreAndGrowElementMonomorphic_string, \
|
||||
"KeyedStoreAndGrowElementMonomorphic") \
|
||||
V(stack_overflow_symbol, "kStackOverflowBoilerplate") \
|
||||
V(illegal_access_symbol, "illegal access") \
|
||||
V(out_of_memory_symbol, "out-of-memory") \
|
||||
V(illegal_execution_state_symbol, "illegal execution state") \
|
||||
V(get_symbol, "get") \
|
||||
V(set_symbol, "set") \
|
||||
V(map_field_symbol, "%map") \
|
||||
V(elements_field_symbol, "%elements") \
|
||||
V(length_field_symbol, "%length") \
|
||||
V(function_class_symbol, "Function") \
|
||||
V(illegal_argument_symbol, "illegal argument") \
|
||||
V(MakeReferenceError_symbol, "MakeReferenceError") \
|
||||
V(MakeSyntaxError_symbol, "MakeSyntaxError") \
|
||||
V(MakeTypeError_symbol, "MakeTypeError") \
|
||||
V(invalid_lhs_in_assignment_symbol, "invalid_lhs_in_assignment") \
|
||||
V(invalid_lhs_in_for_in_symbol, "invalid_lhs_in_for_in") \
|
||||
V(invalid_lhs_in_postfix_op_symbol, "invalid_lhs_in_postfix_op") \
|
||||
V(invalid_lhs_in_prefix_op_symbol, "invalid_lhs_in_prefix_op") \
|
||||
V(illegal_return_symbol, "illegal_return") \
|
||||
V(illegal_break_symbol, "illegal_break") \
|
||||
V(illegal_continue_symbol, "illegal_continue") \
|
||||
V(unknown_label_symbol, "unknown_label") \
|
||||
V(redeclaration_symbol, "redeclaration") \
|
||||
V(failure_symbol, "<failure>") \
|
||||
V(space_symbol, " ") \
|
||||
V(exec_symbol, "exec") \
|
||||
V(zero_symbol, "0") \
|
||||
V(global_eval_symbol, "GlobalEval") \
|
||||
V(identity_hash_symbol, "v8::IdentityHash") \
|
||||
V(closure_symbol, "(closure)") \
|
||||
V(use_strict, "use strict") \
|
||||
V(dot_symbol, ".") \
|
||||
V(anonymous_function_symbol, "(anonymous function)") \
|
||||
V(compare_ic_symbol, "==") \
|
||||
V(strict_compare_ic_symbol, "===") \
|
||||
V(infinity_symbol, "Infinity") \
|
||||
V(minus_infinity_symbol, "-Infinity") \
|
||||
V(hidden_stack_trace_symbol, "v8::hidden_stack_trace") \
|
||||
V(query_colon_symbol, "(?:)")
|
||||
V(stack_overflow_string, "kStackOverflowBoilerplate") \
|
||||
V(illegal_access_string, "illegal access") \
|
||||
V(out_of_memory_string, "out-of-memory") \
|
||||
V(illegal_execution_state_string, "illegal execution state") \
|
||||
V(get_string, "get") \
|
||||
V(set_string, "set") \
|
||||
V(map_field_string, "%map") \
|
||||
V(elements_field_string, "%elements") \
|
||||
V(length_field_string, "%length") \
|
||||
V(function_class_string, "Function") \
|
||||
V(illegal_argument_string, "illegal argument") \
|
||||
V(MakeReferenceError_string, "MakeReferenceError") \
|
||||
V(MakeSyntaxError_string, "MakeSyntaxError") \
|
||||
V(MakeTypeError_string, "MakeTypeError") \
|
||||
V(invalid_lhs_in_assignment_string, "invalid_lhs_in_assignment") \
|
||||
V(invalid_lhs_in_for_in_string, "invalid_lhs_in_for_in") \
|
||||
V(invalid_lhs_in_postfix_op_string, "invalid_lhs_in_postfix_op") \
|
||||
V(invalid_lhs_in_prefix_op_string, "invalid_lhs_in_prefix_op") \
|
||||
V(illegal_return_string, "illegal_return") \
|
||||
V(illegal_break_string, "illegal_break") \
|
||||
V(illegal_continue_string, "illegal_continue") \
|
||||
V(unknown_label_string, "unknown_label") \
|
||||
V(redeclaration_string, "redeclaration") \
|
||||
V(failure_string, "<failure>") \
|
||||
V(space_string, " ") \
|
||||
V(exec_string, "exec") \
|
||||
V(zero_string, "0") \
|
||||
V(global_eval_string, "GlobalEval") \
|
||||
V(identity_hash_string, "v8::IdentityHash") \
|
||||
V(closure_string, "(closure)") \
|
||||
V(use_strict_string, "use strict") \
|
||||
V(dot_string, ".") \
|
||||
V(anonymous_function_string, "(anonymous function)") \
|
||||
V(compare_ic_string, "==") \
|
||||
V(strict_compare_ic_string, "===") \
|
||||
V(infinity_string, "Infinity") \
|
||||
V(minus_infinity_string, "-Infinity") \
|
||||
V(hidden_stack_trace_string, "v8::hidden_stack_trace") \
|
||||
V(query_colon_string, "(?:)") \
|
||||
|
||||
// Forward declarations.
|
||||
class GCTracer;
|
||||
@ -763,20 +772,20 @@ class Heap {
|
||||
Vector<const uc16> str,
|
||||
PretenureFlag pretenure = NOT_TENURED);
|
||||
|
||||
// Allocates a symbol in old space based on the character stream.
|
||||
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
|
||||
// failed.
|
||||
// Allocates an internalized string in old space based on the character
|
||||
// stream. Returns Failure::RetryAfterGC(requested_bytes, space) if the
|
||||
// allocation failed.
|
||||
// Please note this function does not perform a garbage collection.
|
||||
MUST_USE_RESULT inline MaybeObject* AllocateSymbolFromUtf8(
|
||||
MUST_USE_RESULT inline MaybeObject* AllocateInternalizedStringFromUtf8(
|
||||
Vector<const char> str,
|
||||
int chars,
|
||||
uint32_t hash_field);
|
||||
|
||||
MUST_USE_RESULT inline MaybeObject* AllocateOneByteSymbol(
|
||||
MUST_USE_RESULT inline MaybeObject* AllocateOneByteInternalizedString(
|
||||
Vector<const uint8_t> str,
|
||||
uint32_t hash_field);
|
||||
|
||||
MUST_USE_RESULT inline MaybeObject* AllocateTwoByteSymbol(
|
||||
MUST_USE_RESULT inline MaybeObject* AllocateTwoByteInternalizedString(
|
||||
Vector<const uc16> str,
|
||||
uint32_t hash_field);
|
||||
|
||||
@ -784,11 +793,11 @@ class Heap {
|
||||
static inline bool IsOneByte(T t, int chars);
|
||||
|
||||
template<typename T>
|
||||
MUST_USE_RESULT inline MaybeObject* AllocateInternalSymbol(
|
||||
MUST_USE_RESULT inline MaybeObject* AllocateInternalizedStringImpl(
|
||||
T t, int chars, uint32_t hash_field);
|
||||
|
||||
template<bool is_one_byte, typename T>
|
||||
MUST_USE_RESULT MaybeObject* AllocateInternalSymbol(
|
||||
MUST_USE_RESULT MaybeObject* AllocateInternalizedStringImpl(
|
||||
T t, int chars, uint32_t hash_field);
|
||||
|
||||
// Allocates and partially initializes a String. There are two String
|
||||
@ -1085,27 +1094,28 @@ class Heap {
|
||||
// the provided data as the relocation information.
|
||||
MUST_USE_RESULT MaybeObject* CopyCode(Code* code, Vector<byte> reloc_info);
|
||||
|
||||
// Finds the symbol for string in the symbol table.
|
||||
// If not found, a new symbol is added to the table and returned.
|
||||
// Finds the internalized copy for string in the string table.
|
||||
// If not found, a new string is added to the table and returned.
|
||||
// Returns Failure::RetryAfterGC(requested_bytes, space) if allocation
|
||||
// failed.
|
||||
// Please note this function does not perform a garbage collection.
|
||||
MUST_USE_RESULT MaybeObject* LookupUtf8Symbol(Vector<const char> str);
|
||||
MUST_USE_RESULT MaybeObject* LookupUtf8Symbol(const char* str) {
|
||||
return LookupUtf8Symbol(CStrVector(str));
|
||||
MUST_USE_RESULT MaybeObject* InternalizeUtf8String(Vector<const char> str);
|
||||
MUST_USE_RESULT MaybeObject* InternalizeUtf8String(const char* str) {
|
||||
return InternalizeUtf8String(CStrVector(str));
|
||||
}
|
||||
MUST_USE_RESULT MaybeObject* LookupOneByteSymbol(Vector<const uint8_t> str);
|
||||
MUST_USE_RESULT MaybeObject* LookupTwoByteSymbol(Vector<const uc16> str);
|
||||
MUST_USE_RESULT MaybeObject* LookupSymbol(String* str);
|
||||
MUST_USE_RESULT MaybeObject* LookupOneByteSymbol(
|
||||
MUST_USE_RESULT MaybeObject* InternalizeOneByteString(
|
||||
Vector<const uint8_t> str);
|
||||
MUST_USE_RESULT MaybeObject* InternalizeTwoByteString(Vector<const uc16> str);
|
||||
MUST_USE_RESULT MaybeObject* InternalizeString(String* str);
|
||||
MUST_USE_RESULT MaybeObject* InternalizeOneByteString(
|
||||
Handle<SeqOneByteString> string, int from, int length);
|
||||
|
||||
bool LookupSymbolIfExists(String* str, String** symbol);
|
||||
bool LookupTwoCharsSymbolIfExists(String* str, String** symbol);
|
||||
bool InternalizeStringIfExists(String* str, String** result);
|
||||
bool InternalizeTwoCharsStringIfExists(String* str, String** result);
|
||||
|
||||
// Compute the matching symbol map for a string if possible.
|
||||
// Compute the matching internalized string map for a string if possible.
|
||||
// NULL is returned if string is in new space or not flattened.
|
||||
Map* SymbolMapForString(String* str);
|
||||
Map* InternalizedStringMapForString(String* str);
|
||||
|
||||
// Tries to flatten a string before compare operation.
|
||||
//
|
||||
@ -1233,15 +1243,15 @@ class Heap {
|
||||
STRUCT_LIST(STRUCT_MAP_ACCESSOR)
|
||||
#undef STRUCT_MAP_ACCESSOR
|
||||
|
||||
#define SYMBOL_ACCESSOR(name, str) String* name() { \
|
||||
#define STRING_ACCESSOR(name, str) String* name() { \
|
||||
return String::cast(roots_[k##name##RootIndex]); \
|
||||
}
|
||||
SYMBOL_LIST(SYMBOL_ACCESSOR)
|
||||
#undef SYMBOL_ACCESSOR
|
||||
INTERNALIZED_STRING_LIST(STRING_ACCESSOR)
|
||||
#undef STRING_ACCESSOR
|
||||
|
||||
// The hidden_symbol is special because it is the empty string, but does
|
||||
// The hidden_string is special because it is the empty string, but does
|
||||
// not match the empty string.
|
||||
String* hidden_symbol() { return hidden_symbol_; }
|
||||
String* hidden_string() { return hidden_string_; }
|
||||
|
||||
void set_native_contexts_list(Object* object) {
|
||||
native_contexts_list_ = object;
|
||||
@ -1367,13 +1377,13 @@ class Heap {
|
||||
// Print short heap statistics.
|
||||
void PrintShortHeapStatistics();
|
||||
|
||||
// Makes a new symbol object
|
||||
// Makes a new internalized string object
|
||||
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
|
||||
// failed.
|
||||
// Please note this function does not perform a garbage collection.
|
||||
MUST_USE_RESULT MaybeObject* CreateSymbol(
|
||||
MUST_USE_RESULT MaybeObject* CreateInternalizedString(
|
||||
const char* str, int length, int hash);
|
||||
MUST_USE_RESULT MaybeObject* CreateSymbol(String* str);
|
||||
MUST_USE_RESULT MaybeObject* CreateInternalizedString(String* str);
|
||||
|
||||
// Write barrier support for address[offset] = o.
|
||||
INLINE(void RecordWrite(Address address, int offset));
|
||||
@ -1490,17 +1500,17 @@ class Heap {
|
||||
STRONG_ROOT_LIST(ROOT_INDEX_DECLARATION)
|
||||
#undef ROOT_INDEX_DECLARATION
|
||||
|
||||
#define SYMBOL_INDEX_DECLARATION(name, str) k##name##RootIndex,
|
||||
SYMBOL_LIST(SYMBOL_INDEX_DECLARATION)
|
||||
#undef SYMBOL_DECLARATION
|
||||
#define STRING_INDEX_DECLARATION(name, str) k##name##RootIndex,
|
||||
INTERNALIZED_STRING_LIST(STRING_INDEX_DECLARATION)
|
||||
#undef STRING_DECLARATION
|
||||
|
||||
// Utility type maps
|
||||
#define DECLARE_STRUCT_MAP(NAME, Name, name) k##Name##MapRootIndex,
|
||||
STRUCT_LIST(DECLARE_STRUCT_MAP)
|
||||
#undef DECLARE_STRUCT_MAP
|
||||
|
||||
kSymbolTableRootIndex,
|
||||
kStrongRootListLength = kSymbolTableRootIndex,
|
||||
kStringTableRootIndex,
|
||||
kStrongRootListLength = kStringTableRootIndex,
|
||||
kRootListLength
|
||||
};
|
||||
|
||||
@ -1508,7 +1518,7 @@ class Heap {
|
||||
STATIC_CHECK(kNullValueRootIndex == Internals::kNullValueRootIndex);
|
||||
STATIC_CHECK(kTrueValueRootIndex == Internals::kTrueValueRootIndex);
|
||||
STATIC_CHECK(kFalseValueRootIndex == Internals::kFalseValueRootIndex);
|
||||
STATIC_CHECK(kempty_symbolRootIndex == Internals::kEmptySymbolRootIndex);
|
||||
STATIC_CHECK(kempty_stringRootIndex == Internals::kEmptyStringRootIndex);
|
||||
|
||||
// Generated code can embed direct references to non-writable roots if
|
||||
// they are in new space.
|
||||
@ -1914,7 +1924,7 @@ class Heap {
|
||||
RootListIndex index;
|
||||
};
|
||||
|
||||
struct ConstantSymbolTable {
|
||||
struct ConstantStringTable {
|
||||
const char* contents;
|
||||
RootListIndex index;
|
||||
};
|
||||
@ -1926,12 +1936,12 @@ class Heap {
|
||||
};
|
||||
|
||||
static const StringTypeTable string_type_table[];
|
||||
static const ConstantSymbolTable constant_symbol_table[];
|
||||
static const ConstantStringTable constant_string_table[];
|
||||
static const StructTable struct_table[];
|
||||
|
||||
// The special hidden symbol which is an empty string, but does not match
|
||||
// The special hidden string which is an empty string, but does not match
|
||||
// any string when looked up in properties.
|
||||
String* hidden_symbol_;
|
||||
String* hidden_string_;
|
||||
|
||||
// GC callback function, called before and after mark-compact GC.
|
||||
// Allocations in the callback function are disallowed.
|
||||
@ -2173,7 +2183,7 @@ class Heap {
|
||||
|
||||
void ClearObjectStats(bool clear_last_time_stats = false);
|
||||
|
||||
static const int kInitialSymbolTableSize = 2048;
|
||||
static const int kInitialStringTableSize = 2048;
|
||||
static const int kInitialEvalCacheSize = 64;
|
||||
static const int kInitialNumberStringCacheSize = 256;
|
||||
|
||||
@ -2509,7 +2519,7 @@ class DescriptorLookupCache {
|
||||
// Lookup descriptor index for (map, name).
|
||||
// If absent, kAbsent is returned.
|
||||
int Lookup(Map* source, String* name) {
|
||||
if (!StringShape(name).IsSymbol()) return kAbsent;
|
||||
if (!StringShape(name).IsInternalized()) return kAbsent;
|
||||
int index = Hash(source, name);
|
||||
Key& key = keys_[index];
|
||||
if ((key.source == source) && (key.name == name)) return results_[index];
|
||||
@ -2519,7 +2529,7 @@ class DescriptorLookupCache {
|
||||
// Update an element in the cache.
|
||||
void Update(Map* source, String* name, int result) {
|
||||
ASSERT(result != kAbsent);
|
||||
if (StringShape(name).IsSymbol()) {
|
||||
if (StringShape(name).IsInternalized()) {
|
||||
int index = Hash(source, name);
|
||||
Key& key = keys_[index];
|
||||
key.source = source;
|
||||
|
@ -1303,10 +1303,11 @@ HValue* HCheckInstanceType::Canonicalize() {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (check_ == IS_SYMBOL && value()->IsConstant()) {
|
||||
// Dereferencing is safe here: a symbol cannot become a non-symbol.
|
||||
if (check_ == IS_INTERNALIZED_STRING && value()->IsConstant()) {
|
||||
// Dereferencing is safe here:
|
||||
// an internalized string cannot become non-internalized.
|
||||
AllowHandleDereference allow_handle_deref(isolate());
|
||||
if (HConstant::cast(value())->handle()->IsSymbol()) return NULL;
|
||||
if (HConstant::cast(value())->handle()->IsInternalizedString()) return NULL;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@ -1336,9 +1337,9 @@ void HCheckInstanceType::GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag) {
|
||||
*mask = kIsNotStringMask;
|
||||
*tag = kStringTag;
|
||||
return;
|
||||
case IS_SYMBOL:
|
||||
*mask = kIsSymbolMask;
|
||||
*tag = kSymbolTag;
|
||||
case IS_INTERNALIZED_STRING:
|
||||
*mask = kIsInternalizedMask;
|
||||
*tag = kInternalizedTag;
|
||||
return;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
@ -1396,7 +1397,7 @@ const char* HCheckInstanceType::GetCheckName() {
|
||||
case IS_SPEC_OBJECT: return "object";
|
||||
case IS_JS_ARRAY: return "array";
|
||||
case IS_STRING: return "string";
|
||||
case IS_SYMBOL: return "symbol";
|
||||
case IS_INTERNALIZED_STRING: return "internalized_string";
|
||||
}
|
||||
UNREACHABLE();
|
||||
return "";
|
||||
|
@ -2652,8 +2652,9 @@ class HCheckInstanceType: public HUnaryOperation {
|
||||
static HCheckInstanceType* NewIsString(HValue* value, Zone* zone) {
|
||||
return new(zone) HCheckInstanceType(value, IS_STRING);
|
||||
}
|
||||
static HCheckInstanceType* NewIsSymbol(HValue* value, Zone* zone) {
|
||||
return new(zone) HCheckInstanceType(value, IS_SYMBOL);
|
||||
static HCheckInstanceType* NewIsInternalizedString(
|
||||
HValue* value, Zone* zone) {
|
||||
return new(zone) HCheckInstanceType(value, IS_INTERNALIZED_STRING);
|
||||
}
|
||||
|
||||
virtual void PrintDataTo(StringStream* stream);
|
||||
@ -2684,7 +2685,7 @@ class HCheckInstanceType: public HUnaryOperation {
|
||||
IS_SPEC_OBJECT,
|
||||
IS_JS_ARRAY,
|
||||
IS_STRING,
|
||||
IS_SYMBOL,
|
||||
IS_INTERNALIZED_STRING,
|
||||
LAST_INTERVAL_CHECK = IS_JS_ARRAY
|
||||
};
|
||||
|
||||
|
@ -1075,7 +1075,7 @@ HValue* HGraphBuilder::BuildAllocateElements(HContext* context,
|
||||
BuildStoreMap(elements, map, BailoutId::StubEntry());
|
||||
|
||||
Handle<String> fixed_array_length_field_name =
|
||||
isolate->factory()->length_field_symbol();
|
||||
isolate->factory()->length_field_string();
|
||||
HInstruction* store_length =
|
||||
new(zone) HStoreNamedField(elements, fixed_array_length_field_name,
|
||||
capacity, true, FixedArray::kLengthOffset);
|
||||
@ -1092,7 +1092,7 @@ HInstruction* HGraphBuilder::BuildStoreMap(HValue* object,
|
||||
Zone* zone = this->zone();
|
||||
Isolate* isolate = graph()->isolate();
|
||||
Factory* factory = isolate->factory();
|
||||
Handle<String> map_field_name = factory->map_field_symbol();
|
||||
Handle<String> map_field_name = factory->map_field_string();
|
||||
HInstruction* store_map =
|
||||
new(zone) HStoreNamedField(object, map_field_name, map,
|
||||
true, JSObject::kMapOffset);
|
||||
@ -5752,7 +5752,7 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
ASSERT(!CompileTimeValue::IsCompileTimeValue(value));
|
||||
// Fall through.
|
||||
case ObjectLiteral::Property::COMPUTED:
|
||||
if (key->handle()->IsSymbol()) {
|
||||
if (key->handle()->IsInternalizedString()) {
|
||||
if (property->emit_store()) {
|
||||
property->RecordTypeFeedback(oracle());
|
||||
CHECK_ALIVE(VisitForValue(value));
|
||||
@ -9437,11 +9437,12 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
|
||||
default:
|
||||
return Bailout("Unsupported non-primitive compare");
|
||||
}
|
||||
} else if (overall_type_info.IsSymbol() && Token::IsEqualityOp(op)) {
|
||||
} else if (overall_type_info.IsInternalizedString() &&
|
||||
Token::IsEqualityOp(op)) {
|
||||
AddInstruction(new(zone()) HCheckNonSmi(left));
|
||||
AddInstruction(HCheckInstanceType::NewIsSymbol(left, zone()));
|
||||
AddInstruction(HCheckInstanceType::NewIsInternalizedString(left, zone()));
|
||||
AddInstruction(new(zone()) HCheckNonSmi(right));
|
||||
AddInstruction(HCheckInstanceType::NewIsSymbol(right, zone()));
|
||||
AddInstruction(HCheckInstanceType::NewIsInternalizedString(right, zone()));
|
||||
HCompareObjectEqAndBranch* result =
|
||||
new(zone()) HCompareObjectEqAndBranch(left, right);
|
||||
result->set_position(expr->position());
|
||||
@ -9871,7 +9872,7 @@ void HOptimizedGraphBuilder::GenerateSetValueOf(CallRuntime* call) {
|
||||
|
||||
// Create in-object property store to kValueOffset.
|
||||
set_current_block(if_js_value);
|
||||
Handle<String> name = isolate()->factory()->undefined_symbol();
|
||||
Handle<String> name = isolate()->factory()->undefined_string();
|
||||
AddInstruction(new(zone()) HStoreNamedField(object,
|
||||
name,
|
||||
value,
|
||||
|
@ -3255,7 +3255,7 @@ void ArrayLengthStub::Generate(MacroAssembler* masm) {
|
||||
Label miss;
|
||||
|
||||
if (kind() == Code::KEYED_LOAD_IC) {
|
||||
__ cmp(ecx, Immediate(masm->isolate()->factory()->length_symbol()));
|
||||
__ cmp(ecx, Immediate(masm->isolate()->factory()->length_string()));
|
||||
__ j(not_equal, &miss);
|
||||
}
|
||||
|
||||
@ -3274,7 +3274,7 @@ void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
|
||||
Label miss;
|
||||
|
||||
if (kind() == Code::KEYED_LOAD_IC) {
|
||||
__ cmp(ecx, Immediate(masm->isolate()->factory()->prototype_symbol()));
|
||||
__ cmp(ecx, Immediate(masm->isolate()->factory()->prototype_string()));
|
||||
__ j(not_equal, &miss);
|
||||
}
|
||||
|
||||
@ -3293,7 +3293,7 @@ void StringLengthStub::Generate(MacroAssembler* masm) {
|
||||
Label miss;
|
||||
|
||||
if (kind() == Code::KEYED_LOAD_IC) {
|
||||
__ cmp(ecx, Immediate(masm->isolate()->factory()->length_symbol()));
|
||||
__ cmp(ecx, Immediate(masm->isolate()->factory()->length_string()));
|
||||
__ j(not_equal, &miss);
|
||||
}
|
||||
|
||||
@ -3324,7 +3324,7 @@ void StoreArrayLengthStub::Generate(MacroAssembler* masm) {
|
||||
Register scratch = ebx;
|
||||
|
||||
if (kind() == Code::KEYED_LOAD_IC) {
|
||||
__ cmp(ecx, Immediate(masm->isolate()->factory()->length_symbol()));
|
||||
__ cmp(ecx, Immediate(masm->isolate()->factory()->length_string()));
|
||||
__ j(not_equal, &miss);
|
||||
}
|
||||
|
||||
@ -4435,21 +4435,21 @@ static void CheckInputType(MacroAssembler* masm,
|
||||
Immediate(masm->isolate()->factory()->heap_number_map()));
|
||||
__ j(not_equal, fail);
|
||||
}
|
||||
// We could be strict about symbol/string here, but as long as
|
||||
// We could be strict about internalized/non-internalized here, but as long as
|
||||
// hydrogen doesn't care, the stub doesn't have to care either.
|
||||
__ bind(&ok);
|
||||
}
|
||||
|
||||
|
||||
static void BranchIfNonSymbol(MacroAssembler* masm,
|
||||
Label* label,
|
||||
Register object,
|
||||
Register scratch) {
|
||||
static void BranchIfNotInternalizedString(MacroAssembler* masm,
|
||||
Label* label,
|
||||
Register object,
|
||||
Register scratch) {
|
||||
__ JumpIfSmi(object, label);
|
||||
__ mov(scratch, FieldOperand(object, HeapObject::kMapOffset));
|
||||
__ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
|
||||
__ and_(scratch, kIsSymbolMask | kIsNotStringMask);
|
||||
__ cmp(scratch, kSymbolTag | kStringTag);
|
||||
__ and_(scratch, kIsInternalizedMask | kIsNotStringMask);
|
||||
__ cmp(scratch, kInternalizedTag | kStringTag);
|
||||
__ j(not_equal, label);
|
||||
}
|
||||
|
||||
@ -4677,14 +4677,14 @@ void ICCompareStub::GenerateGeneric(MacroAssembler* masm) {
|
||||
// The number comparison code did not provide a valid result.
|
||||
__ bind(&non_number_comparison);
|
||||
|
||||
// Fast negative check for symbol-to-symbol equality.
|
||||
// Fast negative check for internalized-to-internalized equality.
|
||||
Label check_for_strings;
|
||||
if (cc == equal) {
|
||||
BranchIfNonSymbol(masm, &check_for_strings, eax, ecx);
|
||||
BranchIfNonSymbol(masm, &check_for_strings, edx, ecx);
|
||||
BranchIfNotInternalizedString(masm, &check_for_strings, eax, ecx);
|
||||
BranchIfNotInternalizedString(masm, &check_for_strings, edx, ecx);
|
||||
|
||||
// We've already checked for object identity, so if both operands
|
||||
// are symbols they aren't equal. Register eax already holds a
|
||||
// are internalized they aren't equal. Register eax already holds a
|
||||
// non-zero value, which indicates not equal, so just return.
|
||||
__ ret(0);
|
||||
}
|
||||
@ -5748,8 +5748,8 @@ void StringAddStub::Generate(MacroAssembler* masm) {
|
||||
STATIC_ASSERT(Smi::kMaxValue == String::kMaxLength);
|
||||
// Handle exceptionally long strings in the runtime system.
|
||||
__ j(overflow, &call_runtime);
|
||||
// Use the symbol table when adding two one character strings, as it
|
||||
// helps later optimizations to return a symbol here.
|
||||
// Use the string table when adding two one character strings, as it
|
||||
// helps later optimizations to return an internalized string here.
|
||||
__ cmp(ebx, Immediate(Smi::FromInt(2)));
|
||||
__ j(not_equal, &longer_than_two);
|
||||
|
||||
@ -5760,10 +5760,10 @@ void StringAddStub::Generate(MacroAssembler* masm) {
|
||||
__ movzx_b(ebx, FieldOperand(eax, SeqOneByteString::kHeaderSize));
|
||||
__ movzx_b(ecx, FieldOperand(edx, SeqOneByteString::kHeaderSize));
|
||||
|
||||
// Try to lookup two character string in symbol table. If it is not found
|
||||
// Try to lookup two character string in string table. If it is not found
|
||||
// just allocate a new one.
|
||||
Label make_two_character_string, make_two_character_string_no_reload;
|
||||
StringHelper::GenerateTwoCharacterSymbolTableProbe(
|
||||
StringHelper::GenerateTwoCharacterStringTableProbe(
|
||||
masm, ebx, ecx, eax, edx, edi,
|
||||
&make_two_character_string_no_reload, &make_two_character_string);
|
||||
__ IncrementCounter(counters->string_add_native(), 1);
|
||||
@ -6109,7 +6109,7 @@ void StringHelper::GenerateCopyCharactersREP(MacroAssembler* masm,
|
||||
}
|
||||
|
||||
|
||||
void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
|
||||
void StringHelper::GenerateTwoCharacterStringTableProbe(MacroAssembler* masm,
|
||||
Register c1,
|
||||
Register c2,
|
||||
Register scratch1,
|
||||
@ -6121,7 +6121,7 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
|
||||
Register scratch = scratch3;
|
||||
|
||||
// Make sure that both characters are not digits as such strings has a
|
||||
// different hash algorithm. Don't try to look for these in the symbol table.
|
||||
// different hash algorithm. Don't try to look for these in the string table.
|
||||
Label not_array_index;
|
||||
__ mov(scratch, c1);
|
||||
__ sub(scratch, Immediate(static_cast<int>('0')));
|
||||
@ -6147,47 +6147,47 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
|
||||
// chars: two character string, char 1 in byte 0 and char 2 in byte 1.
|
||||
// hash: hash of two character string.
|
||||
|
||||
// Load the symbol table.
|
||||
Register symbol_table = c2;
|
||||
// Load the string table.
|
||||
Register string_table = c2;
|
||||
ExternalReference roots_array_start =
|
||||
ExternalReference::roots_array_start(masm->isolate());
|
||||
__ mov(scratch, Immediate(Heap::kSymbolTableRootIndex));
|
||||
__ mov(symbol_table,
|
||||
__ mov(scratch, Immediate(Heap::kStringTableRootIndex));
|
||||
__ mov(string_table,
|
||||
Operand::StaticArray(scratch, times_pointer_size, roots_array_start));
|
||||
|
||||
// Calculate capacity mask from the symbol table capacity.
|
||||
// Calculate capacity mask from the string table capacity.
|
||||
Register mask = scratch2;
|
||||
__ mov(mask, FieldOperand(symbol_table, SymbolTable::kCapacityOffset));
|
||||
__ mov(mask, FieldOperand(string_table, StringTable::kCapacityOffset));
|
||||
__ SmiUntag(mask);
|
||||
__ sub(mask, Immediate(1));
|
||||
|
||||
// Registers
|
||||
// chars: two character string, char 1 in byte 0 and char 2 in byte 1.
|
||||
// hash: hash of two character string
|
||||
// symbol_table: symbol table
|
||||
// string_table: string table
|
||||
// mask: capacity mask
|
||||
// scratch: -
|
||||
|
||||
// Perform a number of probes in the symbol table.
|
||||
// Perform a number of probes in the string table.
|
||||
static const int kProbes = 4;
|
||||
Label found_in_symbol_table;
|
||||
Label found_in_string_table;
|
||||
Label next_probe[kProbes], next_probe_pop_mask[kProbes];
|
||||
Register candidate = scratch; // Scratch register contains candidate.
|
||||
for (int i = 0; i < kProbes; i++) {
|
||||
// Calculate entry in symbol table.
|
||||
// Calculate entry in string table.
|
||||
__ mov(scratch, hash);
|
||||
if (i > 0) {
|
||||
__ add(scratch, Immediate(SymbolTable::GetProbeOffset(i)));
|
||||
__ add(scratch, Immediate(StringTable::GetProbeOffset(i)));
|
||||
}
|
||||
__ and_(scratch, mask);
|
||||
|
||||
// Load the entry from the symbol table.
|
||||
STATIC_ASSERT(SymbolTable::kEntrySize == 1);
|
||||
// Load the entry from the string table.
|
||||
STATIC_ASSERT(StringTable::kEntrySize == 1);
|
||||
__ mov(candidate,
|
||||
FieldOperand(symbol_table,
|
||||
FieldOperand(string_table,
|
||||
scratch,
|
||||
times_pointer_size,
|
||||
SymbolTable::kElementsStartOffset));
|
||||
StringTable::kElementsStartOffset));
|
||||
|
||||
// If entry is undefined no string with this hash can be found.
|
||||
Factory* factory = masm->isolate()->factory();
|
||||
@ -6216,7 +6216,7 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
|
||||
__ mov(temp, FieldOperand(candidate, SeqOneByteString::kHeaderSize));
|
||||
__ and_(temp, 0x0000ffff);
|
||||
__ cmp(chars, temp);
|
||||
__ j(equal, &found_in_symbol_table);
|
||||
__ j(equal, &found_in_string_table);
|
||||
__ bind(&next_probe_pop_mask[i]);
|
||||
__ pop(mask);
|
||||
__ bind(&next_probe[i]);
|
||||
@ -6227,7 +6227,7 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
|
||||
|
||||
// Scratch register contains result when we fall through to here.
|
||||
Register result = candidate;
|
||||
__ bind(&found_in_symbol_table);
|
||||
__ bind(&found_in_string_table);
|
||||
__ pop(mask); // Pop saved mask from the stack.
|
||||
if (!result.is(eax)) {
|
||||
__ mov(eax, result);
|
||||
@ -6840,8 +6840,8 @@ void ICCompareStub::GenerateNumbers(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void ICCompareStub::GenerateSymbols(MacroAssembler* masm) {
|
||||
ASSERT(state_ == CompareIC::SYMBOL);
|
||||
void ICCompareStub::GenerateInternalizedStrings(MacroAssembler* masm) {
|
||||
ASSERT(state_ == CompareIC::INTERNALIZED_STRING);
|
||||
ASSERT(GetCondition() == equal);
|
||||
|
||||
// Registers containing left and right operands respectively.
|
||||
@ -6857,17 +6857,17 @@ void ICCompareStub::GenerateSymbols(MacroAssembler* masm) {
|
||||
__ and_(tmp1, right);
|
||||
__ JumpIfSmi(tmp1, &miss, Label::kNear);
|
||||
|
||||
// Check that both operands are symbols.
|
||||
// Check that both operands are internalized strings.
|
||||
__ mov(tmp1, FieldOperand(left, HeapObject::kMapOffset));
|
||||
__ mov(tmp2, FieldOperand(right, HeapObject::kMapOffset));
|
||||
__ movzx_b(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset));
|
||||
__ movzx_b(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset));
|
||||
STATIC_ASSERT(kSymbolTag != 0);
|
||||
STATIC_ASSERT(kInternalizedTag != 0);
|
||||
__ and_(tmp1, tmp2);
|
||||
__ test(tmp1, Immediate(kIsSymbolMask));
|
||||
__ test(tmp1, Immediate(kIsInternalizedMask));
|
||||
__ j(zero, &miss, Label::kNear);
|
||||
|
||||
// Symbols are compared by identity.
|
||||
// Internalized strings are compared by identity.
|
||||
Label done;
|
||||
__ cmp(left, right);
|
||||
// Make sure eax is non-zero. At this point input operands are
|
||||
@ -6928,14 +6928,14 @@ void ICCompareStub::GenerateStrings(MacroAssembler* masm) {
|
||||
// Handle not identical strings.
|
||||
__ bind(¬_same);
|
||||
|
||||
// Check that both strings are symbols. If they are, we're done
|
||||
// Check that both strings are internalized. If they are, we're done
|
||||
// because we already know they are not identical. But in the case of
|
||||
// non-equality compare, we still need to determine the order.
|
||||
if (equality) {
|
||||
Label do_compare;
|
||||
STATIC_ASSERT(kSymbolTag != 0);
|
||||
STATIC_ASSERT(kInternalizedTag != 0);
|
||||
__ and_(tmp1, tmp2);
|
||||
__ test(tmp1, Immediate(kIsSymbolMask));
|
||||
__ test(tmp1, Immediate(kIsInternalizedMask));
|
||||
__ j(zero, &do_compare, Label::kNear);
|
||||
// Make sure eax is non-zero. At this point input operands are
|
||||
// guaranteed to be non-zero.
|
||||
@ -7043,14 +7043,14 @@ void ICCompareStub::GenerateMiss(MacroAssembler* masm) {
|
||||
// the property. This function may return false negatives, so miss_label
|
||||
// must always call a backup property check that is complete.
|
||||
// This function is safe to call if the receiver has fast properties.
|
||||
// Name must be a symbol and receiver must be a heap object.
|
||||
// Name must be an internalized string and receiver must be a heap object.
|
||||
void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm,
|
||||
Label* miss,
|
||||
Label* done,
|
||||
Register properties,
|
||||
Handle<String> name,
|
||||
Register r0) {
|
||||
ASSERT(name->IsSymbol());
|
||||
ASSERT(name->IsInternalizedString());
|
||||
|
||||
// If names of slots in range from 1 to kProbes - 1 for the hash value are
|
||||
// not equal to the name and kProbes-th slot is not used (its name is the
|
||||
@ -7087,10 +7087,10 @@ void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm,
|
||||
__ cmp(entity_name, masm->isolate()->factory()->the_hole_value());
|
||||
__ j(equal, &the_hole, Label::kNear);
|
||||
|
||||
// Check if the entry name is not a symbol.
|
||||
// Check if the entry name is not an internalized string.
|
||||
__ mov(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset));
|
||||
__ test_b(FieldOperand(entity_name, Map::kInstanceTypeOffset),
|
||||
kIsSymbolMask);
|
||||
kIsInternalizedMask);
|
||||
__ j(zero, miss);
|
||||
__ bind(&the_hole);
|
||||
}
|
||||
@ -7225,14 +7225,14 @@ void StringDictionaryLookupStub::Generate(MacroAssembler* masm) {
|
||||
__ j(equal, &in_dictionary);
|
||||
|
||||
if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) {
|
||||
// If we hit a non symbol key during negative lookup
|
||||
// we have to bailout as this key might be equal to the
|
||||
// If we hit a key that is not an internalized string during negative
|
||||
// lookup we have to bailout as this key might be equal to the
|
||||
// key we are looking for.
|
||||
|
||||
// Check if the entry name is not a symbol.
|
||||
// Check if the entry name is not an internalized string.
|
||||
__ mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset));
|
||||
__ test_b(FieldOperand(scratch, Map::kInstanceTypeOffset),
|
||||
kIsSymbolMask);
|
||||
kIsInternalizedMask);
|
||||
__ j(zero, &maybe_in_dictionary);
|
||||
}
|
||||
}
|
||||
|
@ -177,15 +177,15 @@ class StringHelper : public AllStatic {
|
||||
Register scratch, // Neither of above.
|
||||
bool ascii);
|
||||
|
||||
// Probe the symbol table for a two character string. If the string
|
||||
// Probe the string table for a two character string. If the string
|
||||
// requires non-standard hashing a jump to the label not_probed is
|
||||
// performed and registers c1 and c2 are preserved. In all other
|
||||
// cases they are clobbered. If the string is not found by probing a
|
||||
// jump to the label not_found is performed. This jump does not
|
||||
// guarantee that the string is not in the symbol table. If the
|
||||
// guarantee that the string is not in the string table. If the
|
||||
// string is found the code falls through with the string in
|
||||
// register eax.
|
||||
static void GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
|
||||
static void GenerateTwoCharacterStringTableProbe(MacroAssembler* masm,
|
||||
Register c1,
|
||||
Register c2,
|
||||
Register scratch1,
|
||||
|
@ -1586,7 +1586,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
ASSERT(!CompileTimeValue::IsCompileTimeValue(value));
|
||||
// Fall through.
|
||||
case ObjectLiteral::Property::COMPUTED:
|
||||
if (key->handle()->IsSymbol()) {
|
||||
if (key->handle()->IsInternalizedString()) {
|
||||
if (property->emit_store()) {
|
||||
VisitForAccumulatorValue(value);
|
||||
__ mov(ecx, Immediate(key->handle()));
|
||||
@ -2634,7 +2634,7 @@ void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
|
||||
__ cmp(ecx, FACTORY->hash_table_map());
|
||||
__ j(equal, if_false);
|
||||
|
||||
// Look for valueOf symbol in the descriptor array, and indicate false if
|
||||
// Look for valueOf string in the descriptor array, and indicate false if
|
||||
// found. Since we omit an enumeration index check, if it is added via a
|
||||
// transition that shares its descriptor array, this is a false positive.
|
||||
Label entry, loop, done;
|
||||
@ -2656,11 +2656,11 @@ void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
|
||||
// Calculate location of the first key name.
|
||||
__ add(ebx, Immediate(DescriptorArray::kFirstOffset));
|
||||
// Loop through all the keys in the descriptor array. If one of these is the
|
||||
// symbol valueOf the result is false.
|
||||
// internalized string "valueOf" the result is false.
|
||||
__ jmp(&entry);
|
||||
__ bind(&loop);
|
||||
__ mov(edx, FieldOperand(ebx, 0));
|
||||
__ cmp(edx, FACTORY->value_of_symbol());
|
||||
__ cmp(edx, FACTORY->value_of_string());
|
||||
__ j(equal, if_false);
|
||||
__ add(ebx, Immediate(DescriptorArray::kDescriptorSize * kPointerSize));
|
||||
__ bind(&entry);
|
||||
@ -2897,12 +2897,12 @@ void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
|
||||
|
||||
// Functions have class 'Function'.
|
||||
__ bind(&function);
|
||||
__ mov(eax, isolate()->factory()->function_class_symbol());
|
||||
__ mov(eax, isolate()->factory()->function_class_string());
|
||||
__ jmp(&done);
|
||||
|
||||
// Objects with a non-function constructor have class 'Object'.
|
||||
__ bind(&non_function_constructor);
|
||||
__ mov(eax, isolate()->factory()->Object_symbol());
|
||||
__ mov(eax, isolate()->factory()->Object_string());
|
||||
__ jmp(&done);
|
||||
|
||||
// Non-JS objects have class null.
|
||||
@ -4232,12 +4232,12 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
||||
}
|
||||
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||
|
||||
if (check->Equals(isolate()->heap()->number_symbol())) {
|
||||
if (check->Equals(isolate()->heap()->number_string())) {
|
||||
__ JumpIfSmi(eax, if_true);
|
||||
__ cmp(FieldOperand(eax, HeapObject::kMapOffset),
|
||||
isolate()->factory()->heap_number_map());
|
||||
Split(equal, if_true, if_false, fall_through);
|
||||
} else if (check->Equals(isolate()->heap()->string_symbol())) {
|
||||
} else if (check->Equals(isolate()->heap()->string_string())) {
|
||||
__ JumpIfSmi(eax, if_false);
|
||||
__ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edx);
|
||||
__ j(above_equal, if_false);
|
||||
@ -4245,16 +4245,16 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
||||
__ test_b(FieldOperand(edx, Map::kBitFieldOffset),
|
||||
1 << Map::kIsUndetectable);
|
||||
Split(zero, if_true, if_false, fall_through);
|
||||
} else if (check->Equals(isolate()->heap()->boolean_symbol())) {
|
||||
} else if (check->Equals(isolate()->heap()->boolean_string())) {
|
||||
__ cmp(eax, isolate()->factory()->true_value());
|
||||
__ j(equal, if_true);
|
||||
__ cmp(eax, isolate()->factory()->false_value());
|
||||
Split(equal, if_true, if_false, fall_through);
|
||||
} else if (FLAG_harmony_typeof &&
|
||||
check->Equals(isolate()->heap()->null_symbol())) {
|
||||
check->Equals(isolate()->heap()->null_string())) {
|
||||
__ cmp(eax, isolate()->factory()->null_value());
|
||||
Split(equal, if_true, if_false, fall_through);
|
||||
} else if (check->Equals(isolate()->heap()->undefined_symbol())) {
|
||||
} else if (check->Equals(isolate()->heap()->undefined_string())) {
|
||||
__ cmp(eax, isolate()->factory()->undefined_value());
|
||||
__ j(equal, if_true);
|
||||
__ JumpIfSmi(eax, if_false);
|
||||
@ -4263,14 +4263,14 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
||||
__ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
|
||||
__ test(ecx, Immediate(1 << Map::kIsUndetectable));
|
||||
Split(not_zero, if_true, if_false, fall_through);
|
||||
} else if (check->Equals(isolate()->heap()->function_symbol())) {
|
||||
} else if (check->Equals(isolate()->heap()->function_string())) {
|
||||
__ JumpIfSmi(eax, if_false);
|
||||
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
|
||||
__ CmpObjectType(eax, JS_FUNCTION_TYPE, edx);
|
||||
__ j(equal, if_true);
|
||||
__ CmpInstanceType(edx, JS_FUNCTION_PROXY_TYPE);
|
||||
Split(equal, if_true, if_false, fall_through);
|
||||
} else if (check->Equals(isolate()->heap()->object_symbol())) {
|
||||
} else if (check->Equals(isolate()->heap()->object_string())) {
|
||||
__ JumpIfSmi(eax, if_false);
|
||||
if (!FLAG_harmony_typeof) {
|
||||
__ cmp(eax, isolate()->factory()->null_value());
|
||||
|
@ -100,7 +100,7 @@ static void GenerateStringDictionaryReceiverCheck(MacroAssembler* masm,
|
||||
// storage. This function may fail to load a property even though it is
|
||||
// in the dictionary, so code at miss_label must always call a backup
|
||||
// property load that is complete. This function is safe to call if
|
||||
// name is not a symbol, and will jump to the miss_label in that
|
||||
// name is not internalized, and will jump to the miss_label in that
|
||||
// case. The generated code assumes that the receiver has slow
|
||||
// properties, is not a global object and does not have interceptors.
|
||||
static void GenerateDictionaryLoad(MacroAssembler* masm,
|
||||
@ -157,7 +157,7 @@ static void GenerateDictionaryLoad(MacroAssembler* masm,
|
||||
// storage. This function may fail to store a property eventhough it
|
||||
// is in the dictionary, so code at miss_label must always call a
|
||||
// backup property store that is complete. This function is safe to
|
||||
// call if name is not a symbol, and will jump to the miss_label in
|
||||
// call if name is not internalized, and will jump to the miss_label in
|
||||
// that case. The generated code assumes that the receiver has slow
|
||||
// properties, is not a global object and does not have interceptors.
|
||||
static void GenerateDictionaryStore(MacroAssembler* masm,
|
||||
@ -292,31 +292,31 @@ static void GenerateFastArrayLoad(MacroAssembler* masm,
|
||||
}
|
||||
|
||||
|
||||
// Checks whether a key is an array index string or a symbol string.
|
||||
// Falls through if the key is a symbol.
|
||||
// Checks whether a key is an array index string or an internalized string.
|
||||
// Falls through if the key is an internalized string.
|
||||
static void GenerateKeyStringCheck(MacroAssembler* masm,
|
||||
Register key,
|
||||
Register map,
|
||||
Register hash,
|
||||
Label* index_string,
|
||||
Label* not_symbol) {
|
||||
Label* not_internalized) {
|
||||
// Register use:
|
||||
// key - holds the key and is unchanged. Assumed to be non-smi.
|
||||
// Scratch registers:
|
||||
// map - used to hold the map of the key.
|
||||
// hash - used to hold the hash of the key.
|
||||
__ CmpObjectType(key, FIRST_NONSTRING_TYPE, map);
|
||||
__ j(above_equal, not_symbol);
|
||||
__ j(above_equal, not_internalized);
|
||||
|
||||
// Is the string an array index, with cached numeric value?
|
||||
__ mov(hash, FieldOperand(key, String::kHashFieldOffset));
|
||||
__ test(hash, Immediate(String::kContainsCachedArrayIndexMask));
|
||||
__ j(zero, index_string);
|
||||
|
||||
// Is the string a symbol?
|
||||
STATIC_ASSERT(kSymbolTag != 0);
|
||||
__ test_b(FieldOperand(map, Map::kInstanceTypeOffset), kIsSymbolMask);
|
||||
__ j(zero, not_symbol);
|
||||
// Is the string internalized?
|
||||
STATIC_ASSERT(kInternalizedTag != 0);
|
||||
__ test_b(FieldOperand(map, Map::kInstanceTypeOffset), kIsInternalizedMask);
|
||||
__ j(zero, not_internalized);
|
||||
}
|
||||
|
||||
|
||||
@ -484,7 +484,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
__ xor_(eax, edi);
|
||||
__ and_(eax, KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask);
|
||||
|
||||
// Load the key (consisting of map and symbol) from the cache and
|
||||
// Load the key (consisting of map and internalized string) from the cache and
|
||||
// check for match.
|
||||
Label load_in_object_property;
|
||||
static const int kEntriesPerBucket = KeyedLookupCache::kEntriesPerBucket;
|
||||
@ -1198,7 +1198,7 @@ void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
|
||||
__ bind(&check_string);
|
||||
GenerateKeyStringCheck(masm, ecx, eax, ebx, &index_string, &slow_call);
|
||||
|
||||
// The key is known to be a symbol.
|
||||
// The key is known to be an internalized string.
|
||||
// If the receiver is a regular JS object with slow properties then do
|
||||
// a quick inline probe of the receiver's dictionary.
|
||||
// Otherwise do the monomorphic cache probe.
|
||||
@ -1224,7 +1224,7 @@ void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
|
||||
__ bind(&slow_call);
|
||||
// This branch is taken if:
|
||||
// - the receiver requires boxing or access check,
|
||||
// - the key is neither smi nor symbol,
|
||||
// - the key is neither smi nor an internalized string,
|
||||
// - the value loaded is not a function,
|
||||
// - there is hope that the runtime will create a monomorphic call stub
|
||||
// that will get fetched next time.
|
||||
|
@ -2509,12 +2509,12 @@ void LCodeGen::EmitClassOfTest(Label* is_true,
|
||||
__ mov(temp, FieldOperand(temp, JSFunction::kSharedFunctionInfoOffset));
|
||||
__ mov(temp, FieldOperand(temp,
|
||||
SharedFunctionInfo::kInstanceClassNameOffset));
|
||||
// The class name we are testing against is a symbol because it's a literal.
|
||||
// The name in the constructor is a symbol because of the way the context is
|
||||
// booted. This routine isn't expected to work for random API-created
|
||||
// The class name we are testing against is internalized since it's a literal.
|
||||
// The name in the constructor is internalized because of the way the context
|
||||
// is booted. This routine isn't expected to work for random API-created
|
||||
// classes and it doesn't have to because you can't access it with natives
|
||||
// syntax. Since both sides are symbols it is sufficient to use an identity
|
||||
// comparison.
|
||||
// syntax. Since both sides are internalized it is sufficient to use an
|
||||
// identity comparison.
|
||||
__ cmp(temp, class_name);
|
||||
// End with the answer in the z flag.
|
||||
}
|
||||
@ -5920,13 +5920,13 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
|
||||
Register input,
|
||||
Handle<String> type_name) {
|
||||
Condition final_branch_condition = no_condition;
|
||||
if (type_name->Equals(heap()->number_symbol())) {
|
||||
if (type_name->Equals(heap()->number_string())) {
|
||||
__ JumpIfSmi(input, true_label);
|
||||
__ cmp(FieldOperand(input, HeapObject::kMapOffset),
|
||||
factory()->heap_number_map());
|
||||
final_branch_condition = equal;
|
||||
|
||||
} else if (type_name->Equals(heap()->string_symbol())) {
|
||||
} else if (type_name->Equals(heap()->string_string())) {
|
||||
__ JumpIfSmi(input, false_label);
|
||||
__ CmpObjectType(input, FIRST_NONSTRING_TYPE, input);
|
||||
__ j(above_equal, false_label);
|
||||
@ -5934,17 +5934,17 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
|
||||
1 << Map::kIsUndetectable);
|
||||
final_branch_condition = zero;
|
||||
|
||||
} else if (type_name->Equals(heap()->boolean_symbol())) {
|
||||
} else if (type_name->Equals(heap()->boolean_string())) {
|
||||
__ cmp(input, factory()->true_value());
|
||||
__ j(equal, true_label);
|
||||
__ cmp(input, factory()->false_value());
|
||||
final_branch_condition = equal;
|
||||
|
||||
} else if (FLAG_harmony_typeof && type_name->Equals(heap()->null_symbol())) {
|
||||
} else if (FLAG_harmony_typeof && type_name->Equals(heap()->null_string())) {
|
||||
__ cmp(input, factory()->null_value());
|
||||
final_branch_condition = equal;
|
||||
|
||||
} else if (type_name->Equals(heap()->undefined_symbol())) {
|
||||
} else if (type_name->Equals(heap()->undefined_string())) {
|
||||
__ cmp(input, factory()->undefined_value());
|
||||
__ j(equal, true_label);
|
||||
__ JumpIfSmi(input, false_label);
|
||||
@ -5954,7 +5954,7 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
|
||||
1 << Map::kIsUndetectable);
|
||||
final_branch_condition = not_zero;
|
||||
|
||||
} else if (type_name->Equals(heap()->function_symbol())) {
|
||||
} else if (type_name->Equals(heap()->function_string())) {
|
||||
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
|
||||
__ JumpIfSmi(input, false_label);
|
||||
__ CmpObjectType(input, JS_FUNCTION_TYPE, input);
|
||||
@ -5962,7 +5962,7 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
|
||||
__ CmpInstanceType(input, JS_FUNCTION_PROXY_TYPE);
|
||||
final_branch_condition = equal;
|
||||
|
||||
} else if (type_name->Equals(heap()->object_symbol())) {
|
||||
} else if (type_name->Equals(heap()->object_string())) {
|
||||
__ JumpIfSmi(input, false_label);
|
||||
if (!FLAG_harmony_typeof) {
|
||||
__ cmp(input, factory()->null_value());
|
||||
|
@ -141,14 +141,14 @@ static void ProbeTable(Isolate* isolate,
|
||||
// the property. This function may return false negatives, so miss_label
|
||||
// must always call a backup property check that is complete.
|
||||
// This function is safe to call if the receiver has fast properties.
|
||||
// Name must be a symbol and receiver must be a heap object.
|
||||
// Name must be an internalized string and receiver must be a heap object.
|
||||
static void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
|
||||
Label* miss_label,
|
||||
Register receiver,
|
||||
Handle<String> name,
|
||||
Register r0,
|
||||
Register r1) {
|
||||
ASSERT(name->IsSymbol());
|
||||
ASSERT(name->IsInternalizedString());
|
||||
Counters* counters = masm->isolate()->counters();
|
||||
__ IncrementCounter(counters->negative_lookups(), 1);
|
||||
__ IncrementCounter(counters->negative_lookups_miss(), 1);
|
||||
@ -972,8 +972,8 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
|
||||
if (!current->HasFastProperties() &&
|
||||
!current->IsJSGlobalObject() &&
|
||||
!current->IsJSGlobalProxy()) {
|
||||
if (!name->IsSymbol()) {
|
||||
name = factory()->LookupSymbol(name);
|
||||
if (!name->IsInternalizedString()) {
|
||||
name = factory()->InternalizeString(name);
|
||||
}
|
||||
ASSERT(current->property_dictionary()->FindEntry(*name) ==
|
||||
StringDictionary::kNotFound);
|
||||
@ -2355,7 +2355,7 @@ void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
|
||||
break;
|
||||
|
||||
case STRING_CHECK:
|
||||
// Check that the object is a string or a symbol.
|
||||
// Check that the object is a string.
|
||||
__ CmpObjectType(edx, FIRST_NONSTRING_TYPE, eax);
|
||||
__ j(above_equal, &miss);
|
||||
// Check that the maps starting from the prototype haven't changed.
|
||||
|
49
src/ic.cc
49
src/ic.cc
@ -756,7 +756,7 @@ void CallICBase::UpdateCaches(LookupResult* lookup,
|
||||
MaybeObject* KeyedCallIC::LoadFunction(State state,
|
||||
Handle<Object> object,
|
||||
Handle<Object> key) {
|
||||
if (key->IsSymbol()) {
|
||||
if (key->IsInternalizedString()) {
|
||||
return CallICBase::LoadFunction(state,
|
||||
Code::kNoExtraICState,
|
||||
object,
|
||||
@ -817,7 +817,7 @@ MaybeObject* LoadIC::Load(State state,
|
||||
// objects is read-only and therefore always returns the length of
|
||||
// the underlying string value. See ECMA-262 15.5.5.1.
|
||||
if ((object->IsString() || object->IsStringWrapper()) &&
|
||||
name->Equals(isolate()->heap()->length_symbol())) {
|
||||
name->Equals(isolate()->heap()->length_string())) {
|
||||
Handle<Code> stub;
|
||||
if (state == UNINITIALIZED) {
|
||||
stub = pre_monomorphic_stub();
|
||||
@ -846,7 +846,7 @@ MaybeObject* LoadIC::Load(State state,
|
||||
|
||||
// Use specialized code for getting the length of arrays.
|
||||
if (object->IsJSArray() &&
|
||||
name->Equals(isolate()->heap()->length_symbol())) {
|
||||
name->Equals(isolate()->heap()->length_string())) {
|
||||
Handle<Code> stub;
|
||||
if (state == UNINITIALIZED) {
|
||||
stub = pre_monomorphic_stub();
|
||||
@ -868,7 +868,7 @@ MaybeObject* LoadIC::Load(State state,
|
||||
|
||||
// Use specialized code for getting prototype of functions.
|
||||
if (object->IsJSFunction() &&
|
||||
name->Equals(isolate()->heap()->prototype_symbol()) &&
|
||||
name->Equals(isolate()->heap()->prototype_string()) &&
|
||||
Handle<JSFunction>::cast(object)->should_have_prototype()) {
|
||||
Handle<Code> stub;
|
||||
if (state == UNINITIALIZED) {
|
||||
@ -1093,7 +1093,7 @@ static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) {
|
||||
if (key->IsHeapNumber()) {
|
||||
double value = Handle<HeapNumber>::cast(key)->value();
|
||||
if (isnan(value)) {
|
||||
key = isolate->factory()->nan_symbol();
|
||||
key = isolate->factory()->nan_string();
|
||||
} else {
|
||||
int int_value = FastD2I(value);
|
||||
if (value == int_value && Smi::IsValid(int_value)) {
|
||||
@ -1101,7 +1101,7 @@ static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) {
|
||||
}
|
||||
}
|
||||
} else if (key->IsUndefined()) {
|
||||
key = isolate->factory()->undefined_symbol();
|
||||
key = isolate->factory()->undefined_string();
|
||||
}
|
||||
return key;
|
||||
}
|
||||
@ -1226,11 +1226,11 @@ MaybeObject* KeyedLoadIC::Load(State state,
|
||||
Handle<Object> object,
|
||||
Handle<Object> key,
|
||||
ICMissMode miss_mode) {
|
||||
// Check for values that can be converted into a symbol directly or
|
||||
// is representable as a smi.
|
||||
// Check for values that can be converted into an internalized string directly
|
||||
// or is representable as a smi.
|
||||
key = TryConvertKey(key, isolate());
|
||||
|
||||
if (key->IsSymbol()) {
|
||||
if (key->IsInternalizedString()) {
|
||||
return LoadIC::Load(state, object, Handle<String>::cast(key));
|
||||
}
|
||||
|
||||
@ -1367,7 +1367,7 @@ MaybeObject* StoreIC::Store(State state,
|
||||
|
||||
// The length property of string values is read-only. Throw in strict mode.
|
||||
if (strict_mode == kStrictMode && object->IsString() &&
|
||||
name->Equals(isolate()->heap()->length_symbol())) {
|
||||
name->Equals(isolate()->heap()->length_string())) {
|
||||
return TypeError("strict_read_only_property", object, name);
|
||||
}
|
||||
|
||||
@ -1396,7 +1396,7 @@ MaybeObject* StoreIC::Store(State state,
|
||||
// property.
|
||||
if (FLAG_use_ic &&
|
||||
receiver->IsJSArray() &&
|
||||
name->Equals(isolate()->heap()->length_symbol()) &&
|
||||
name->Equals(isolate()->heap()->length_string()) &&
|
||||
Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() &&
|
||||
receiver->HasFastProperties()) {
|
||||
Handle<Code> stub =
|
||||
@ -1723,11 +1723,11 @@ MaybeObject* KeyedStoreIC::Store(State state,
|
||||
Handle<Object> key,
|
||||
Handle<Object> value,
|
||||
ICMissMode miss_mode) {
|
||||
// Check for values that can be converted into a symbol directly or
|
||||
// is representable as a smi.
|
||||
// Check for values that can be converted into an internalized string directly
|
||||
// or is representable as a smi.
|
||||
key = TryConvertKey(key, isolate());
|
||||
|
||||
if (key->IsSymbol()) {
|
||||
if (key->IsInternalizedString()) {
|
||||
return StoreIC::Store(state,
|
||||
strict_mode,
|
||||
object,
|
||||
@ -1936,7 +1936,7 @@ RUNTIME_FUNCTION(MaybeObject*, StoreIC_ArrayLength) {
|
||||
#ifdef DEBUG
|
||||
// The length property has to be a writable callback property.
|
||||
LookupResult debug_lookup(isolate);
|
||||
receiver->LocalLookup(isolate->heap()->length_symbol(), &debug_lookup);
|
||||
receiver->LocalLookup(isolate->heap()->length_string(), &debug_lookup);
|
||||
ASSERT(debug_lookup.IsPropertyCallbacks() && !debug_lookup.IsReadOnly());
|
||||
#endif
|
||||
|
||||
@ -2376,7 +2376,7 @@ const char* CompareIC::GetStateName(State state) {
|
||||
case UNINITIALIZED: return "UNINITIALIZED";
|
||||
case SMI: return "SMI";
|
||||
case NUMBER: return "NUMBER";
|
||||
case SYMBOL: return "SYMBOL";
|
||||
case INTERNALIZED_STRING: return "INTERNALIZED_STRING";
|
||||
case STRING: return "STRING";
|
||||
case OBJECT: return "OBJECT";
|
||||
case KNOWN_OBJECT: return "KNOWN_OBJECT";
|
||||
@ -2394,7 +2394,7 @@ static CompareIC::State InputState(CompareIC::State old_state,
|
||||
case CompareIC::UNINITIALIZED:
|
||||
if (value->IsSmi()) return CompareIC::SMI;
|
||||
if (value->IsHeapNumber()) return CompareIC::NUMBER;
|
||||
if (value->IsSymbol()) return CompareIC::SYMBOL;
|
||||
if (value->IsInternalizedString()) return CompareIC::INTERNALIZED_STRING;
|
||||
if (value->IsString()) return CompareIC::STRING;
|
||||
if (value->IsJSObject()) return CompareIC::OBJECT;
|
||||
break;
|
||||
@ -2405,12 +2405,13 @@ static CompareIC::State InputState(CompareIC::State old_state,
|
||||
case CompareIC::NUMBER:
|
||||
if (value->IsNumber()) return CompareIC::NUMBER;
|
||||
break;
|
||||
case CompareIC::SYMBOL:
|
||||
if (value->IsSymbol()) return CompareIC::SYMBOL;
|
||||
case CompareIC::INTERNALIZED_STRING:
|
||||
if (value->IsInternalizedString()) return CompareIC::INTERNALIZED_STRING;
|
||||
if (value->IsString()) return CompareIC::STRING;
|
||||
break;
|
||||
case CompareIC::STRING:
|
||||
if (value->IsSymbol() || value->IsString()) return CompareIC::STRING;
|
||||
if (value->IsInternalizedString() || value->IsString())
|
||||
return CompareIC::STRING;
|
||||
break;
|
||||
case CompareIC::OBJECT:
|
||||
if (value->IsJSObject()) return CompareIC::OBJECT;
|
||||
@ -2443,10 +2444,10 @@ CompareIC::State CompareIC::TargetState(State old_state,
|
||||
return NUMBER;
|
||||
}
|
||||
}
|
||||
if (x->IsSymbol() && y->IsSymbol()) {
|
||||
// We compare symbols as strings if we need to determine
|
||||
if (x->IsInternalizedString() && y->IsInternalizedString()) {
|
||||
// We compare internalized strings as plain ones if we need to determine
|
||||
// the order in a non-equality compare.
|
||||
return Token::IsEqualityOp(op_) ? SYMBOL : STRING;
|
||||
return Token::IsEqualityOp(op_) ? INTERNALIZED_STRING : STRING;
|
||||
}
|
||||
if (x->IsString() && y->IsString()) return STRING;
|
||||
if (!Token::IsEqualityOp(op_)) return GENERIC;
|
||||
@ -2461,7 +2462,7 @@ CompareIC::State CompareIC::TargetState(State old_state,
|
||||
return GENERIC;
|
||||
case SMI:
|
||||
return x->IsNumber() && y->IsNumber() ? NUMBER : GENERIC;
|
||||
case SYMBOL:
|
||||
case INTERNALIZED_STRING:
|
||||
ASSERT(Token::IsEqualityOp(op_));
|
||||
return x->IsString() && y->IsString() ? STRING : GENERIC;
|
||||
case NUMBER:
|
||||
|
4
src/ic.h
4
src/ic.h
@ -756,14 +756,14 @@ class CompareIC: public IC {
|
||||
// UNINITIALIZED < ...
|
||||
// ... < GENERIC
|
||||
// SMI < NUMBER
|
||||
// SYMBOL < STRING
|
||||
// INTERNALIZED_STRING < STRING
|
||||
// KNOWN_OBJECT < OBJECT
|
||||
enum State {
|
||||
UNINITIALIZED,
|
||||
SMI,
|
||||
NUMBER,
|
||||
SYMBOL,
|
||||
STRING,
|
||||
INTERNALIZED_STRING,
|
||||
OBJECT, // JSObject
|
||||
KNOWN_OBJECT, // JSObject with specific map (faster check)
|
||||
GENERIC
|
||||
|
@ -35,8 +35,8 @@ namespace internal {
|
||||
static bool Match(void* key1, void* key2) {
|
||||
String* name1 = *static_cast<String**>(key1);
|
||||
String* name2 = *static_cast<String**>(key2);
|
||||
ASSERT(name1->IsSymbol());
|
||||
ASSERT(name2->IsSymbol());
|
||||
ASSERT(name1->IsInternalizedString());
|
||||
ASSERT(name2->IsInternalizedString());
|
||||
return name1 == name2;
|
||||
}
|
||||
|
||||
|
@ -541,11 +541,11 @@ Handle<String> Isolate::StackTraceString() {
|
||||
OS::PrintError(
|
||||
"If you are lucky you may find a partial stack dump on stdout.\n\n");
|
||||
incomplete_message_->OutputToStdOut();
|
||||
return factory()->empty_symbol();
|
||||
return factory()->empty_string();
|
||||
} else {
|
||||
OS::Abort();
|
||||
// Unreachable
|
||||
return factory()->empty_symbol();
|
||||
return factory()->empty_string();
|
||||
}
|
||||
}
|
||||
|
||||
@ -662,7 +662,7 @@ Handle<JSArray> Isolate::CaptureSimpleStackTrace(Handle<JSObject> error_object,
|
||||
void Isolate::CaptureAndSetDetailedStackTrace(Handle<JSObject> error_object) {
|
||||
if (capture_stack_trace_for_uncaught_exceptions_) {
|
||||
// Capture stack trace for a detailed exception message.
|
||||
Handle<String> key = factory()->hidden_stack_trace_symbol();
|
||||
Handle<String> key = factory()->hidden_stack_trace_string();
|
||||
Handle<JSArray> stack_trace = CaptureCurrentStackTrace(
|
||||
stack_trace_for_uncaught_exceptions_frame_limit_,
|
||||
stack_trace_for_uncaught_exceptions_options_);
|
||||
@ -678,20 +678,20 @@ Handle<JSArray> Isolate::CaptureCurrentStackTrace(
|
||||
Handle<JSArray> stack_trace = factory()->NewJSArray(frame_limit);
|
||||
|
||||
Handle<String> column_key =
|
||||
factory()->LookupOneByteSymbol(STATIC_ASCII_VECTOR("column"));
|
||||
factory()->InternalizeOneByteString(STATIC_ASCII_VECTOR("column"));
|
||||
Handle<String> line_key =
|
||||
factory()->LookupOneByteSymbol(STATIC_ASCII_VECTOR("lineNumber"));
|
||||
factory()->InternalizeOneByteString(STATIC_ASCII_VECTOR("lineNumber"));
|
||||
Handle<String> script_key =
|
||||
factory()->LookupOneByteSymbol(STATIC_ASCII_VECTOR("scriptName"));
|
||||
factory()->InternalizeOneByteString(STATIC_ASCII_VECTOR("scriptName"));
|
||||
Handle<String> script_name_or_source_url_key =
|
||||
factory()->LookupOneByteSymbol(
|
||||
factory()->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("scriptNameOrSourceURL"));
|
||||
Handle<String> function_key =
|
||||
factory()->LookupOneByteSymbol(STATIC_ASCII_VECTOR("functionName"));
|
||||
factory()->InternalizeOneByteString(STATIC_ASCII_VECTOR("functionName"));
|
||||
Handle<String> eval_key =
|
||||
factory()->LookupOneByteSymbol(STATIC_ASCII_VECTOR("isEval"));
|
||||
factory()->InternalizeOneByteString(STATIC_ASCII_VECTOR("isEval"));
|
||||
Handle<String> constructor_key =
|
||||
factory()->LookupOneByteSymbol(STATIC_ASCII_VECTOR("isConstructor"));
|
||||
factory()->InternalizeOneByteString(STATIC_ASCII_VECTOR("isConstructor"));
|
||||
|
||||
StackTraceFrameIterator it(this);
|
||||
int frames_seen = 0;
|
||||
@ -934,7 +934,7 @@ bool Isolate::MayNamedAccess(JSObject* receiver, Object* key,
|
||||
|
||||
// Skip checks for hidden properties access. Note, we do not
|
||||
// require existence of a context in this case.
|
||||
if (key == heap_.hidden_symbol()) return true;
|
||||
if (key == heap_.hidden_string()) return true;
|
||||
|
||||
// Check for compatibility between the security tokens in the
|
||||
// current lexical context and the accessed object.
|
||||
@ -1030,7 +1030,7 @@ Failure* Isolate::StackOverflow() {
|
||||
// At this point we cannot create an Error object using its javascript
|
||||
// constructor. Instead, we copy the pre-constructed boilerplate and
|
||||
// attach the stack trace as a hidden property.
|
||||
Handle<String> key = factory()->stack_overflow_symbol();
|
||||
Handle<String> key = factory()->stack_overflow_string();
|
||||
Handle<JSObject> boilerplate =
|
||||
Handle<JSObject>::cast(GetProperty(this, js_builtins_object(), key));
|
||||
Handle<JSObject> exception = Copy(boilerplate);
|
||||
@ -1047,7 +1047,7 @@ Failure* Isolate::StackOverflow() {
|
||||
Handle<JSArray> stack_trace = CaptureSimpleStackTrace(
|
||||
exception, factory()->undefined_value(), limit);
|
||||
JSObject::SetHiddenProperty(exception,
|
||||
factory()->hidden_stack_trace_symbol(),
|
||||
factory()->hidden_stack_trace_string(),
|
||||
stack_trace);
|
||||
return Failure::Exception();
|
||||
}
|
||||
@ -1081,7 +1081,7 @@ Failure* Isolate::ReThrow(MaybeObject* exception) {
|
||||
|
||||
|
||||
Failure* Isolate::ThrowIllegalOperation() {
|
||||
return Throw(heap_.illegal_access_symbol());
|
||||
return Throw(heap_.illegal_access_string());
|
||||
}
|
||||
|
||||
|
||||
@ -1187,7 +1187,7 @@ bool Isolate::IsErrorObject(Handle<Object> obj) {
|
||||
if (!obj->IsJSObject()) return false;
|
||||
|
||||
String* error_key =
|
||||
*(factory()->LookupOneByteSymbol(STATIC_ASCII_VECTOR("$Error")));
|
||||
*(factory()->InternalizeOneByteString(STATIC_ASCII_VECTOR("$Error")));
|
||||
Object* error_constructor =
|
||||
js_builtins_object()->GetPropertyNoExceptionThrown(error_key);
|
||||
|
||||
@ -1243,7 +1243,7 @@ void Isolate::DoThrow(Object* exception, MessageLocation* location) {
|
||||
if (capture_stack_trace_for_uncaught_exceptions_) {
|
||||
if (IsErrorObject(exception_handle)) {
|
||||
// We fetch the stack trace that corresponds to this error object.
|
||||
String* key = heap()->hidden_stack_trace_symbol();
|
||||
String* key = heap()->hidden_stack_trace_string();
|
||||
Object* stack_property =
|
||||
JSObject::cast(*exception_handle)->GetHiddenProperty(key);
|
||||
// Property lookup may have failed. In this case it's probably not
|
||||
@ -1268,8 +1268,8 @@ void Isolate::DoThrow(Object* exception, MessageLocation* location) {
|
||||
bool failed = false;
|
||||
exception_arg = Execution::ToDetailString(exception_arg, &failed);
|
||||
if (failed) {
|
||||
exception_arg =
|
||||
factory()->LookupOneByteSymbol(STATIC_ASCII_VECTOR("exception"));
|
||||
exception_arg = factory()->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("exception"));
|
||||
}
|
||||
}
|
||||
Handle<Object> message_obj = MessageHandler::MakeMessageObject(
|
||||
|
@ -102,10 +102,10 @@ class JsonParser BASE_EMBEDDED {
|
||||
Handle<String> ParseJsonString() {
|
||||
return ScanJsonString<false>();
|
||||
}
|
||||
Handle<String> ParseJsonSymbol() {
|
||||
Handle<String> ParseJsonInternalizedString() {
|
||||
return ScanJsonString<true>();
|
||||
}
|
||||
template <bool is_symbol>
|
||||
template <bool is_internalized>
|
||||
Handle<String> ScanJsonString();
|
||||
// Creates a new string and copies prefix[start..end] into the beginning
|
||||
// of it. Then scans the rest of the string, adding characters after the
|
||||
@ -338,7 +338,7 @@ Handle<Object> JsonParser<seq_ascii>::ParseJsonObject() {
|
||||
c0_ = '"';
|
||||
#endif
|
||||
|
||||
Handle<String> key = ParseJsonSymbol();
|
||||
Handle<String> key = ParseJsonInternalizedString();
|
||||
if (key.is_null() || c0_ != ':') return ReportUnexpectedCharacter();
|
||||
|
||||
AdvanceSkipWhitespace();
|
||||
@ -601,7 +601,7 @@ Handle<String> JsonParser<seq_ascii>::SlowScanJsonString(
|
||||
|
||||
|
||||
template <bool seq_ascii>
|
||||
template <bool is_symbol>
|
||||
template <bool is_internalized>
|
||||
Handle<String> JsonParser<seq_ascii>::ScanJsonString() {
|
||||
ASSERT_EQ('"', c0_);
|
||||
Advance();
|
||||
@ -610,10 +610,10 @@ Handle<String> JsonParser<seq_ascii>::ScanJsonString() {
|
||||
return factory()->empty_string();
|
||||
}
|
||||
|
||||
if (seq_ascii && is_symbol) {
|
||||
// Fast path for existing symbols. If the the string being parsed is not
|
||||
// a known symbol, contains backslashes or unexpectedly reaches the end of
|
||||
// string, return with an empty handle.
|
||||
if (seq_ascii && is_internalized) {
|
||||
// Fast path for existing internalized strings. If the the string being
|
||||
// parsed is not a known internalized string, contains backslashes or
|
||||
// unexpectedly reaches the end of string, return with an empty handle.
|
||||
uint32_t running_hash = isolate()->heap()->HashSeed();
|
||||
int position = position_;
|
||||
uc32 c0 = c0_;
|
||||
@ -647,12 +647,12 @@ Handle<String> JsonParser<seq_ascii>::ScanJsonString() {
|
||||
? StringHasher::GetHashCore(running_hash) : length;
|
||||
Vector<const uint8_t> string_vector(
|
||||
seq_source_->GetChars() + position_, length);
|
||||
SymbolTable* symbol_table = isolate()->heap()->symbol_table();
|
||||
uint32_t capacity = symbol_table->Capacity();
|
||||
uint32_t entry = SymbolTable::FirstProbe(hash, capacity);
|
||||
StringTable* string_table = isolate()->heap()->string_table();
|
||||
uint32_t capacity = string_table->Capacity();
|
||||
uint32_t entry = StringTable::FirstProbe(hash, capacity);
|
||||
uint32_t count = 1;
|
||||
while (true) {
|
||||
Object* element = symbol_table->KeyAt(entry);
|
||||
Object* element = string_table->KeyAt(entry);
|
||||
if (element == isolate()->heap()->undefined_value()) {
|
||||
// Lookup failure.
|
||||
break;
|
||||
@ -665,7 +665,7 @@ Handle<String> JsonParser<seq_ascii>::ScanJsonString() {
|
||||
AdvanceSkipWhitespace();
|
||||
return Handle<String>(String::cast(element), isolate());
|
||||
}
|
||||
entry = SymbolTable::NextProbe(entry, count++, capacity);
|
||||
entry = StringTable::NextProbe(entry, count++, capacity);
|
||||
}
|
||||
}
|
||||
|
||||
@ -690,8 +690,8 @@ Handle<String> JsonParser<seq_ascii>::ScanJsonString() {
|
||||
} while (c0_ != '"');
|
||||
int length = position_ - beg_pos;
|
||||
Handle<String> result;
|
||||
if (seq_ascii && is_symbol) {
|
||||
result = factory()->LookupOneByteSymbol(seq_source_, beg_pos, length);
|
||||
if (seq_ascii && is_internalized) {
|
||||
result = factory()->InternalizeOneByteString(seq_source_, beg_pos, length);
|
||||
} else {
|
||||
result = factory()->NewRawOneByteString(length, pretenure_);
|
||||
uint8_t* dest = SeqOneByteString::cast(*result)->GetChars();
|
||||
|
@ -165,7 +165,7 @@ class BasicJsonStringifier BASE_EMBEDDED {
|
||||
// (indirect) handle to it in the outermost handle scope.
|
||||
Handle<JSValue> accumulator_store_;
|
||||
Handle<String> current_part_;
|
||||
Handle<String> tojson_symbol_;
|
||||
Handle<String> tojson_string_;
|
||||
Handle<JSArray> stack_;
|
||||
int current_index_;
|
||||
int part_length_;
|
||||
@ -251,8 +251,8 @@ BasicJsonStringifier::BasicJsonStringifier(Isolate* isolate)
|
||||
factory_->ToObject(factory_->empty_string()));
|
||||
part_length_ = kInitialPartLength;
|
||||
current_part_ = factory_->NewRawOneByteString(kInitialPartLength);
|
||||
tojson_symbol_ =
|
||||
factory_->LookupOneByteSymbol(STATIC_ASCII_VECTOR("toJSON"));
|
||||
tojson_string_ =
|
||||
factory_->InternalizeOneByteString(STATIC_ASCII_VECTOR("toJSON"));
|
||||
stack_ = factory_->NewJSArray(8);
|
||||
}
|
||||
|
||||
@ -297,11 +297,11 @@ void BasicJsonStringifier::Append_(const Char* chars) {
|
||||
Handle<Object> BasicJsonStringifier::ApplyToJsonFunction(
|
||||
Handle<Object> object, Handle<Object> key) {
|
||||
LookupResult lookup(isolate_);
|
||||
JSObject::cast(*object)->LookupRealNamedProperty(*tojson_symbol_, &lookup);
|
||||
JSObject::cast(*object)->LookupRealNamedProperty(*tojson_string_, &lookup);
|
||||
if (!lookup.IsProperty()) return object;
|
||||
PropertyAttributes attr;
|
||||
Handle<Object> fun =
|
||||
Object::GetProperty(object, object, &lookup, tojson_symbol_, &attr);
|
||||
Object::GetProperty(object, object, &lookup, tojson_string_, &attr);
|
||||
if (!fun->IsJSFunction()) return object;
|
||||
|
||||
// Call toJSON function.
|
||||
@ -434,17 +434,17 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSValue(
|
||||
Handle<JSValue> object) {
|
||||
bool has_exception = false;
|
||||
String* class_name = object->class_name();
|
||||
if (class_name == isolate_->heap()->String_symbol()) {
|
||||
if (class_name == isolate_->heap()->String_string()) {
|
||||
Handle<Object> value = Execution::ToString(object, &has_exception);
|
||||
if (has_exception) return EXCEPTION;
|
||||
SerializeString(Handle<String>::cast(value));
|
||||
} else if (class_name == isolate_->heap()->Number_symbol()) {
|
||||
} else if (class_name == isolate_->heap()->Number_string()) {
|
||||
Handle<Object> value = Execution::ToNumber(object, &has_exception);
|
||||
if (has_exception) return EXCEPTION;
|
||||
if (value->IsSmi()) return SerializeSmi(Smi::cast(*value));
|
||||
SerializeHeapNumber(Handle<HeapNumber>::cast(value));
|
||||
} else {
|
||||
ASSERT(class_name == isolate_->heap()->Boolean_symbol());
|
||||
ASSERT(class_name == isolate_->heap()->Boolean_string());
|
||||
Object* value = JSValue::cast(*object)->value();
|
||||
ASSERT(value->IsBoolean());
|
||||
AppendAscii(value->IsTrue() ? "true" : "false");
|
||||
|
@ -966,14 +966,14 @@ JSArray* LiveEdit::GatherCompileInfo(Handle<Script> script,
|
||||
rethrow_exception = Handle<JSObject>::cast(exception);
|
||||
|
||||
Factory* factory = isolate->factory();
|
||||
Handle<String> start_pos_key =
|
||||
factory->LookupOneByteSymbol(STATIC_ASCII_VECTOR("startPosition"));
|
||||
Handle<String> end_pos_key =
|
||||
factory->LookupOneByteSymbol(STATIC_ASCII_VECTOR("endPosition"));
|
||||
Handle<String> script_obj_key =
|
||||
factory->LookupOneByteSymbol(STATIC_ASCII_VECTOR("scriptObject"));
|
||||
Handle<Smi> start_pos(Smi::FromInt(message_location.start_pos()),
|
||||
isolate);
|
||||
Handle<String> start_pos_key = factory->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("startPosition"));
|
||||
Handle<String> end_pos_key = factory->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("endPosition"));
|
||||
Handle<String> script_obj_key = factory->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("scriptObject"));
|
||||
Handle<Smi> start_pos(
|
||||
Smi::FromInt(message_location.start_pos()), isolate);
|
||||
Handle<Smi> end_pos(Smi::FromInt(message_location.end_pos()), isolate);
|
||||
Handle<JSValue> script_obj = GetScriptWrapper(message_location.script());
|
||||
JSReceiver::SetProperty(
|
||||
|
@ -262,7 +262,7 @@ void LogMessageBuilder::AppendDetailed(String* str, bool show_impl_info) {
|
||||
Append(str->IsOneByteRepresentation() ? 'a' : '2');
|
||||
if (StringShape(str).IsExternal())
|
||||
Append('e');
|
||||
if (StringShape(str).IsSymbol())
|
||||
if (StringShape(str).IsInternalized())
|
||||
Append('#');
|
||||
Append(":%i:", str->length());
|
||||
}
|
||||
|
@ -1178,7 +1178,7 @@ MarkCompactCollector::~MarkCompactCollector() {
|
||||
|
||||
|
||||
static inline HeapObject* ShortCircuitConsString(Object** p) {
|
||||
// Optimization: If the heap object pointed to by p is a non-symbol
|
||||
// Optimization: If the heap object pointed to by p is a non-internalized
|
||||
// cons string whose right substring is HEAP->empty_string, update
|
||||
// it in place to its left substring. Return the updated value.
|
||||
//
|
||||
@ -1186,7 +1186,7 @@ static inline HeapObject* ShortCircuitConsString(Object** p) {
|
||||
// (i.e., the left substring of a cons string is always a heap object).
|
||||
//
|
||||
// The check performed is:
|
||||
// object->IsConsString() && !object->IsSymbol() &&
|
||||
// object->IsConsString() && !object->IsInternalizedString() &&
|
||||
// (ConsString::cast(object)->second() == HEAP->empty_string())
|
||||
// except the maps for the object and its possible substrings might be
|
||||
// marked.
|
||||
@ -1563,10 +1563,10 @@ class MarkCompactMarkingVisitor::ObjectStatsTracker<
|
||||
static inline void Visit(Map* map, HeapObject* obj) {
|
||||
Heap* heap = map->GetHeap();
|
||||
FixedArray* fixed_array = FixedArray::cast(obj);
|
||||
if (fixed_array == heap->symbol_table()) {
|
||||
if (fixed_array == heap->string_table()) {
|
||||
heap->RecordObjectStats(
|
||||
FIXED_ARRAY_TYPE,
|
||||
SYMBOL_TABLE_SUB_TYPE,
|
||||
STRING_TABLE_SUB_TYPE,
|
||||
fixed_array->Size());
|
||||
}
|
||||
ObjectStatsVisitBase(kVisitFixedArray, map, obj);
|
||||
@ -1747,10 +1747,10 @@ class RootMarkingVisitor : public ObjectVisitor {
|
||||
};
|
||||
|
||||
|
||||
// Helper class for pruning the symbol table.
|
||||
class SymbolTableCleaner : public ObjectVisitor {
|
||||
// Helper class for pruning the string table.
|
||||
class StringTableCleaner : public ObjectVisitor {
|
||||
public:
|
||||
explicit SymbolTableCleaner(Heap* heap)
|
||||
explicit StringTableCleaner(Heap* heap)
|
||||
: heap_(heap), pointers_removed_(0) { }
|
||||
|
||||
virtual void VisitPointers(Object** start, Object** end) {
|
||||
@ -1759,8 +1759,8 @@ class SymbolTableCleaner : public ObjectVisitor {
|
||||
Object* o = *p;
|
||||
if (o->IsHeapObject() &&
|
||||
!Marking::MarkBitFrom(HeapObject::cast(o)).Get()) {
|
||||
// Check if the symbol being pruned is an external symbol. We need to
|
||||
// delete the associated external data as this symbol is going away.
|
||||
// Check if the internalized string being pruned is external. We need to
|
||||
// delete the associated external data as this string is going away.
|
||||
|
||||
// Since no objects have yet been moved we can safely access the map of
|
||||
// the object.
|
||||
@ -1920,14 +1920,14 @@ bool MarkCompactCollector::IsUnmarkedHeapObjectWithHeap(Heap* heap,
|
||||
}
|
||||
|
||||
|
||||
void MarkCompactCollector::MarkSymbolTable() {
|
||||
SymbolTable* symbol_table = heap()->symbol_table();
|
||||
// Mark the symbol table itself.
|
||||
MarkBit symbol_table_mark = Marking::MarkBitFrom(symbol_table);
|
||||
SetMark(symbol_table, symbol_table_mark);
|
||||
void MarkCompactCollector::MarkStringTable() {
|
||||
StringTable* string_table = heap()->string_table();
|
||||
// Mark the string table itself.
|
||||
MarkBit string_table_mark = Marking::MarkBitFrom(string_table);
|
||||
SetMark(string_table, string_table_mark);
|
||||
// Explicitly mark the prefix.
|
||||
MarkingVisitor marker(heap());
|
||||
symbol_table->IteratePrefix(&marker);
|
||||
string_table->IteratePrefix(&marker);
|
||||
ProcessMarkingDeque();
|
||||
}
|
||||
|
||||
@ -1937,8 +1937,8 @@ void MarkCompactCollector::MarkRoots(RootMarkingVisitor* visitor) {
|
||||
// etc., and all objects reachable from them.
|
||||
heap()->IterateStrongRoots(visitor, VISIT_ONLY_STRONG);
|
||||
|
||||
// Handle the symbol table specially.
|
||||
MarkSymbolTable();
|
||||
// Handle the string table specially.
|
||||
MarkStringTable();
|
||||
|
||||
// There may be overflowed objects in the heap. Visit them now.
|
||||
while (marking_deque_.overflowed()) {
|
||||
@ -2176,19 +2176,19 @@ void MarkCompactCollector::MarkLiveObjects() {
|
||||
|
||||
|
||||
void MarkCompactCollector::AfterMarking() {
|
||||
// Object literal map caches reference symbols (cache keys) and maps
|
||||
// Object literal map caches reference strings (cache keys) and maps
|
||||
// (cache values). At this point still useful maps have already been
|
||||
// marked. Mark the keys for the alive values before we process the
|
||||
// symbol table.
|
||||
// string table.
|
||||
ProcessMapCaches();
|
||||
|
||||
// Prune the symbol table removing all symbols only pointed to by the
|
||||
// symbol table. Cannot use symbol_table() here because the symbol
|
||||
// Prune the string table removing all strings only pointed to by the
|
||||
// string table. Cannot use string_table() here because the string
|
||||
// table is marked.
|
||||
SymbolTable* symbol_table = heap()->symbol_table();
|
||||
SymbolTableCleaner v(heap());
|
||||
symbol_table->IterateElements(&v);
|
||||
symbol_table->ElementsRemoved(v.PointersRemoved());
|
||||
StringTable* string_table = heap()->string_table();
|
||||
StringTableCleaner v(heap());
|
||||
string_table->IterateElements(&v);
|
||||
string_table->ElementsRemoved(v.PointersRemoved());
|
||||
heap()->external_string_table_.Iterate(&v);
|
||||
heap()->external_string_table_.CleanUp();
|
||||
heap()->error_object_list_.RemoveUnmarked(heap());
|
||||
@ -3284,7 +3284,7 @@ void MarkCompactCollector::EvacuateNewSpaceAndCandidates() {
|
||||
// Update pointer from the native contexts list.
|
||||
updating_visitor.VisitPointer(heap_->native_contexts_list_address());
|
||||
|
||||
heap_->symbol_table()->Iterate(&updating_visitor);
|
||||
heap_->string_table()->Iterate(&updating_visitor);
|
||||
|
||||
// Update pointers from external string table.
|
||||
heap_->UpdateReferencesInExternalStringTable(
|
||||
|
@ -797,9 +797,9 @@ class MarkCompactCollector {
|
||||
// Mark the heap roots and all objects reachable from them.
|
||||
void MarkRoots(RootMarkingVisitor* visitor);
|
||||
|
||||
// Mark the symbol table specially. References to symbols from the
|
||||
// symbol table are weak.
|
||||
void MarkSymbolTable();
|
||||
// Mark the string table specially. References to internalized strings from
|
||||
// the string table are weak.
|
||||
void MarkStringTable();
|
||||
|
||||
// Mark objects in implicit references groups if their parent object
|
||||
// is marked.
|
||||
|
@ -62,7 +62,7 @@ Handle<JSMessageObject> MessageHandler::MakeMessageObject(
|
||||
Vector< Handle<Object> > args,
|
||||
Handle<String> stack_trace,
|
||||
Handle<JSArray> stack_frames) {
|
||||
Handle<String> type_handle = FACTORY->LookupUtf8Symbol(type);
|
||||
Handle<String> type_handle = FACTORY->InternalizeUtf8String(type);
|
||||
Handle<FixedArray> arguments_elements =
|
||||
FACTORY->NewFixedArray(args.length());
|
||||
for (int i = 0; i < args.length(); i++) {
|
||||
@ -157,7 +157,7 @@ Handle<String> MessageHandler::GetMessage(Isolate* isolate,
|
||||
Handle<Object> data) {
|
||||
Factory* factory = isolate->factory();
|
||||
Handle<String> fmt_str =
|
||||
factory->LookupOneByteSymbol(STATIC_ASCII_VECTOR("FormatMessage"));
|
||||
factory->InternalizeOneByteString(STATIC_ASCII_VECTOR("FormatMessage"));
|
||||
Handle<JSFunction> fun =
|
||||
Handle<JSFunction>(
|
||||
JSFunction::cast(
|
||||
@ -176,7 +176,7 @@ Handle<String> MessageHandler::GetMessage(Isolate* isolate,
|
||||
&caught_exception);
|
||||
|
||||
if (caught_exception || !result->IsString()) {
|
||||
return factory->LookupOneByteSymbol(STATIC_ASCII_VECTOR("<error>"));
|
||||
return factory->InternalizeOneByteString(STATIC_ASCII_VECTOR("<error>"));
|
||||
}
|
||||
Handle<String> result_string = Handle<String>::cast(result);
|
||||
// A string that has been obtained from JS code in this way is
|
||||
|
@ -6125,7 +6125,7 @@ void StringHelper::GenerateCopyCharactersLong(MacroAssembler* masm,
|
||||
}
|
||||
|
||||
|
||||
void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
|
||||
void StringHelper::GenerateTwoCharacterStringTableProbe(MacroAssembler* masm,
|
||||
Register c1,
|
||||
Register c2,
|
||||
Register scratch1,
|
||||
@ -6175,41 +6175,41 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
|
||||
|
||||
// Load symbol table.
|
||||
// Load address of first element of the symbol table.
|
||||
Register symbol_table = c2;
|
||||
__ LoadRoot(symbol_table, Heap::kSymbolTableRootIndex);
|
||||
Register string_table = c2;
|
||||
__ LoadRoot(string_table, Heap::kStringTableRootIndex);
|
||||
|
||||
Register undefined = scratch4;
|
||||
__ LoadRoot(undefined, Heap::kUndefinedValueRootIndex);
|
||||
|
||||
// Calculate capacity mask from the symbol table capacity.
|
||||
Register mask = scratch2;
|
||||
__ lw(mask, FieldMemOperand(symbol_table, SymbolTable::kCapacityOffset));
|
||||
__ lw(mask, FieldMemOperand(string_table, StringTable::kCapacityOffset));
|
||||
__ sra(mask, mask, 1);
|
||||
__ Addu(mask, mask, -1);
|
||||
|
||||
// Calculate untagged address of the first element of the symbol table.
|
||||
Register first_symbol_table_element = symbol_table;
|
||||
__ Addu(first_symbol_table_element, symbol_table,
|
||||
Operand(SymbolTable::kElementsStartOffset - kHeapObjectTag));
|
||||
Register first_string_table_element = string_table;
|
||||
__ Addu(first_string_table_element, string_table,
|
||||
Operand(StringTable::kElementsStartOffset - kHeapObjectTag));
|
||||
|
||||
// Registers.
|
||||
// chars: two character string, char 1 in byte 0 and char 2 in byte 1.
|
||||
// hash: hash of two character string
|
||||
// mask: capacity mask
|
||||
// first_symbol_table_element: address of the first element of
|
||||
// first_string_table_element: address of the first element of
|
||||
// the symbol table
|
||||
// undefined: the undefined object
|
||||
// scratch: -
|
||||
|
||||
// Perform a number of probes in the symbol table.
|
||||
const int kProbes = 4;
|
||||
Label found_in_symbol_table;
|
||||
Label found_in_string_table;
|
||||
Label next_probe[kProbes];
|
||||
Register candidate = scratch5; // Scratch register contains candidate.
|
||||
for (int i = 0; i < kProbes; i++) {
|
||||
// Calculate entry in symbol table.
|
||||
if (i > 0) {
|
||||
__ Addu(candidate, hash, Operand(SymbolTable::GetProbeOffset(i)));
|
||||
__ Addu(candidate, hash, Operand(StringTable::GetProbeOffset(i)));
|
||||
} else {
|
||||
__ mov(candidate, hash);
|
||||
}
|
||||
@ -6217,9 +6217,9 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
|
||||
__ And(candidate, candidate, Operand(mask));
|
||||
|
||||
// Load the entry from the symble table.
|
||||
STATIC_ASSERT(SymbolTable::kEntrySize == 1);
|
||||
STATIC_ASSERT(StringTable::kEntrySize == 1);
|
||||
__ sll(scratch, candidate, kPointerSizeLog2);
|
||||
__ Addu(scratch, scratch, first_symbol_table_element);
|
||||
__ Addu(scratch, scratch, first_string_table_element);
|
||||
__ lw(candidate, MemOperand(scratch));
|
||||
|
||||
// If entry is undefined no string with this hash can be found.
|
||||
@ -6250,7 +6250,7 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
|
||||
// Check if the two characters match.
|
||||
// Assumes that word load is little endian.
|
||||
__ lhu(scratch, FieldMemOperand(candidate, SeqOneByteString::kHeaderSize));
|
||||
__ Branch(&found_in_symbol_table, eq, chars, Operand(scratch));
|
||||
__ Branch(&found_in_string_table, eq, chars, Operand(scratch));
|
||||
__ bind(&next_probe[i]);
|
||||
}
|
||||
|
||||
@ -6259,7 +6259,7 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
|
||||
|
||||
// Scratch register contains result when we fall through to here.
|
||||
Register result = candidate;
|
||||
__ bind(&found_in_symbol_table);
|
||||
__ bind(&found_in_string_table);
|
||||
__ mov(v0, result);
|
||||
}
|
||||
|
||||
@ -6796,7 +6796,7 @@ void StringAddStub::Generate(MacroAssembler* masm) {
|
||||
// Try to lookup two character string in symbol table. If it is not found
|
||||
// just allocate a new one.
|
||||
Label make_two_character_string;
|
||||
StringHelper::GenerateTwoCharacterSymbolTableProbe(
|
||||
StringHelper::GenerateTwoCharacterStringTableProbe(
|
||||
masm, a2, a3, t2, t3, t0, t1, t5, &make_two_character_string);
|
||||
__ IncrementCounter(counters->string_add_native(), 1, a2, a3);
|
||||
__ DropAndRet(2);
|
||||
|
@ -180,7 +180,7 @@ class StringHelper : public AllStatic {
|
||||
// Contents of both c1 and c2 registers are modified. At the exit c1 is
|
||||
// guaranteed to contain halfword with low and high bytes equal to
|
||||
// initial contents of c1 and c2 respectively.
|
||||
static void GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
|
||||
static void GenerateTwoCharacterStringTableProbe(MacroAssembler* masm,
|
||||
Register c1,
|
||||
Register c2,
|
||||
Register scratch1,
|
||||
|
@ -1104,7 +1104,7 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
|
||||
!current->IsJSGlobalObject() &&
|
||||
!current->IsJSGlobalProxy()) {
|
||||
if (!name->IsSymbol()) {
|
||||
name = factory()->LookupSymbol(name);
|
||||
name = factory()->InternalizeString(name);
|
||||
}
|
||||
ASSERT(current->property_dictionary()->FindEntry(*name) ==
|
||||
StringDictionary::kNotFound);
|
||||
|
@ -469,7 +469,7 @@ void JSMessageObject::JSMessageObjectVerify() {
|
||||
void String::StringVerify() {
|
||||
CHECK(IsString());
|
||||
CHECK(length() >= 0 && length() <= Smi::kMaxValue);
|
||||
if (IsSymbol()) {
|
||||
if (IsInternalizedString()) {
|
||||
CHECK(!HEAP->InNewSpace(this));
|
||||
}
|
||||
if (IsConsString()) {
|
||||
|
@ -204,15 +204,15 @@ bool Object::IsSpecFunction() {
|
||||
}
|
||||
|
||||
|
||||
bool Object::IsSymbol() {
|
||||
bool Object::IsInternalizedString() {
|
||||
if (!this->IsHeapObject()) return false;
|
||||
uint32_t type = HeapObject::cast(this)->map()->instance_type();
|
||||
// Because the symbol tag is non-zero and no non-string types have the
|
||||
// symbol bit set we can test for symbols with a very simple test
|
||||
// operation.
|
||||
STATIC_ASSERT(kSymbolTag != 0);
|
||||
ASSERT(kNotStringTag + kIsSymbolMask > LAST_TYPE);
|
||||
return (type & kIsSymbolMask) != 0;
|
||||
// Because the internalized tag is non-zero and no non-string types have the
|
||||
// internalized bit set we can test for internalized strings with a very
|
||||
// simple test operation.
|
||||
STATIC_ASSERT(kInternalizedTag != 0);
|
||||
ASSERT(kNotStringTag + kIsInternalizedMask > LAST_TYPE);
|
||||
return (type & kIsInternalizedMask) != 0;
|
||||
}
|
||||
|
||||
|
||||
@ -293,10 +293,10 @@ StringShape::StringShape(InstanceType t)
|
||||
}
|
||||
|
||||
|
||||
bool StringShape::IsSymbol() {
|
||||
bool StringShape::IsInternalized() {
|
||||
ASSERT(valid());
|
||||
STATIC_ASSERT(kSymbolTag != 0);
|
||||
return (type_ & kIsSymbolMask) != 0;
|
||||
STATIC_ASSERT(kInternalizedTag != 0);
|
||||
return (type_ & kIsInternalizedMask) != 0;
|
||||
}
|
||||
|
||||
|
||||
@ -685,13 +685,13 @@ bool Object::IsHashTable() {
|
||||
|
||||
bool Object::IsDictionary() {
|
||||
return IsHashTable() &&
|
||||
this != HeapObject::cast(this)->GetHeap()->symbol_table();
|
||||
this != HeapObject::cast(this)->GetHeap()->string_table();
|
||||
}
|
||||
|
||||
|
||||
bool Object::IsSymbolTable() {
|
||||
bool Object::IsStringTable() {
|
||||
return IsHashTable() &&
|
||||
this == HeapObject::cast(this)->GetHeap()->raw_unchecked_symbol_table();
|
||||
this == HeapObject::cast(this)->GetHeap()->raw_unchecked_string_table();
|
||||
}
|
||||
|
||||
|
||||
@ -2358,7 +2358,7 @@ int HashTable<Shape, Key>::FindEntry(Isolate* isolate, Key key) {
|
||||
while (true) {
|
||||
Object* element = KeyAt(entry);
|
||||
// Empty entry. Uses raw unchecked accessors because it is called by the
|
||||
// symbol table during bootstrapping.
|
||||
// string table during bootstrapping.
|
||||
if (element == isolate->heap()->raw_unchecked_undefined_value()) break;
|
||||
if (element != isolate->heap()->raw_unchecked_the_hole_value() &&
|
||||
Shape::IsMatch(key, element)) return entry;
|
||||
@ -2399,7 +2399,7 @@ CAST_ACCESSOR(DeoptimizationInputData)
|
||||
CAST_ACCESSOR(DeoptimizationOutputData)
|
||||
CAST_ACCESSOR(DependentCode)
|
||||
CAST_ACCESSOR(TypeFeedbackCells)
|
||||
CAST_ACCESSOR(SymbolTable)
|
||||
CAST_ACCESSOR(StringTable)
|
||||
CAST_ACCESSOR(JSFunctionResultCache)
|
||||
CAST_ACCESSOR(NormalizedMapCache)
|
||||
CAST_ACCESSOR(ScopeInfo)
|
||||
@ -2488,7 +2488,8 @@ void String::set_hash_field(uint32_t value) {
|
||||
|
||||
bool String::Equals(String* other) {
|
||||
if (other == this) return true;
|
||||
if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
|
||||
if (StringShape(this).IsInternalized() &&
|
||||
StringShape(other).IsInternalized()) {
|
||||
return false;
|
||||
}
|
||||
return SlowEquals(other);
|
||||
@ -3217,9 +3218,10 @@ int Map::pre_allocated_property_fields() {
|
||||
int HeapObject::SizeFromMap(Map* map) {
|
||||
int instance_size = map->instance_size();
|
||||
if (instance_size != kVariableSizeSentinel) return instance_size;
|
||||
// We can ignore the "symbol" bit becase it is only set for symbols
|
||||
// and implies a string type.
|
||||
int instance_type = static_cast<int>(map->instance_type()) & ~kIsSymbolMask;
|
||||
// We can ignore the "internalized" bit becase it is only set for strings
|
||||
// and thus implies a string type.
|
||||
int instance_type =
|
||||
static_cast<int>(map->instance_type()) & ~kIsInternalizedMask;
|
||||
// Only inline the most frequent cases.
|
||||
if (instance_type == FIXED_ARRAY_TYPE) {
|
||||
return FixedArray::BodyDescriptor::SizeOf(map, this);
|
||||
|
@ -477,26 +477,32 @@ static const char* TypeToString(InstanceType type) {
|
||||
case INVALID_TYPE: return "INVALID";
|
||||
case MAP_TYPE: return "MAP";
|
||||
case HEAP_NUMBER_TYPE: return "HEAP_NUMBER";
|
||||
case SYMBOL_TYPE: return "SYMBOL";
|
||||
case ASCII_SYMBOL_TYPE: return "ASCII_SYMBOL";
|
||||
case CONS_SYMBOL_TYPE: return "CONS_SYMBOL";
|
||||
case CONS_ASCII_SYMBOL_TYPE: return "CONS_ASCII_SYMBOL";
|
||||
case EXTERNAL_ASCII_SYMBOL_TYPE:
|
||||
case EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE:
|
||||
case EXTERNAL_SYMBOL_TYPE: return "EXTERNAL_SYMBOL";
|
||||
case SHORT_EXTERNAL_ASCII_SYMBOL_TYPE:
|
||||
case SHORT_EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE:
|
||||
case SHORT_EXTERNAL_SYMBOL_TYPE: return "SHORT_EXTERNAL_SYMBOL";
|
||||
case ASCII_STRING_TYPE: return "ASCII_STRING";
|
||||
case STRING_TYPE: return "TWO_BYTE_STRING";
|
||||
case ASCII_STRING_TYPE: return "ASCII_STRING";
|
||||
case CONS_STRING_TYPE:
|
||||
case CONS_ASCII_STRING_TYPE: return "CONS_STRING";
|
||||
case CONS_ASCII_STRING_TYPE:
|
||||
return "CONS_STRING";
|
||||
case EXTERNAL_STRING_TYPE:
|
||||
case EXTERNAL_ASCII_STRING_TYPE:
|
||||
case EXTERNAL_STRING_WITH_ASCII_DATA_TYPE:
|
||||
case EXTERNAL_STRING_TYPE: return "EXTERNAL_STRING";
|
||||
return "EXTERNAL_STRING";
|
||||
case SHORT_EXTERNAL_STRING_TYPE:
|
||||
case SHORT_EXTERNAL_ASCII_STRING_TYPE:
|
||||
case SHORT_EXTERNAL_STRING_WITH_ASCII_DATA_TYPE:
|
||||
case SHORT_EXTERNAL_STRING_TYPE: return "SHORT_EXTERNAL_STRING";
|
||||
return "SHORT_EXTERNAL_STRING";
|
||||
case INTERNALIZED_STRING_TYPE: return "INTERNALIZED_STRING";
|
||||
case ASCII_INTERNALIZED_STRING_TYPE: return "ASCII_INTERNALIZED_STRING";
|
||||
case CONS_INTERNALIZED_STRING_TYPE: return "CONS_INTERNALIZED_STRING";
|
||||
case CONS_ASCII_INTERNALIZED_STRING_TYPE:
|
||||
return "CONS_ASCII_INTERNALIZED_STRING";
|
||||
case EXTERNAL_INTERNALIZED_STRING_TYPE:
|
||||
case EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE:
|
||||
case EXTERNAL_INTERNALIZED_STRING_WITH_ASCII_DATA_TYPE:
|
||||
return "EXTERNAL_INTERNALIZED_STRING";
|
||||
case SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE:
|
||||
case SHORT_EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE:
|
||||
case SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ASCII_DATA_TYPE:
|
||||
return "SHORT_EXTERNAL_INTERNALIZED_STRING";
|
||||
case FIXED_ARRAY_TYPE: return "FIXED_ARRAY";
|
||||
case BYTE_ARRAY_TYPE: return "BYTE_ARRAY";
|
||||
case FREE_SPACE_TYPE: return "FREE_SPACE";
|
||||
@ -668,7 +674,7 @@ void JSMessageObject::JSMessageObjectPrint(FILE* out) {
|
||||
|
||||
|
||||
void String::StringPrint(FILE* out) {
|
||||
if (StringShape(this).IsSymbol()) {
|
||||
if (StringShape(this).IsInternalized()) {
|
||||
PrintF(out, "#");
|
||||
} else if (StringShape(this).IsCons()) {
|
||||
PrintF(out, "c\"");
|
||||
@ -690,7 +696,7 @@ void String::StringPrint(FILE* out) {
|
||||
PrintF(out, "%s", truncated_epilogue);
|
||||
}
|
||||
|
||||
if (!StringShape(this).IsSymbol()) PrintF(out, "\"");
|
||||
if (!StringShape(this).IsInternalized()) PrintF(out, "\"");
|
||||
}
|
||||
|
||||
|
||||
|
359
src/objects.cc
359
src/objects.cc
@ -966,28 +966,33 @@ bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
|
||||
return false;
|
||||
}
|
||||
bool is_ascii = this->IsOneByteRepresentation();
|
||||
bool is_symbol = this->IsSymbol();
|
||||
bool is_internalized = this->IsInternalizedString();
|
||||
|
||||
// Morph the object to an external string by adjusting the map and
|
||||
// reinitializing the fields.
|
||||
if (size >= ExternalString::kSize) {
|
||||
this->set_map_no_write_barrier(
|
||||
is_symbol
|
||||
? (is_ascii ? heap->external_symbol_with_ascii_data_map()
|
||||
: heap->external_symbol_map())
|
||||
: (is_ascii ? heap->external_string_with_ascii_data_map()
|
||||
: heap->external_string_map()));
|
||||
is_internalized
|
||||
? (is_ascii
|
||||
? heap->external_internalized_string_with_ascii_data_map()
|
||||
: heap->external_internalized_string_map())
|
||||
: (is_ascii
|
||||
? heap->external_string_with_ascii_data_map()
|
||||
: heap->external_string_map()));
|
||||
} else {
|
||||
this->set_map_no_write_barrier(
|
||||
is_symbol
|
||||
? (is_ascii ? heap->short_external_symbol_with_ascii_data_map()
|
||||
: heap->short_external_symbol_map())
|
||||
: (is_ascii ? heap->short_external_string_with_ascii_data_map()
|
||||
: heap->short_external_string_map()));
|
||||
is_internalized
|
||||
? (is_ascii
|
||||
? heap->
|
||||
short_external_internalized_string_with_ascii_data_map()
|
||||
: heap->short_external_internalized_string_map())
|
||||
: (is_ascii
|
||||
? heap->short_external_string_with_ascii_data_map()
|
||||
: heap->short_external_string_map()));
|
||||
}
|
||||
ExternalTwoByteString* self = ExternalTwoByteString::cast(this);
|
||||
self->set_resource(resource);
|
||||
if (is_symbol) self->Hash(); // Force regeneration of the hash value.
|
||||
if (is_internalized) self->Hash(); // Force regeneration of the hash value.
|
||||
|
||||
// Fill the remainder of the string with dead wood.
|
||||
int new_size = this->Size(); // Byte size of the external String object.
|
||||
@ -1017,22 +1022,22 @@ bool String::MakeExternal(v8::String::ExternalAsciiStringResource* resource) {
|
||||
if (size < ExternalString::kShortSize) {
|
||||
return false;
|
||||
}
|
||||
bool is_symbol = this->IsSymbol();
|
||||
bool is_internalized = this->IsInternalizedString();
|
||||
|
||||
// Morph the object to an external string by adjusting the map and
|
||||
// reinitializing the fields. Use short version if space is limited.
|
||||
if (size >= ExternalString::kSize) {
|
||||
this->set_map_no_write_barrier(
|
||||
is_symbol ? heap->external_ascii_symbol_map()
|
||||
: heap->external_ascii_string_map());
|
||||
is_internalized ? heap->external_ascii_internalized_string_map()
|
||||
: heap->external_ascii_string_map());
|
||||
} else {
|
||||
this->set_map_no_write_barrier(
|
||||
is_symbol ? heap->short_external_ascii_symbol_map()
|
||||
: heap->short_external_ascii_string_map());
|
||||
is_internalized ? heap->short_external_ascii_internalized_string_map()
|
||||
: heap->short_external_ascii_string_map());
|
||||
}
|
||||
ExternalAsciiString* self = ExternalAsciiString::cast(this);
|
||||
self->set_resource(resource);
|
||||
if (is_symbol) self->Hash(); // Force regeneration of the hash value.
|
||||
if (is_internalized) self->Hash(); // Force regeneration of the hash value.
|
||||
|
||||
// Fill the remainder of the string with dead wood.
|
||||
int new_size = this->Size(); // Byte size of the external String object.
|
||||
@ -1502,14 +1507,14 @@ void HeapNumber::HeapNumberPrint(StringStream* accumulator) {
|
||||
|
||||
String* JSReceiver::class_name() {
|
||||
if (IsJSFunction() && IsJSFunctionProxy()) {
|
||||
return GetHeap()->function_class_symbol();
|
||||
return GetHeap()->function_class_string();
|
||||
}
|
||||
if (map()->constructor()->IsJSFunction()) {
|
||||
JSFunction* constructor = JSFunction::cast(map()->constructor());
|
||||
return String::cast(constructor->shared()->instance_class_name());
|
||||
}
|
||||
// If the constructor is not present, return "Object".
|
||||
return GetHeap()->Object_symbol();
|
||||
return GetHeap()->Object_string();
|
||||
}
|
||||
|
||||
|
||||
@ -1525,7 +1530,7 @@ String* JSReceiver::constructor_name() {
|
||||
}
|
||||
// TODO(rossberg): what about proxies?
|
||||
// If the constructor is not present, return "Object".
|
||||
return GetHeap()->Object_symbol();
|
||||
return GetHeap()->Object_string();
|
||||
}
|
||||
|
||||
|
||||
@ -1574,11 +1579,11 @@ MaybeObject* JSObject::AddFastProperty(String* name,
|
||||
name, map()->NumberOfOwnDescriptors()));
|
||||
|
||||
// Normalize the object if the name is an actual string (not the
|
||||
// hidden symbols) and is not a real identifier.
|
||||
// hidden strings) and is not a real identifier.
|
||||
// Normalize the object if it will have too many fast properties.
|
||||
Isolate* isolate = GetHeap()->isolate();
|
||||
if ((!IsIdentifier(isolate->unicode_cache(), name)
|
||||
&& name != isolate->heap()->hidden_symbol()) ||
|
||||
&& name != isolate->heap()->hidden_string()) ||
|
||||
(map()->unused_property_fields() == 0 &&
|
||||
TooManyFastProperties(properties()->length(), store_mode))) {
|
||||
Object* obj;
|
||||
@ -1756,7 +1761,7 @@ void JSObject::EnqueueChangeRecord(Handle<JSObject> object,
|
||||
Handle<Object> old_value) {
|
||||
Isolate* isolate = object->GetIsolate();
|
||||
HandleScope scope(isolate);
|
||||
Handle<String> type = isolate->factory()->LookupUtf8Symbol(type_str);
|
||||
Handle<String> type = isolate->factory()->InternalizeUtf8String(type_str);
|
||||
if (object->IsJSGlobalObject()) {
|
||||
object = handle(JSGlobalObject::cast(*object)->global_receiver(), isolate);
|
||||
}
|
||||
@ -2268,13 +2273,13 @@ void Map::AppendCallbackDescriptors(Handle<Map> map,
|
||||
|
||||
ASSERT(array->NumberOfSlackDescriptors() >= nof_callbacks);
|
||||
|
||||
// Ensure the keys are symbols before writing them into the instance
|
||||
// descriptor. Since it may cause a GC, it has to be done before we
|
||||
// Ensure the keys are internalized strings before writing them into the
|
||||
// instance descriptor. Since it may cause a GC, it has to be done before we
|
||||
// temporarily put the heap in an invalid state while appending descriptors.
|
||||
for (int i = 0; i < nof_callbacks; ++i) {
|
||||
Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks.get(i)));
|
||||
Handle<String> key =
|
||||
isolate->factory()->SymbolFromString(
|
||||
isolate->factory()->InternalizedStringFromString(
|
||||
Handle<String>(String::cast(entry->name())));
|
||||
entry->set_name(*key);
|
||||
}
|
||||
@ -2662,15 +2667,16 @@ MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyViaPrototypesWithHandler(
|
||||
if (has_pending_exception) return Failure::Exception();
|
||||
|
||||
// [[GetProperty]] requires to check that all properties are configurable.
|
||||
Handle<String> configurable_name = isolate->factory()->LookupOneByteSymbol(
|
||||
STATIC_ASCII_VECTOR("configurable_"));
|
||||
Handle<String> configurable_name =
|
||||
isolate->factory()->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("configurable_"));
|
||||
Handle<Object> configurable(
|
||||
v8::internal::GetProperty(isolate, desc, configurable_name));
|
||||
ASSERT(!isolate->has_pending_exception());
|
||||
ASSERT(configurable->IsTrue() || configurable->IsFalse());
|
||||
if (configurable->IsFalse()) {
|
||||
Handle<String> trap =
|
||||
isolate->factory()->LookupOneByteSymbol(
|
||||
isolate->factory()->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("getPropertyDescriptor"));
|
||||
Handle<Object> args[] = { handler, trap, name };
|
||||
Handle<Object> error = isolate->factory()->NewTypeError(
|
||||
@ -2681,7 +2687,7 @@ MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyViaPrototypesWithHandler(
|
||||
|
||||
// Check for DataDescriptor.
|
||||
Handle<String> hasWritable_name =
|
||||
isolate->factory()->LookupOneByteSymbol(
|
||||
isolate->factory()->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("hasWritable_"));
|
||||
Handle<Object> hasWritable(
|
||||
v8::internal::GetProperty(isolate, desc, hasWritable_name));
|
||||
@ -2689,7 +2695,7 @@ MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyViaPrototypesWithHandler(
|
||||
ASSERT(hasWritable->IsTrue() || hasWritable->IsFalse());
|
||||
if (hasWritable->IsTrue()) {
|
||||
Handle<String> writable_name =
|
||||
isolate->factory()->LookupOneByteSymbol(
|
||||
isolate->factory()->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("writable_"));
|
||||
Handle<Object> writable(
|
||||
v8::internal::GetProperty(isolate, desc, writable_name));
|
||||
@ -2705,7 +2711,7 @@ MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyViaPrototypesWithHandler(
|
||||
}
|
||||
|
||||
// We have an AccessorDescriptor.
|
||||
Handle<String> set_name = isolate->factory()->LookupOneByteSymbol(
|
||||
Handle<String> set_name = isolate->factory()->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("set_"));
|
||||
Handle<Object> setter(v8::internal::GetProperty(isolate, desc, set_name));
|
||||
ASSERT(!isolate->has_pending_exception());
|
||||
@ -2738,7 +2744,7 @@ MUST_USE_RESULT MaybeObject* JSProxy::DeletePropertyWithHandler(
|
||||
Object* bool_result = result->ToBoolean();
|
||||
if (mode == STRICT_DELETION && bool_result == GetHeap()->false_value()) {
|
||||
Handle<Object> handler(receiver->handler(), isolate);
|
||||
Handle<String> trap_name = isolate->factory()->LookupOneByteSymbol(
|
||||
Handle<String> trap_name = isolate->factory()->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("delete"));
|
||||
Handle<Object> args[] = { handler, trap_name };
|
||||
Handle<Object> error = isolate->factory()->NewTypeError(
|
||||
@ -2785,21 +2791,21 @@ MUST_USE_RESULT PropertyAttributes JSProxy::GetPropertyAttributeWithHandler(
|
||||
if (has_pending_exception) return NONE;
|
||||
|
||||
// Convert result to PropertyAttributes.
|
||||
Handle<String> enum_n = isolate->factory()->LookupOneByteSymbol(
|
||||
Handle<String> enum_n = isolate->factory()->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("enumerable"));
|
||||
Handle<Object> enumerable(v8::internal::GetProperty(isolate, desc, enum_n));
|
||||
if (isolate->has_pending_exception()) return NONE;
|
||||
Handle<String> conf_n = isolate->factory()->LookupOneByteSymbol(
|
||||
Handle<String> conf_n = isolate->factory()->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("configurable"));
|
||||
Handle<Object> configurable(v8::internal::GetProperty(isolate, desc, conf_n));
|
||||
if (isolate->has_pending_exception()) return NONE;
|
||||
Handle<String> writ_n = isolate->factory()->LookupOneByteSymbol(
|
||||
Handle<String> writ_n = isolate->factory()->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("writable"));
|
||||
Handle<Object> writable(v8::internal::GetProperty(isolate, desc, writ_n));
|
||||
if (isolate->has_pending_exception()) return NONE;
|
||||
|
||||
if (configurable->IsFalse()) {
|
||||
Handle<String> trap = isolate->factory()->LookupOneByteSymbol(
|
||||
Handle<String> trap = isolate->factory()->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("getPropertyDescriptor"));
|
||||
Handle<Object> args[] = { handler, trap, name };
|
||||
Handle<Object> error = isolate->factory()->NewTypeError(
|
||||
@ -2860,7 +2866,7 @@ MUST_USE_RESULT Handle<Object> JSProxy::CallTrap(const char* name,
|
||||
Isolate* isolate = GetIsolate();
|
||||
Handle<Object> handler(this->handler(), isolate);
|
||||
|
||||
Handle<String> trap_name = isolate->factory()->LookupUtf8Symbol(name);
|
||||
Handle<String> trap_name = isolate->factory()->InternalizeUtf8String(name);
|
||||
Handle<Object> trap(v8::internal::GetProperty(isolate, handler, trap_name));
|
||||
if (isolate->has_pending_exception()) return trap;
|
||||
|
||||
@ -2901,13 +2907,13 @@ MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup,
|
||||
AssertNoContextChange ncc;
|
||||
|
||||
// Optimization for 2-byte strings often used as keys in a decompression
|
||||
// dictionary. We make these short keys into symbols to avoid constantly
|
||||
// dictionary. We internalize these short keys to avoid constantly
|
||||
// reallocating them.
|
||||
if (!name_raw->IsSymbol() && name_raw->length() <= 2) {
|
||||
Object* symbol_version;
|
||||
{ MaybeObject* maybe_symbol_version = heap->LookupSymbol(name_raw);
|
||||
if (maybe_symbol_version->ToObject(&symbol_version)) {
|
||||
name_raw = String::cast(symbol_version);
|
||||
if (!name_raw->IsInternalizedString() && name_raw->length() <= 2) {
|
||||
Object* internalized_version;
|
||||
{ MaybeObject* maybe_string_version = heap->InternalizeString(name_raw);
|
||||
if (maybe_string_version->ToObject(&internalized_version)) {
|
||||
name_raw = String::cast(internalized_version);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3780,7 +3786,7 @@ Smi* JSReceiver::GenerateIdentityHash() {
|
||||
|
||||
|
||||
MaybeObject* JSObject::SetIdentityHash(Smi* hash, CreationFlag flag) {
|
||||
MaybeObject* maybe = SetHiddenProperty(GetHeap()->identity_hash_symbol(),
|
||||
MaybeObject* maybe = SetHiddenProperty(GetHeap()->identity_hash_string(),
|
||||
hash);
|
||||
if (maybe->IsFailure()) return maybe;
|
||||
return this;
|
||||
@ -3796,14 +3802,14 @@ int JSObject::GetIdentityHash(Handle<JSObject> obj) {
|
||||
|
||||
|
||||
MaybeObject* JSObject::GetIdentityHash(CreationFlag flag) {
|
||||
Object* stored_value = GetHiddenProperty(GetHeap()->identity_hash_symbol());
|
||||
Object* stored_value = GetHiddenProperty(GetHeap()->identity_hash_string());
|
||||
if (stored_value->IsSmi()) return stored_value;
|
||||
|
||||
// Do not generate permanent identity hash code if not requested.
|
||||
if (flag == OMIT_CREATION) return GetHeap()->undefined_value();
|
||||
|
||||
Smi* hash = GenerateIdentityHash();
|
||||
MaybeObject* result = SetHiddenProperty(GetHeap()->identity_hash_symbol(),
|
||||
MaybeObject* result = SetHiddenProperty(GetHeap()->identity_hash_string(),
|
||||
hash);
|
||||
if (result->IsFailure()) return result;
|
||||
if (result->ToObjectUnchecked()->IsUndefined()) {
|
||||
@ -3825,7 +3831,7 @@ MaybeObject* JSProxy::GetIdentityHash(CreationFlag flag) {
|
||||
|
||||
|
||||
Object* JSObject::GetHiddenProperty(String* key) {
|
||||
ASSERT(key->IsSymbol());
|
||||
ASSERT(key->IsInternalizedString());
|
||||
if (IsJSGlobalProxy()) {
|
||||
// For a proxy, use the prototype as target object.
|
||||
Object* proxy_parent = GetPrototype();
|
||||
@ -3841,7 +3847,7 @@ Object* JSObject::GetHiddenProperty(String* key) {
|
||||
|
||||
if (inline_value->IsSmi()) {
|
||||
// Handle inline-stored identity hash.
|
||||
if (key == GetHeap()->identity_hash_symbol()) {
|
||||
if (key == GetHeap()->identity_hash_string()) {
|
||||
return inline_value;
|
||||
} else {
|
||||
return GetHeap()->undefined_value();
|
||||
@ -3867,7 +3873,7 @@ Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> obj,
|
||||
|
||||
|
||||
MaybeObject* JSObject::SetHiddenProperty(String* key, Object* value) {
|
||||
ASSERT(key->IsSymbol());
|
||||
ASSERT(key->IsInternalizedString());
|
||||
if (IsJSGlobalProxy()) {
|
||||
// For a proxy, use the prototype as target object.
|
||||
Object* proxy_parent = GetPrototype();
|
||||
@ -3883,7 +3889,7 @@ MaybeObject* JSObject::SetHiddenProperty(String* key, Object* value) {
|
||||
|
||||
// If there is no backing store yet, store the identity hash inline.
|
||||
if (value->IsSmi() &&
|
||||
key == GetHeap()->identity_hash_symbol() &&
|
||||
key == GetHeap()->identity_hash_string() &&
|
||||
(inline_value->IsUndefined() || inline_value->IsSmi())) {
|
||||
return SetHiddenPropertiesHashTable(value);
|
||||
}
|
||||
@ -3908,7 +3914,7 @@ MaybeObject* JSObject::SetHiddenProperty(String* key, Object* value) {
|
||||
|
||||
|
||||
void JSObject::DeleteHiddenProperty(String* key) {
|
||||
ASSERT(key->IsSymbol());
|
||||
ASSERT(key->IsInternalizedString());
|
||||
if (IsJSGlobalProxy()) {
|
||||
// For a proxy, use the prototype as target object.
|
||||
Object* proxy_parent = GetPrototype();
|
||||
@ -3924,7 +3930,7 @@ void JSObject::DeleteHiddenProperty(String* key) {
|
||||
Object* inline_value = hidden_lookup->ToObjectUnchecked();
|
||||
|
||||
// We never delete (inline-stored) identity hashes.
|
||||
ASSERT(key != GetHeap()->identity_hash_symbol());
|
||||
ASSERT(key != GetHeap()->identity_hash_string());
|
||||
if (inline_value->IsUndefined() || inline_value->IsSmi()) return;
|
||||
|
||||
ObjectHashTable* hashtable = ObjectHashTable::cast(inline_value);
|
||||
@ -3936,7 +3942,7 @@ void JSObject::DeleteHiddenProperty(String* key) {
|
||||
|
||||
bool JSObject::HasHiddenProperties() {
|
||||
return GetPropertyAttributePostInterceptor(this,
|
||||
GetHeap()->hidden_symbol(),
|
||||
GetHeap()->hidden_string(),
|
||||
false) != ABSENT;
|
||||
}
|
||||
|
||||
@ -3947,13 +3953,13 @@ MaybeObject* JSObject::GetHiddenPropertiesHashTable(
|
||||
Object* inline_value;
|
||||
if (HasFastProperties()) {
|
||||
// If the object has fast properties, check whether the first slot
|
||||
// in the descriptor array matches the hidden symbol. Since the
|
||||
// hidden symbols hash code is zero (and no other string has hash
|
||||
// in the descriptor array matches the hidden string. Since the
|
||||
// hidden strings hash code is zero (and no other string has hash
|
||||
// code zero) it will always occupy the first entry if present.
|
||||
DescriptorArray* descriptors = this->map()->instance_descriptors();
|
||||
if (descriptors->number_of_descriptors() > 0) {
|
||||
int sorted_index = descriptors->GetSortedKeyIndex(0);
|
||||
if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_symbol() &&
|
||||
if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_string() &&
|
||||
sorted_index < map()->NumberOfOwnDescriptors()) {
|
||||
ASSERT(descriptors->GetType(sorted_index) == FIELD);
|
||||
inline_value =
|
||||
@ -3966,12 +3972,12 @@ MaybeObject* JSObject::GetHiddenPropertiesHashTable(
|
||||
}
|
||||
} else {
|
||||
PropertyAttributes attributes;
|
||||
// You can't install a getter on a property indexed by the hidden symbol,
|
||||
// You can't install a getter on a property indexed by the hidden string,
|
||||
// so we can be sure that GetLocalPropertyPostInterceptor returns a real
|
||||
// object.
|
||||
inline_value =
|
||||
GetLocalPropertyPostInterceptor(this,
|
||||
GetHeap()->hidden_symbol(),
|
||||
GetHeap()->hidden_string(),
|
||||
&attributes)->ToObjectUnchecked();
|
||||
}
|
||||
|
||||
@ -3991,7 +3997,7 @@ MaybeObject* JSObject::GetHiddenPropertiesHashTable(
|
||||
// We were storing the identity hash inline and now allocated an actual
|
||||
// dictionary. Put the identity hash into the new dictionary.
|
||||
MaybeObject* insert_result =
|
||||
hashtable->Put(GetHeap()->identity_hash_symbol(), inline_value);
|
||||
hashtable->Put(GetHeap()->identity_hash_string(), inline_value);
|
||||
ObjectHashTable* new_table;
|
||||
if (!insert_result->To(&new_table)) return insert_result;
|
||||
// We expect no resizing for the first insert.
|
||||
@ -3999,7 +4005,7 @@ MaybeObject* JSObject::GetHiddenPropertiesHashTable(
|
||||
}
|
||||
|
||||
MaybeObject* store_result =
|
||||
SetPropertyPostInterceptor(GetHeap()->hidden_symbol(),
|
||||
SetPropertyPostInterceptor(GetHeap()->hidden_string(),
|
||||
hashtable,
|
||||
DONT_ENUM,
|
||||
kNonStrictMode,
|
||||
@ -4016,13 +4022,13 @@ MaybeObject* JSObject::SetHiddenPropertiesHashTable(Object* value) {
|
||||
ASSERT(HasHiddenProperties() != value->IsSmi());
|
||||
if (HasFastProperties()) {
|
||||
// If the object has fast properties, check whether the first slot
|
||||
// in the descriptor array matches the hidden symbol. Since the
|
||||
// hidden symbols hash code is zero (and no other string has hash
|
||||
// in the descriptor array matches the hidden string. Since the
|
||||
// hidden strings hash code is zero (and no other string has hash
|
||||
// code zero) it will always occupy the first entry if present.
|
||||
DescriptorArray* descriptors = this->map()->instance_descriptors();
|
||||
if (descriptors->number_of_descriptors() > 0) {
|
||||
int sorted_index = descriptors->GetSortedKeyIndex(0);
|
||||
if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_symbol() &&
|
||||
if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_string() &&
|
||||
sorted_index < map()->NumberOfOwnDescriptors()) {
|
||||
ASSERT(descriptors->GetType(sorted_index) == FIELD);
|
||||
this->FastPropertyAtPut(descriptors->GetFieldIndex(sorted_index),
|
||||
@ -4032,7 +4038,7 @@ MaybeObject* JSObject::SetHiddenPropertiesHashTable(Object* value) {
|
||||
}
|
||||
}
|
||||
MaybeObject* store_result =
|
||||
SetPropertyPostInterceptor(GetHeap()->hidden_symbol(),
|
||||
SetPropertyPostInterceptor(GetHeap()->hidden_string(),
|
||||
value,
|
||||
DONT_ENUM,
|
||||
kNonStrictMode,
|
||||
@ -5492,8 +5498,8 @@ MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor,
|
||||
TransitionFlag flag) {
|
||||
DescriptorArray* descriptors = instance_descriptors();
|
||||
|
||||
// Ensure the key is a symbol.
|
||||
MaybeObject* maybe_failure = descriptor->KeyToSymbol();
|
||||
// Ensure the key is an internalized string.
|
||||
MaybeObject* maybe_failure = descriptor->KeyToInternalizedString();
|
||||
if (maybe_failure->IsFailure()) return maybe_failure;
|
||||
|
||||
int old_size = NumberOfOwnDescriptors();
|
||||
@ -5536,8 +5542,8 @@ MaybeObject* Map::CopyInsertDescriptor(Descriptor* descriptor,
|
||||
TransitionFlag flag) {
|
||||
DescriptorArray* old_descriptors = instance_descriptors();
|
||||
|
||||
// Ensure the key is a symbol.
|
||||
MaybeObject* maybe_result = descriptor->KeyToSymbol();
|
||||
// Ensure the key is an internalized string.
|
||||
MaybeObject* maybe_result = descriptor->KeyToInternalizedString();
|
||||
if (maybe_result->IsFailure()) return maybe_result;
|
||||
|
||||
// We replace the key if it is already present.
|
||||
@ -5573,8 +5579,8 @@ MaybeObject* Map::CopyReplaceDescriptor(DescriptorArray* descriptors,
|
||||
Descriptor* descriptor,
|
||||
int insertion_index,
|
||||
TransitionFlag flag) {
|
||||
// Ensure the key is a symbol.
|
||||
MaybeObject* maybe_failure = descriptor->KeyToSymbol();
|
||||
// Ensure the key is an internalized string.
|
||||
MaybeObject* maybe_failure = descriptor->KeyToInternalizedString();
|
||||
if (maybe_failure->IsFailure()) return maybe_failure;
|
||||
|
||||
String* key = descriptor->GetKey();
|
||||
@ -7266,7 +7272,7 @@ bool String::SlowEquals(String* other) {
|
||||
|
||||
|
||||
bool String::MarkAsUndetectable() {
|
||||
if (StringShape(this).IsSymbol()) return false;
|
||||
if (StringShape(this).IsInternalized()) return false;
|
||||
|
||||
Map* map = this->map();
|
||||
Heap* heap = GetHeap();
|
||||
@ -8090,12 +8096,13 @@ Context* JSFunction::NativeContextFromLiterals(FixedArray* literals) {
|
||||
MaybeObject* Oddball::Initialize(const char* to_string,
|
||||
Object* to_number,
|
||||
byte kind) {
|
||||
String* symbol;
|
||||
{ MaybeObject* maybe_symbol =
|
||||
Isolate::Current()->heap()->LookupUtf8Symbol(CStrVector(to_string));
|
||||
if (!maybe_symbol->To(&symbol)) return maybe_symbol;
|
||||
String* internalized_to_string;
|
||||
{ MaybeObject* maybe_string =
|
||||
Isolate::Current()->heap()->InternalizeUtf8String(
|
||||
CStrVector(to_string));
|
||||
if (!maybe_string->To(&internalized_to_string)) return maybe_string;
|
||||
}
|
||||
set_to_string(symbol);
|
||||
set_to_string(internalized_to_string);
|
||||
set_to_number(to_number);
|
||||
set_kind(kind);
|
||||
return this;
|
||||
@ -9424,7 +9431,7 @@ MaybeObject* JSArray::SetElementsLength(Object* len) {
|
||||
self, "deleted", indices[i], old_values[i]);
|
||||
}
|
||||
JSObject::EnqueueChangeRecord(
|
||||
self, "updated", isolate->factory()->length_symbol(),
|
||||
self, "updated", isolate->factory()->length_string(),
|
||||
old_length_handle);
|
||||
}
|
||||
return *hresult;
|
||||
@ -10460,7 +10467,7 @@ MaybeObject* JSObject::SetElement(uint32_t index,
|
||||
if (self->IsJSArray() &&
|
||||
!old_length->SameValue(Handle<JSArray>::cast(self)->length())) {
|
||||
EnqueueChangeRecord(
|
||||
self, "updated", isolate->factory()->length_symbol(), old_length);
|
||||
self, "updated", isolate->factory()->length_string(), old_length);
|
||||
}
|
||||
} else if (old_value->IsTheHole()) {
|
||||
EnqueueChangeRecord(self, "reconfigured", name, old_value);
|
||||
@ -11642,10 +11649,10 @@ class RegExpKey : public HashTableKey {
|
||||
Smi* flags_;
|
||||
};
|
||||
|
||||
// Utf8SymbolKey carries a vector of chars as key.
|
||||
class Utf8SymbolKey : public HashTableKey {
|
||||
// Utf8StringKey carries a vector of chars as key.
|
||||
class Utf8StringKey : public HashTableKey {
|
||||
public:
|
||||
explicit Utf8SymbolKey(Vector<const char> string, uint32_t seed)
|
||||
explicit Utf8StringKey(Vector<const char> string, uint32_t seed)
|
||||
: string_(string), hash_field_(0), seed_(seed) { }
|
||||
|
||||
bool IsMatch(Object* string) {
|
||||
@ -11666,7 +11673,7 @@ class Utf8SymbolKey : public HashTableKey {
|
||||
|
||||
MaybeObject* AsObject() {
|
||||
if (hash_field_ == 0) Hash();
|
||||
return Isolate::Current()->heap()->AllocateSymbolFromUtf8(
|
||||
return Isolate::Current()->heap()->AllocateInternalizedStringFromUtf8(
|
||||
string_, chars_, hash_field_);
|
||||
}
|
||||
|
||||
@ -11678,9 +11685,9 @@ class Utf8SymbolKey : public HashTableKey {
|
||||
|
||||
|
||||
template <typename Char>
|
||||
class SequentialSymbolKey : public HashTableKey {
|
||||
class SequentialStringKey : public HashTableKey {
|
||||
public:
|
||||
explicit SequentialSymbolKey(Vector<const Char> string, uint32_t seed)
|
||||
explicit SequentialStringKey(Vector<const Char> string, uint32_t seed)
|
||||
: string_(string), hash_field_(0), seed_(seed) { }
|
||||
|
||||
uint32_t Hash() {
|
||||
@ -11705,10 +11712,10 @@ class SequentialSymbolKey : public HashTableKey {
|
||||
|
||||
|
||||
|
||||
class OneByteSymbolKey : public SequentialSymbolKey<uint8_t> {
|
||||
class OneByteStringKey : public SequentialStringKey<uint8_t> {
|
||||
public:
|
||||
OneByteSymbolKey(Vector<const uint8_t> str, uint32_t seed)
|
||||
: SequentialSymbolKey<uint8_t>(str, seed) { }
|
||||
OneByteStringKey(Vector<const uint8_t> str, uint32_t seed)
|
||||
: SequentialStringKey<uint8_t>(str, seed) { }
|
||||
|
||||
bool IsMatch(Object* string) {
|
||||
return String::cast(string)->IsOneByteEqualTo(string_);
|
||||
@ -11716,16 +11723,16 @@ class OneByteSymbolKey : public SequentialSymbolKey<uint8_t> {
|
||||
|
||||
MaybeObject* AsObject() {
|
||||
if (hash_field_ == 0) Hash();
|
||||
return HEAP->AllocateOneByteSymbol(string_, hash_field_);
|
||||
return HEAP->AllocateOneByteInternalizedString(string_, hash_field_);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class SubStringOneByteSymbolKey : public HashTableKey {
|
||||
class SubStringOneByteStringKey : public HashTableKey {
|
||||
public:
|
||||
explicit SubStringOneByteSymbolKey(Handle<SeqOneByteString> string,
|
||||
int from,
|
||||
int length)
|
||||
explicit SubStringOneByteStringKey(Handle<SeqOneByteString> string,
|
||||
int from,
|
||||
int length)
|
||||
: string_(string), from_(from), length_(length) { }
|
||||
|
||||
uint32_t Hash() {
|
||||
@ -11752,7 +11759,7 @@ class SubStringOneByteSymbolKey : public HashTableKey {
|
||||
MaybeObject* AsObject() {
|
||||
if (hash_field_ == 0) Hash();
|
||||
Vector<const uint8_t> chars(string_->GetChars() + from_, length_);
|
||||
return HEAP->AllocateOneByteSymbol(chars, hash_field_);
|
||||
return HEAP->AllocateOneByteInternalizedString(chars, hash_field_);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -11763,10 +11770,10 @@ class SubStringOneByteSymbolKey : public HashTableKey {
|
||||
};
|
||||
|
||||
|
||||
class TwoByteSymbolKey : public SequentialSymbolKey<uc16> {
|
||||
class TwoByteStringKey : public SequentialStringKey<uc16> {
|
||||
public:
|
||||
explicit TwoByteSymbolKey(Vector<const uc16> str, uint32_t seed)
|
||||
: SequentialSymbolKey<uc16>(str, seed) { }
|
||||
explicit TwoByteStringKey(Vector<const uc16> str, uint32_t seed)
|
||||
: SequentialStringKey<uc16>(str, seed) { }
|
||||
|
||||
bool IsMatch(Object* string) {
|
||||
return String::cast(string)->IsTwoByteEqualTo(string_);
|
||||
@ -11774,15 +11781,15 @@ class TwoByteSymbolKey : public SequentialSymbolKey<uc16> {
|
||||
|
||||
MaybeObject* AsObject() {
|
||||
if (hash_field_ == 0) Hash();
|
||||
return HEAP->AllocateTwoByteSymbol(string_, hash_field_);
|
||||
return HEAP->AllocateTwoByteInternalizedString(string_, hash_field_);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// SymbolKey carries a string/symbol object as key.
|
||||
class SymbolKey : public HashTableKey {
|
||||
// InternalizedStringKey carries a string/internalized-string object as key.
|
||||
class InternalizedStringKey : public HashTableKey {
|
||||
public:
|
||||
explicit SymbolKey(String* string)
|
||||
explicit InternalizedStringKey(String* string)
|
||||
: string_(string) { }
|
||||
|
||||
bool IsMatch(Object* string) {
|
||||
@ -11796,21 +11803,20 @@ class SymbolKey : public HashTableKey {
|
||||
}
|
||||
|
||||
MaybeObject* AsObject() {
|
||||
// Attempt to flatten the string, so that symbols will most often
|
||||
// be flat strings.
|
||||
// Attempt to flatten the string, so that internalized strings will most
|
||||
// often be flat strings.
|
||||
string_ = string_->TryFlattenGetString();
|
||||
Heap* heap = string_->GetHeap();
|
||||
// Transform string to symbol if possible.
|
||||
Map* map = heap->SymbolMapForString(string_);
|
||||
// Internalize the string if possible.
|
||||
Map* map = heap->InternalizedStringMapForString(string_);
|
||||
if (map != NULL) {
|
||||
string_->set_map_no_write_barrier(map);
|
||||
ASSERT(string_->IsSymbol());
|
||||
ASSERT(string_->IsInternalizedString());
|
||||
return string_;
|
||||
}
|
||||
// Otherwise allocate a new symbol.
|
||||
return heap->AllocateInternalSymbol(string_,
|
||||
string_->length(),
|
||||
string_->hash_field());
|
||||
// Otherwise allocate a new internalized string.
|
||||
return heap->AllocateInternalizedStringImpl(
|
||||
string_, string_->length(), string_->hash_field());
|
||||
}
|
||||
|
||||
static uint32_t StringHash(Object* obj) {
|
||||
@ -11861,18 +11867,18 @@ MaybeObject* HashTable<Shape, Key>::Allocate(int at_least_space_for,
|
||||
|
||||
// Find entry for key otherwise return kNotFound.
|
||||
int StringDictionary::FindEntry(String* key) {
|
||||
if (!key->IsSymbol()) {
|
||||
if (!key->IsInternalizedString()) {
|
||||
return HashTable<StringDictionaryShape, String*>::FindEntry(key);
|
||||
}
|
||||
|
||||
// Optimized for symbol key. Knowledge of the key type allows:
|
||||
// 1. Move the check if the key is a symbol out of the loop.
|
||||
// 2. Avoid comparing hash codes in symbol to symbol comparison.
|
||||
// 3. Detect a case when a dictionary key is not a symbol but the key is.
|
||||
// In case of positive result the dictionary key may be replaced by
|
||||
// the symbol with minimal performance penalty. It gives a chance to
|
||||
// perform further lookups in code stubs (and significant performance boost
|
||||
// a certain style of code).
|
||||
// Optimized for internalized string key. Knowledge of the key type allows:
|
||||
// 1. Move the check if the key is internalized out of the loop.
|
||||
// 2. Avoid comparing hash codes in internalized-to-internalized comparison.
|
||||
// 3. Detect a case when a dictionary key is not internalized but the key is.
|
||||
// In case of positive result the dictionary key may be replaced by the
|
||||
// internalized string with minimal performance penalty. It gives a chance
|
||||
// to perform further lookups in code stubs (and significant performance
|
||||
// boost a certain style of code).
|
||||
|
||||
// EnsureCapacity will guarantee the hash table is never full.
|
||||
uint32_t capacity = Capacity();
|
||||
@ -11884,11 +11890,11 @@ int StringDictionary::FindEntry(String* key) {
|
||||
Object* element = get(index);
|
||||
if (element->IsUndefined()) break; // Empty entry.
|
||||
if (key == element) return entry;
|
||||
if (!element->IsSymbol() &&
|
||||
if (!element->IsInternalizedString() &&
|
||||
!element->IsTheHole() &&
|
||||
String::cast(element)->Equals(key)) {
|
||||
// Replace a non-symbol key by the equivalent symbol for faster further
|
||||
// lookups.
|
||||
// Replace a key that is not an internalized string by the equivalent
|
||||
// internalized string for faster further lookups.
|
||||
set(index, key);
|
||||
return entry;
|
||||
}
|
||||
@ -12009,7 +12015,7 @@ uint32_t HashTable<Shape, Key>::FindInsertionEntry(uint32_t hash) {
|
||||
// Force instantiation of template instances class.
|
||||
// Please note this list is compiler dependent.
|
||||
|
||||
template class HashTable<SymbolTableShape, HashTableKey*>;
|
||||
template class HashTable<StringTableShape, HashTableKey*>;
|
||||
|
||||
template class HashTable<CompilationCacheShape, HashTableKey*>;
|
||||
|
||||
@ -12566,13 +12572,13 @@ MaybeObject* GlobalObject::EnsurePropertyCell(String* name) {
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* SymbolTable::LookupString(String* string, Object** s) {
|
||||
SymbolKey key(string);
|
||||
MaybeObject* StringTable::LookupString(String* string, Object** s) {
|
||||
InternalizedStringKey key(string);
|
||||
return LookupKey(&key, s);
|
||||
}
|
||||
|
||||
|
||||
// This class is used for looking up two character strings in the symbol table.
|
||||
// This class is used for looking up two character strings in the string table.
|
||||
// If we don't have a hit we don't want to waste much time so we unroll the
|
||||
// string hash calculation loop here for speed. Doesn't work if the two
|
||||
// characters form a decimal integer, since such strings have a different hash
|
||||
@ -12623,7 +12629,7 @@ class TwoCharHashTableKey : public HashTableKey {
|
||||
}
|
||||
|
||||
Object* AsObject() {
|
||||
// The TwoCharHashTableKey is only used for looking in the symbol
|
||||
// The TwoCharHashTableKey is only used for looking in the string
|
||||
// table, not for adding to it.
|
||||
UNREACHABLE();
|
||||
return NULL;
|
||||
@ -12636,97 +12642,95 @@ class TwoCharHashTableKey : public HashTableKey {
|
||||
};
|
||||
|
||||
|
||||
bool SymbolTable::LookupSymbolIfExists(String* string, String** symbol) {
|
||||
SymbolKey key(string);
|
||||
bool StringTable::LookupStringIfExists(String* string, String** result) {
|
||||
InternalizedStringKey key(string);
|
||||
int entry = FindEntry(&key);
|
||||
if (entry == kNotFound) {
|
||||
return false;
|
||||
} else {
|
||||
String* result = String::cast(KeyAt(entry));
|
||||
ASSERT(StringShape(result).IsSymbol());
|
||||
*symbol = result;
|
||||
*result = String::cast(KeyAt(entry));
|
||||
ASSERT(StringShape(*result).IsInternalized());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool SymbolTable::LookupTwoCharsSymbolIfExists(uint16_t c1,
|
||||
bool StringTable::LookupTwoCharsStringIfExists(uint16_t c1,
|
||||
uint16_t c2,
|
||||
String** symbol) {
|
||||
String** result) {
|
||||
TwoCharHashTableKey key(c1, c2, GetHeap()->HashSeed());
|
||||
int entry = FindEntry(&key);
|
||||
if (entry == kNotFound) {
|
||||
return false;
|
||||
} else {
|
||||
String* result = String::cast(KeyAt(entry));
|
||||
ASSERT(StringShape(result).IsSymbol());
|
||||
*symbol = result;
|
||||
*result = String::cast(KeyAt(entry));
|
||||
ASSERT(StringShape(*result).IsInternalized());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* SymbolTable::LookupUtf8Symbol(Vector<const char> str,
|
||||
MaybeObject* StringTable::LookupUtf8String(Vector<const char> str,
|
||||
Object** s) {
|
||||
Utf8SymbolKey key(str, GetHeap()->HashSeed());
|
||||
Utf8StringKey key(str, GetHeap()->HashSeed());
|
||||
return LookupKey(&key, s);
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* SymbolTable::LookupOneByteSymbol(Vector<const uint8_t> str,
|
||||
MaybeObject* StringTable::LookupOneByteString(Vector<const uint8_t> str,
|
||||
Object** s) {
|
||||
OneByteSymbolKey key(str, GetHeap()->HashSeed());
|
||||
OneByteStringKey key(str, GetHeap()->HashSeed());
|
||||
return LookupKey(&key, s);
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* SymbolTable::LookupSubStringOneByteSymbol(
|
||||
MaybeObject* StringTable::LookupSubStringOneByteString(
|
||||
Handle<SeqOneByteString> str,
|
||||
int from,
|
||||
int length,
|
||||
Object** s) {
|
||||
SubStringOneByteSymbolKey key(str, from, length);
|
||||
SubStringOneByteStringKey key(str, from, length);
|
||||
return LookupKey(&key, s);
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* SymbolTable::LookupTwoByteSymbol(Vector<const uc16> str,
|
||||
MaybeObject* StringTable::LookupTwoByteString(Vector<const uc16> str,
|
||||
Object** s) {
|
||||
TwoByteSymbolKey key(str, GetHeap()->HashSeed());
|
||||
TwoByteStringKey key(str, GetHeap()->HashSeed());
|
||||
return LookupKey(&key, s);
|
||||
}
|
||||
|
||||
MaybeObject* SymbolTable::LookupKey(HashTableKey* key, Object** s) {
|
||||
MaybeObject* StringTable::LookupKey(HashTableKey* key, Object** s) {
|
||||
int entry = FindEntry(key);
|
||||
|
||||
// Symbol already in table.
|
||||
// String already in table.
|
||||
if (entry != kNotFound) {
|
||||
*s = KeyAt(entry);
|
||||
return this;
|
||||
}
|
||||
|
||||
// Adding new symbol. Grow table if needed.
|
||||
// Adding new string. Grow table if needed.
|
||||
Object* obj;
|
||||
{ MaybeObject* maybe_obj = EnsureCapacity(1, key);
|
||||
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
|
||||
}
|
||||
|
||||
// Create symbol object.
|
||||
Object* symbol;
|
||||
{ MaybeObject* maybe_symbol = key->AsObject();
|
||||
if (!maybe_symbol->ToObject(&symbol)) return maybe_symbol;
|
||||
// Create string object.
|
||||
Object* string;
|
||||
{ MaybeObject* maybe_string = key->AsObject();
|
||||
if (!maybe_string->ToObject(&string)) return maybe_string;
|
||||
}
|
||||
|
||||
// If the symbol table grew as part of EnsureCapacity, obj is not
|
||||
// the current symbol table and therefore we cannot use
|
||||
// SymbolTable::cast here.
|
||||
SymbolTable* table = reinterpret_cast<SymbolTable*>(obj);
|
||||
// If the string table grew as part of EnsureCapacity, obj is not
|
||||
// the current string table and therefore we cannot use
|
||||
// StringTable::cast here.
|
||||
StringTable* table = reinterpret_cast<StringTable*>(obj);
|
||||
|
||||
// Add the new symbol and return it along with the symbol table.
|
||||
// Add the new string and return it along with the string table.
|
||||
entry = table->FindInsertionEntry(key->Hash());
|
||||
table->set(EntryToIndex(entry), symbol);
|
||||
table->set(EntryToIndex(entry), string);
|
||||
table->ElementAdded();
|
||||
*s = symbol;
|
||||
*s = string;
|
||||
return table;
|
||||
}
|
||||
|
||||
@ -12866,42 +12870,42 @@ void CompilationCacheTable::Remove(Object* value) {
|
||||
}
|
||||
|
||||
|
||||
// SymbolsKey used for HashTable where key is array of symbols.
|
||||
class SymbolsKey : public HashTableKey {
|
||||
// StringsKey used for HashTable where key is array of internalzied strings.
|
||||
class StringsKey : public HashTableKey {
|
||||
public:
|
||||
explicit SymbolsKey(FixedArray* symbols) : symbols_(symbols) { }
|
||||
explicit StringsKey(FixedArray* strings) : strings_(strings) { }
|
||||
|
||||
bool IsMatch(Object* symbols) {
|
||||
FixedArray* o = FixedArray::cast(symbols);
|
||||
int len = symbols_->length();
|
||||
bool IsMatch(Object* strings) {
|
||||
FixedArray* o = FixedArray::cast(strings);
|
||||
int len = strings_->length();
|
||||
if (o->length() != len) return false;
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (o->get(i) != symbols_->get(i)) return false;
|
||||
if (o->get(i) != strings_->get(i)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t Hash() { return HashForObject(symbols_); }
|
||||
uint32_t Hash() { return HashForObject(strings_); }
|
||||
|
||||
uint32_t HashForObject(Object* obj) {
|
||||
FixedArray* symbols = FixedArray::cast(obj);
|
||||
int len = symbols->length();
|
||||
FixedArray* strings = FixedArray::cast(obj);
|
||||
int len = strings->length();
|
||||
uint32_t hash = 0;
|
||||
for (int i = 0; i < len; i++) {
|
||||
hash ^= String::cast(symbols->get(i))->Hash();
|
||||
hash ^= String::cast(strings->get(i))->Hash();
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
Object* AsObject() { return symbols_; }
|
||||
Object* AsObject() { return strings_; }
|
||||
|
||||
private:
|
||||
FixedArray* symbols_;
|
||||
FixedArray* strings_;
|
||||
};
|
||||
|
||||
|
||||
Object* MapCache::Lookup(FixedArray* array) {
|
||||
SymbolsKey key(array);
|
||||
StringsKey key(array);
|
||||
int entry = FindEntry(&key);
|
||||
if (entry == kNotFound) return GetHeap()->undefined_value();
|
||||
return get(EntryToIndex(entry) + 1);
|
||||
@ -12909,7 +12913,7 @@ Object* MapCache::Lookup(FixedArray* array) {
|
||||
|
||||
|
||||
MaybeObject* MapCache::Put(FixedArray* array, Map* value) {
|
||||
SymbolsKey key(array);
|
||||
StringsKey key(array);
|
||||
Object* obj;
|
||||
{ MaybeObject* maybe_obj = EnsureCapacity(1, &key);
|
||||
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
|
||||
@ -13428,9 +13432,10 @@ MaybeObject* StringDictionary::TransformPropertiesToFastFor(
|
||||
Object* k = KeyAt(i);
|
||||
if (IsKey(k)) {
|
||||
Object* value = ValueAt(i);
|
||||
// Ensure the key is a symbol before writing into the instance descriptor.
|
||||
// Ensure the key is an internalized string before writing into the
|
||||
// instance descriptor.
|
||||
String* key;
|
||||
MaybeObject* maybe_key = heap->LookupSymbol(String::cast(k));
|
||||
MaybeObject* maybe_key = heap->InternalizeString(String::cast(k));
|
||||
if (!maybe_key->To(&key)) return maybe_key;
|
||||
|
||||
PropertyDetails details = DetailsAt(i);
|
||||
|
271
src/objects.h
271
src/objects.h
@ -77,7 +77,7 @@
|
||||
// - DescriptorArray
|
||||
// - HashTable
|
||||
// - Dictionary
|
||||
// - SymbolTable
|
||||
// - StringTable
|
||||
// - CompilationCacheTable
|
||||
// - CodeCacheHashTable
|
||||
// - MapCache
|
||||
@ -234,8 +234,8 @@ const int kStubMinorKeyBits = kBitsPerInt - kSmiTagSize - kStubMajorKeyBits;
|
||||
// encoding is mentioned explicitly in the name. Likewise, the default
|
||||
// representation is considered sequential. It is not mentioned in the
|
||||
// name. The other representations (e.g. CONS, EXTERNAL) are explicitly
|
||||
// mentioned. Finally, the string is either a SYMBOL_TYPE (if it is a
|
||||
// symbol) or a STRING_TYPE (if it is not a symbol).
|
||||
// mentioned. Finally, the string is either a STRING_TYPE (if it is a normal
|
||||
// string) or a INTERNALIZED_STRING_TYPE (if it is a internalized string).
|
||||
//
|
||||
// NOTE: The following things are some that depend on the string types having
|
||||
// instance_types that are less than those of all other types:
|
||||
@ -246,28 +246,28 @@ const int kStubMinorKeyBits = kBitsPerInt - kSmiTagSize - kStubMajorKeyBits;
|
||||
// JSObject for GC purposes. The first four entries here have typeof
|
||||
// 'object', whereas JS_FUNCTION_TYPE has typeof 'function'.
|
||||
#define INSTANCE_TYPE_LIST_ALL(V) \
|
||||
V(SYMBOL_TYPE) \
|
||||
V(ASCII_SYMBOL_TYPE) \
|
||||
V(CONS_SYMBOL_TYPE) \
|
||||
V(CONS_ASCII_SYMBOL_TYPE) \
|
||||
V(EXTERNAL_SYMBOL_TYPE) \
|
||||
V(EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE) \
|
||||
V(EXTERNAL_ASCII_SYMBOL_TYPE) \
|
||||
V(SHORT_EXTERNAL_SYMBOL_TYPE) \
|
||||
V(SHORT_EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE) \
|
||||
V(SHORT_EXTERNAL_ASCII_SYMBOL_TYPE) \
|
||||
V(STRING_TYPE) \
|
||||
V(ASCII_STRING_TYPE) \
|
||||
V(CONS_STRING_TYPE) \
|
||||
V(CONS_ASCII_STRING_TYPE) \
|
||||
V(SLICED_STRING_TYPE) \
|
||||
V(EXTERNAL_STRING_TYPE) \
|
||||
V(EXTERNAL_STRING_WITH_ASCII_DATA_TYPE) \
|
||||
V(EXTERNAL_ASCII_STRING_TYPE) \
|
||||
V(EXTERNAL_STRING_WITH_ASCII_DATA_TYPE) \
|
||||
V(SHORT_EXTERNAL_STRING_TYPE) \
|
||||
V(SHORT_EXTERNAL_STRING_WITH_ASCII_DATA_TYPE) \
|
||||
V(SHORT_EXTERNAL_ASCII_STRING_TYPE) \
|
||||
V(PRIVATE_EXTERNAL_ASCII_STRING_TYPE) \
|
||||
V(SHORT_EXTERNAL_STRING_WITH_ASCII_DATA_TYPE) \
|
||||
\
|
||||
V(INTERNALIZED_STRING_TYPE) \
|
||||
V(ASCII_INTERNALIZED_STRING_TYPE) \
|
||||
V(CONS_INTERNALIZED_STRING_TYPE) \
|
||||
V(CONS_ASCII_INTERNALIZED_STRING_TYPE) \
|
||||
V(EXTERNAL_INTERNALIZED_STRING_TYPE) \
|
||||
V(EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE) \
|
||||
V(EXTERNAL_INTERNALIZED_STRING_WITH_ASCII_DATA_TYPE) \
|
||||
V(SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE) \
|
||||
V(SHORT_EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE) \
|
||||
V(SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ASCII_DATA_TYPE) \
|
||||
\
|
||||
V(MAP_TYPE) \
|
||||
V(CODE_TYPE) \
|
||||
@ -347,46 +347,6 @@ const int kStubMinorKeyBits = kBitsPerInt - kSmiTagSize - kStubMajorKeyBits;
|
||||
// Since string types are not consecutive, this macro is used to
|
||||
// iterate over them.
|
||||
#define STRING_TYPE_LIST(V) \
|
||||
V(SYMBOL_TYPE, \
|
||||
kVariableSizeSentinel, \
|
||||
symbol, \
|
||||
Symbol) \
|
||||
V(ASCII_SYMBOL_TYPE, \
|
||||
kVariableSizeSentinel, \
|
||||
ascii_symbol, \
|
||||
AsciiSymbol) \
|
||||
V(CONS_SYMBOL_TYPE, \
|
||||
ConsString::kSize, \
|
||||
cons_symbol, \
|
||||
ConsSymbol) \
|
||||
V(CONS_ASCII_SYMBOL_TYPE, \
|
||||
ConsString::kSize, \
|
||||
cons_ascii_symbol, \
|
||||
ConsAsciiSymbol) \
|
||||
V(EXTERNAL_SYMBOL_TYPE, \
|
||||
ExternalTwoByteString::kSize, \
|
||||
external_symbol, \
|
||||
ExternalSymbol) \
|
||||
V(EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE, \
|
||||
ExternalTwoByteString::kSize, \
|
||||
external_symbol_with_ascii_data, \
|
||||
ExternalSymbolWithAsciiData) \
|
||||
V(EXTERNAL_ASCII_SYMBOL_TYPE, \
|
||||
ExternalAsciiString::kSize, \
|
||||
external_ascii_symbol, \
|
||||
ExternalAsciiSymbol) \
|
||||
V(SHORT_EXTERNAL_SYMBOL_TYPE, \
|
||||
ExternalTwoByteString::kShortSize, \
|
||||
short_external_symbol, \
|
||||
ShortExternalSymbol) \
|
||||
V(SHORT_EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE, \
|
||||
ExternalTwoByteString::kShortSize, \
|
||||
short_external_symbol_with_ascii_data, \
|
||||
ShortExternalSymbolWithAsciiData) \
|
||||
V(SHORT_EXTERNAL_ASCII_SYMBOL_TYPE, \
|
||||
ExternalAsciiString::kShortSize, \
|
||||
short_external_ascii_symbol, \
|
||||
ShortExternalAsciiSymbol) \
|
||||
V(STRING_TYPE, \
|
||||
kVariableSizeSentinel, \
|
||||
string, \
|
||||
@ -415,26 +375,67 @@ const int kStubMinorKeyBits = kBitsPerInt - kSmiTagSize - kStubMajorKeyBits;
|
||||
ExternalTwoByteString::kSize, \
|
||||
external_string, \
|
||||
ExternalString) \
|
||||
V(EXTERNAL_STRING_WITH_ASCII_DATA_TYPE, \
|
||||
ExternalTwoByteString::kSize, \
|
||||
external_string_with_ascii_data, \
|
||||
ExternalStringWithAsciiData) \
|
||||
V(EXTERNAL_ASCII_STRING_TYPE, \
|
||||
ExternalAsciiString::kSize, \
|
||||
external_ascii_string, \
|
||||
ExternalAsciiString) \
|
||||
V(EXTERNAL_STRING_WITH_ASCII_DATA_TYPE, \
|
||||
ExternalTwoByteString::kSize, \
|
||||
external_string_with_ascii_data, \
|
||||
ExternalStringWithAsciiData) \
|
||||
V(SHORT_EXTERNAL_STRING_TYPE, \
|
||||
ExternalTwoByteString::kShortSize, \
|
||||
short_external_string, \
|
||||
ShortExternalString) \
|
||||
V(SHORT_EXTERNAL_ASCII_STRING_TYPE, \
|
||||
ExternalAsciiString::kShortSize, \
|
||||
short_external_ascii_string, \
|
||||
ShortExternalAsciiString) \
|
||||
V(SHORT_EXTERNAL_STRING_WITH_ASCII_DATA_TYPE, \
|
||||
ExternalTwoByteString::kShortSize, \
|
||||
short_external_string_with_ascii_data, \
|
||||
ShortExternalStringWithAsciiData) \
|
||||
V(SHORT_EXTERNAL_ASCII_STRING_TYPE, \
|
||||
\
|
||||
V(INTERNALIZED_STRING_TYPE, \
|
||||
kVariableSizeSentinel, \
|
||||
internalized_string, \
|
||||
InternalizedString) \
|
||||
V(ASCII_INTERNALIZED_STRING_TYPE, \
|
||||
kVariableSizeSentinel, \
|
||||
ascii_internalized_string, \
|
||||
AsciiInternalizedString) \
|
||||
V(CONS_INTERNALIZED_STRING_TYPE, \
|
||||
ConsString::kSize, \
|
||||
cons_internalized_string, \
|
||||
ConsInternalizedString) \
|
||||
V(CONS_ASCII_INTERNALIZED_STRING_TYPE, \
|
||||
ConsString::kSize, \
|
||||
cons_ascii_internalized_string, \
|
||||
ConsAsciiInternalizedString) \
|
||||
V(EXTERNAL_INTERNALIZED_STRING_TYPE, \
|
||||
ExternalTwoByteString::kSize, \
|
||||
external_internalized_string, \
|
||||
ExternalInternalizedString) \
|
||||
V(EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE, \
|
||||
ExternalAsciiString::kSize, \
|
||||
external_ascii_internalized_string, \
|
||||
ExternalAsciiInternalizedString) \
|
||||
V(EXTERNAL_INTERNALIZED_STRING_WITH_ASCII_DATA_TYPE, \
|
||||
ExternalTwoByteString::kSize, \
|
||||
external_internalized_string_with_ascii_data, \
|
||||
ExternalInternalizedStringWithAsciiData) \
|
||||
V(SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE, \
|
||||
ExternalTwoByteString::kShortSize, \
|
||||
short_external_internalized_string, \
|
||||
ShortExternalInternalizedString) \
|
||||
V(SHORT_EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE, \
|
||||
ExternalAsciiString::kShortSize, \
|
||||
short_external_ascii_string, \
|
||||
ShortExternalAsciiString)
|
||||
short_external_ascii_internalized_string, \
|
||||
ShortExternalAsciiInternalizedString) \
|
||||
V(SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ASCII_DATA_TYPE, \
|
||||
ExternalTwoByteString::kShortSize, \
|
||||
short_external_internalized_string_with_ascii_data, \
|
||||
ShortExternalInternalizedStringWithAsciiData) \
|
||||
|
||||
// A struct is a simple object a set of object-valued fields. Including an
|
||||
// object type in this causes the compiler to generate most of the boilerplate
|
||||
@ -485,12 +486,12 @@ const uint32_t kIsNotStringMask = 0x80;
|
||||
const uint32_t kStringTag = 0x0;
|
||||
const uint32_t kNotStringTag = 0x80;
|
||||
|
||||
// Bit 6 indicates that the object is a symbol (if set) or not (if cleared).
|
||||
// Bit 6 indicates that the object is an internalized string (if set) or not.
|
||||
// There are not enough types that the non-string types (with bit 7 set) can
|
||||
// have bit 6 set too.
|
||||
const uint32_t kIsSymbolMask = 0x40;
|
||||
const uint32_t kNotSymbolTag = 0x0;
|
||||
const uint32_t kSymbolTag = 0x40;
|
||||
const uint32_t kIsInternalizedMask = 0x40;
|
||||
const uint32_t kNotInternalizedTag = 0x0;
|
||||
const uint32_t kInternalizedTag = 0x40;
|
||||
|
||||
// If bit 7 is clear then bit 2 indicates whether the string consists of
|
||||
// two-byte characters or one-byte characters.
|
||||
@ -533,54 +534,51 @@ const uint32_t kShortExternalStringTag = 0x10;
|
||||
|
||||
|
||||
// A ConsString with an empty string as the right side is a candidate
|
||||
// for being shortcut by the garbage collector unless it is a
|
||||
// symbol. It's not common to have non-flat symbols, so we do not
|
||||
// shortcut them thereby avoiding turning symbols into strings. See
|
||||
// heap.cc and mark-compact.cc.
|
||||
// for being shortcut by the garbage collector unless it is internalized.
|
||||
// It's not common to have non-flat internalized strings, so we do not
|
||||
// shortcut them thereby avoiding turning internalized strings into strings.
|
||||
// See heap.cc and mark-compact.cc.
|
||||
const uint32_t kShortcutTypeMask =
|
||||
kIsNotStringMask |
|
||||
kIsSymbolMask |
|
||||
kIsInternalizedMask |
|
||||
kStringRepresentationMask;
|
||||
const uint32_t kShortcutTypeTag = kConsStringTag;
|
||||
|
||||
|
||||
enum InstanceType {
|
||||
// String types.
|
||||
SYMBOL_TYPE = kTwoByteStringTag | kSymbolTag | kSeqStringTag,
|
||||
ASCII_SYMBOL_TYPE = kOneByteStringTag | kSymbolTag | kSeqStringTag,
|
||||
CONS_SYMBOL_TYPE = kTwoByteStringTag | kSymbolTag | kConsStringTag,
|
||||
CONS_ASCII_SYMBOL_TYPE = kOneByteStringTag | kSymbolTag | kConsStringTag,
|
||||
SHORT_EXTERNAL_SYMBOL_TYPE = kTwoByteStringTag | kSymbolTag |
|
||||
kExternalStringTag | kShortExternalStringTag,
|
||||
SHORT_EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE =
|
||||
kTwoByteStringTag | kSymbolTag | kExternalStringTag |
|
||||
kAsciiDataHintTag | kShortExternalStringTag,
|
||||
SHORT_EXTERNAL_ASCII_SYMBOL_TYPE = kOneByteStringTag | kExternalStringTag |
|
||||
kSymbolTag | kShortExternalStringTag,
|
||||
EXTERNAL_SYMBOL_TYPE = kTwoByteStringTag | kSymbolTag | kExternalStringTag,
|
||||
EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE =
|
||||
kTwoByteStringTag | kSymbolTag | kExternalStringTag | kAsciiDataHintTag,
|
||||
EXTERNAL_ASCII_SYMBOL_TYPE =
|
||||
kOneByteStringTag | kSymbolTag | kExternalStringTag,
|
||||
STRING_TYPE = kTwoByteStringTag | kSeqStringTag,
|
||||
ASCII_STRING_TYPE = kOneByteStringTag | kSeqStringTag,
|
||||
CONS_STRING_TYPE = kTwoByteStringTag | kConsStringTag,
|
||||
CONS_ASCII_STRING_TYPE = kOneByteStringTag | kConsStringTag,
|
||||
SLICED_STRING_TYPE = kTwoByteStringTag | kSlicedStringTag,
|
||||
SLICED_ASCII_STRING_TYPE = kOneByteStringTag | kSlicedStringTag,
|
||||
SHORT_EXTERNAL_STRING_TYPE =
|
||||
kTwoByteStringTag | kExternalStringTag | kShortExternalStringTag,
|
||||
SHORT_EXTERNAL_STRING_WITH_ASCII_DATA_TYPE =
|
||||
kTwoByteStringTag | kExternalStringTag |
|
||||
kAsciiDataHintTag | kShortExternalStringTag,
|
||||
SHORT_EXTERNAL_ASCII_STRING_TYPE =
|
||||
kOneByteStringTag | kExternalStringTag | kShortExternalStringTag,
|
||||
EXTERNAL_STRING_TYPE = kTwoByteStringTag | kExternalStringTag,
|
||||
EXTERNAL_STRING_WITH_ASCII_DATA_TYPE =
|
||||
kTwoByteStringTag | kExternalStringTag | kAsciiDataHintTag,
|
||||
// LAST_STRING_TYPE
|
||||
EXTERNAL_ASCII_STRING_TYPE = kOneByteStringTag | kExternalStringTag,
|
||||
PRIVATE_EXTERNAL_ASCII_STRING_TYPE = EXTERNAL_ASCII_STRING_TYPE,
|
||||
EXTERNAL_STRING_WITH_ASCII_DATA_TYPE =
|
||||
EXTERNAL_STRING_TYPE | kAsciiDataHintTag,
|
||||
SHORT_EXTERNAL_STRING_TYPE = EXTERNAL_STRING_TYPE | kShortExternalStringTag,
|
||||
SHORT_EXTERNAL_ASCII_STRING_TYPE =
|
||||
EXTERNAL_ASCII_STRING_TYPE | kShortExternalStringTag,
|
||||
SHORT_EXTERNAL_STRING_WITH_ASCII_DATA_TYPE =
|
||||
EXTERNAL_STRING_WITH_ASCII_DATA_TYPE | kShortExternalStringTag,
|
||||
|
||||
INTERNALIZED_STRING_TYPE = STRING_TYPE | kInternalizedTag,
|
||||
ASCII_INTERNALIZED_STRING_TYPE = ASCII_STRING_TYPE | kInternalizedTag,
|
||||
CONS_INTERNALIZED_STRING_TYPE = CONS_STRING_TYPE | kInternalizedTag,
|
||||
CONS_ASCII_INTERNALIZED_STRING_TYPE =
|
||||
CONS_ASCII_STRING_TYPE | kInternalizedTag,
|
||||
EXTERNAL_INTERNALIZED_STRING_TYPE = EXTERNAL_STRING_TYPE | kInternalizedTag,
|
||||
EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE =
|
||||
EXTERNAL_ASCII_STRING_TYPE | kInternalizedTag,
|
||||
EXTERNAL_INTERNALIZED_STRING_WITH_ASCII_DATA_TYPE =
|
||||
EXTERNAL_STRING_WITH_ASCII_DATA_TYPE | kInternalizedTag,
|
||||
SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE =
|
||||
SHORT_EXTERNAL_STRING_TYPE | kInternalizedTag,
|
||||
SHORT_EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE =
|
||||
SHORT_EXTERNAL_ASCII_STRING_TYPE | kInternalizedTag,
|
||||
SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ASCII_DATA_TYPE =
|
||||
SHORT_EXTERNAL_STRING_WITH_ASCII_DATA_TYPE | kInternalizedTag,
|
||||
|
||||
// Objects allocated in their own spaces (never in new space).
|
||||
MAP_TYPE = kNotStringTag, // FIRST_NONSTRING_TYPE
|
||||
@ -711,7 +709,7 @@ STATIC_CHECK(FOREIGN_TYPE == Internals::kForeignType);
|
||||
V(DICTIONARY_PROPERTIES_SUB_TYPE) \
|
||||
V(MAP_CODE_CACHE_SUB_TYPE) \
|
||||
V(SCOPE_INFO_SUB_TYPE) \
|
||||
V(SYMBOL_TABLE_SUB_TYPE) \
|
||||
V(STRING_TABLE_SUB_TYPE) \
|
||||
V(DESCRIPTOR_ARRAY_SUB_TYPE) \
|
||||
V(TRANSITION_ARRAY_SUB_TYPE)
|
||||
|
||||
@ -842,7 +840,6 @@ class MaybeObject BASE_EMBEDDED {
|
||||
#define HEAP_OBJECT_TYPE_LIST(V) \
|
||||
V(HeapNumber) \
|
||||
V(String) \
|
||||
V(Symbol) \
|
||||
V(SeqString) \
|
||||
V(ExternalString) \
|
||||
V(ConsString) \
|
||||
@ -850,7 +847,8 @@ class MaybeObject BASE_EMBEDDED {
|
||||
V(ExternalTwoByteString) \
|
||||
V(ExternalAsciiString) \
|
||||
V(SeqTwoByteString) \
|
||||
V(SeqOneByteString) \
|
||||
V(SeqOneByteString) \
|
||||
V(InternalizedString) \
|
||||
\
|
||||
V(ExternalArray) \
|
||||
V(ExternalByteArray) \
|
||||
@ -899,7 +897,7 @@ class MaybeObject BASE_EMBEDDED {
|
||||
V(JSRegExp) \
|
||||
V(HashTable) \
|
||||
V(Dictionary) \
|
||||
V(SymbolTable) \
|
||||
V(StringTable) \
|
||||
V(JSFunctionResultCache) \
|
||||
V(NormalizedMapCache) \
|
||||
V(CompilationCacheTable) \
|
||||
@ -1798,7 +1796,7 @@ class JSObject: public JSReceiver {
|
||||
//
|
||||
// Hidden properties are not local properties of the object itself.
|
||||
// Instead they are stored in an auxiliary structure kept as a local
|
||||
// property with a special name Heap::hidden_symbol(). But if the
|
||||
// property with a special name Heap::hidden_string(). But if the
|
||||
// receiver is a JSGlobalProxy then the auxiliary object is a property
|
||||
// of its prototype, and if it's a detached proxy, then you can't have
|
||||
// hidden properties.
|
||||
@ -1817,7 +1815,7 @@ class JSObject: public JSReceiver {
|
||||
// Deletes a hidden property. Deleting a non-existing property is
|
||||
// considered successful.
|
||||
void DeleteHiddenProperty(String* key);
|
||||
// Returns true if the object has a property with the hidden symbol as name.
|
||||
// Returns true if the object has a property with the hidden string as name.
|
||||
bool HasHiddenProperties();
|
||||
|
||||
static int GetIdentityHash(Handle<JSObject> obj);
|
||||
@ -3016,7 +3014,7 @@ class HashTableKey {
|
||||
};
|
||||
|
||||
|
||||
class SymbolTableShape : public BaseShape<HashTableKey*> {
|
||||
class StringTableShape : public BaseShape<HashTableKey*> {
|
||||
public:
|
||||
static inline bool IsMatch(HashTableKey* key, Object* value) {
|
||||
return key->IsMatch(value);
|
||||
@ -3037,44 +3035,47 @@ class SymbolTableShape : public BaseShape<HashTableKey*> {
|
||||
|
||||
class SeqOneByteString;
|
||||
|
||||
// SymbolTable.
|
||||
// StringTable.
|
||||
//
|
||||
// No special elements in the prefix and the element size is 1
|
||||
// because only the symbol itself (the key) needs to be stored.
|
||||
class SymbolTable: public HashTable<SymbolTableShape, HashTableKey*> {
|
||||
// because only the string itself (the key) needs to be stored.
|
||||
class StringTable: public HashTable<StringTableShape, HashTableKey*> {
|
||||
public:
|
||||
// Find symbol in the symbol table. If it is not there yet, it is
|
||||
// added. The return value is the symbol table which might have
|
||||
// been enlarged. If the return value is not a failure, the symbol
|
||||
// pointer *s is set to the symbol found.
|
||||
MUST_USE_RESULT MaybeObject* LookupUtf8Symbol(Vector<const char> str,
|
||||
Object** s);
|
||||
MUST_USE_RESULT MaybeObject* LookupOneByteSymbol(Vector<const uint8_t> str,
|
||||
Object** s);
|
||||
MUST_USE_RESULT MaybeObject* LookupSubStringOneByteSymbol(
|
||||
// Find string in the string table. If it is not there yet, it is
|
||||
// added. The return value is the string table which might have
|
||||
// been enlarged. If the return value is not a failure, the string
|
||||
// pointer *s is set to the string found.
|
||||
MUST_USE_RESULT MaybeObject* LookupUtf8String(
|
||||
Vector<const char> str,
|
||||
Object** s);
|
||||
MUST_USE_RESULT MaybeObject* LookupOneByteString(
|
||||
Vector<const uint8_t> str,
|
||||
Object** s);
|
||||
MUST_USE_RESULT MaybeObject* LookupSubStringOneByteString(
|
||||
Handle<SeqOneByteString> str,
|
||||
int from,
|
||||
int length,
|
||||
Object** s);
|
||||
MUST_USE_RESULT MaybeObject* LookupTwoByteSymbol(Vector<const uc16> str,
|
||||
Object** s);
|
||||
MUST_USE_RESULT MaybeObject* LookupTwoByteString(
|
||||
Vector<const uc16> str,
|
||||
Object** s);
|
||||
MUST_USE_RESULT MaybeObject* LookupString(String* key, Object** s);
|
||||
|
||||
// Looks up a symbol that is equal to the given string and returns
|
||||
// true if it is found, assigning the symbol to the given output
|
||||
// Looks up a string that is equal to the given string and returns
|
||||
// true if it is found, assigning the string to the given output
|
||||
// parameter.
|
||||
bool LookupSymbolIfExists(String* str, String** symbol);
|
||||
bool LookupTwoCharsSymbolIfExists(uint16_t c1, uint16_t c2, String** symbol);
|
||||
bool LookupStringIfExists(String* str, String** result);
|
||||
bool LookupTwoCharsStringIfExists(uint16_t c1, uint16_t c2, String** result);
|
||||
|
||||
// Casting.
|
||||
static inline SymbolTable* cast(Object* obj);
|
||||
static inline StringTable* cast(Object* obj);
|
||||
|
||||
private:
|
||||
MUST_USE_RESULT MaybeObject* LookupKey(HashTableKey* key, Object** s);
|
||||
|
||||
template <bool seq_ascii> friend class JsonParser;
|
||||
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(SymbolTable);
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(StringTable);
|
||||
};
|
||||
|
||||
|
||||
@ -3102,7 +3103,7 @@ class MapCacheShape : public BaseShape<HashTableKey*> {
|
||||
|
||||
// MapCache.
|
||||
//
|
||||
// Maps keys that are a fixed array of symbols to a map.
|
||||
// Maps keys that are a fixed array of internalized strings to a map.
|
||||
// Used for canonicalize maps for object literals.
|
||||
class MapCache: public HashTable<MapCacheShape, HashTableKey*> {
|
||||
public:
|
||||
@ -3535,13 +3536,13 @@ class ScopeInfo : public FixedArray {
|
||||
|
||||
// Lookup support for serialized scope info. Returns the
|
||||
// the stack slot index for a given slot name if the slot is
|
||||
// present; otherwise returns a value < 0. The name must be a symbol
|
||||
// (canonicalized).
|
||||
// present; otherwise returns a value < 0. The name must be an internalized
|
||||
// string.
|
||||
int StackSlotIndex(String* name);
|
||||
|
||||
// Lookup support for serialized scope info. Returns the
|
||||
// context slot index for a given slot name if the slot is present; otherwise
|
||||
// returns a value < 0. The name must be a symbol (canonicalized).
|
||||
// returns a value < 0. The name must be an internalized string.
|
||||
// If the slot is present and mode != NULL, sets *mode to the corresponding
|
||||
// mode for that variable.
|
||||
int ContextSlotIndex(String* name,
|
||||
@ -3550,13 +3551,13 @@ class ScopeInfo : public FixedArray {
|
||||
|
||||
// Lookup support for serialized scope info. Returns the
|
||||
// parameter index for a given parameter name if the parameter is present;
|
||||
// otherwise returns a value < 0. The name must be a symbol (canonicalized).
|
||||
// otherwise returns a value < 0. The name must be an internalized string.
|
||||
int ParameterIndex(String* name);
|
||||
|
||||
// Lookup support for serialized scope info. Returns the function context
|
||||
// slot index if the function name is present and context-allocated (named
|
||||
// function expressions, only), otherwise returns a value < 0. The name
|
||||
// must be a symbol (canonicalized).
|
||||
// must be an internalized string.
|
||||
int FunctionContextSlotIndex(String* name, VariableMode* mode);
|
||||
|
||||
|
||||
@ -7174,7 +7175,7 @@ class StringShape BASE_EMBEDDED {
|
||||
inline bool IsExternalTwoByte();
|
||||
inline bool IsSequentialAscii();
|
||||
inline bool IsSequentialTwoByte();
|
||||
inline bool IsSymbol();
|
||||
inline bool IsInternalized();
|
||||
inline StringRepresentationTag representation_tag();
|
||||
inline uint32_t encoding_tag();
|
||||
inline uint32_t full_representation_tag();
|
||||
@ -8892,10 +8893,10 @@ class BreakPointInfo: public Struct {
|
||||
#undef DECLARE_VERIFIER
|
||||
|
||||
#define VISITOR_SYNCHRONIZATION_TAGS_LIST(V) \
|
||||
V(kSymbolTable, "symbol_table", "(Symbols)") \
|
||||
V(kStringTable, "string_table", "(Internalized strings)") \
|
||||
V(kExternalStringsTable, "external_strings_table", "(External strings)") \
|
||||
V(kStrongRootList, "strong_root_list", "(Strong roots)") \
|
||||
V(kSymbol, "symbol", "(Symbol)") \
|
||||
V(kInternalizedString, "internalized_string", "(Internal string)") \
|
||||
V(kBootstrapper, "bootstrapper", "(Bootstrapper)") \
|
||||
V(kTop, "top", "(Isolate)") \
|
||||
V(kRelocatable, "relocatable", "(Relocatable)") \
|
||||
|
@ -257,10 +257,10 @@ Handle<String> Parser::LookupSymbol(int symbol_id) {
|
||||
if (static_cast<unsigned>(symbol_id)
|
||||
>= static_cast<unsigned>(symbol_cache_.length())) {
|
||||
if (scanner().is_literal_ascii()) {
|
||||
return isolate()->factory()->LookupOneByteSymbol(
|
||||
return isolate()->factory()->InternalizeOneByteString(
|
||||
Vector<const uint8_t>::cast(scanner().literal_ascii_string()));
|
||||
} else {
|
||||
return isolate()->factory()->LookupTwoByteSymbol(
|
||||
return isolate()->factory()->InternalizeTwoByteString(
|
||||
scanner().literal_utf16_string());
|
||||
}
|
||||
}
|
||||
@ -278,10 +278,10 @@ Handle<String> Parser::LookupCachedSymbol(int symbol_id) {
|
||||
Handle<String> result = symbol_cache_.at(symbol_id);
|
||||
if (result.is_null()) {
|
||||
if (scanner().is_literal_ascii()) {
|
||||
result = isolate()->factory()->LookupOneByteSymbol(
|
||||
result = isolate()->factory()->InternalizeOneByteString(
|
||||
Vector<const uint8_t>::cast(scanner().literal_ascii_string()));
|
||||
} else {
|
||||
result = isolate()->factory()->LookupTwoByteSymbol(
|
||||
result = isolate()->factory()->InternalizeTwoByteString(
|
||||
scanner().literal_utf16_string());
|
||||
}
|
||||
symbol_cache_.at(symbol_id) = result;
|
||||
@ -617,7 +617,7 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
|
||||
ASSERT(target_stack_ == NULL);
|
||||
if (pre_data_ != NULL) pre_data_->Initialize();
|
||||
|
||||
Handle<String> no_name = isolate()->factory()->empty_symbol();
|
||||
Handle<String> no_name = isolate()->factory()->empty_string();
|
||||
|
||||
FunctionLiteral* result = NULL;
|
||||
{ Scope* scope = NewScope(top_scope_, GLOBAL_SCOPE);
|
||||
@ -920,7 +920,7 @@ class ThisNamedPropertyAssignmentFinder {
|
||||
if (literal != NULL &&
|
||||
literal->handle()->IsString() &&
|
||||
!String::cast(*(literal->handle()))->Equals(
|
||||
isolate_->heap()->Proto_symbol()) &&
|
||||
isolate_->heap()->proto_string()) &&
|
||||
!String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) {
|
||||
Handle<String> key = Handle<String>::cast(literal->handle());
|
||||
|
||||
@ -1057,9 +1057,9 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
|
||||
|
||||
// Check "use strict" directive (ES5 14.1).
|
||||
if (top_scope_->is_classic_mode() &&
|
||||
directive->Equals(isolate()->heap()->use_strict()) &&
|
||||
directive->Equals(isolate()->heap()->use_strict_string()) &&
|
||||
token_loc.end_pos - token_loc.beg_pos ==
|
||||
isolate()->heap()->use_strict()->length() + 2) {
|
||||
isolate()->heap()->use_strict_string()->length() + 2) {
|
||||
// TODO(mstarzinger): Global strict eval calls, need their own scope
|
||||
// as specified in ES5 10.4.2(3). The correct fix would be to always
|
||||
// add this scope in DoParseProgram(), but that requires adaptations
|
||||
@ -1144,7 +1144,7 @@ Statement* Parser::ParseModuleElement(ZoneStringList* labels,
|
||||
if (estmt != NULL &&
|
||||
estmt->expression()->AsVariableProxy() != NULL &&
|
||||
estmt->expression()->AsVariableProxy()->name()->Equals(
|
||||
isolate()->heap()->module_symbol()) &&
|
||||
isolate()->heap()->module_string()) &&
|
||||
!scanner().literal_contains_escapes()) {
|
||||
return ParseModuleDeclaration(NULL, ok);
|
||||
}
|
||||
@ -1716,7 +1716,7 @@ void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) {
|
||||
isolate()->factory()->NewStringFromUtf8(CStrVector("Variable"),
|
||||
TENURED);
|
||||
Expression* expression =
|
||||
NewThrowTypeError(isolate()->factory()->redeclaration_symbol(),
|
||||
NewThrowTypeError(isolate()->factory()->redeclaration_string(),
|
||||
type_string, name);
|
||||
declaration_scope->SetIllegalRedeclaration(expression);
|
||||
}
|
||||
@ -1978,8 +1978,8 @@ Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context,
|
||||
|
||||
|
||||
bool Parser::IsEvalOrArguments(Handle<String> string) {
|
||||
return string.is_identical_to(isolate()->factory()->eval_symbol()) ||
|
||||
string.is_identical_to(isolate()->factory()->arguments_symbol());
|
||||
return string.is_identical_to(isolate()->factory()->eval_string()) ||
|
||||
string.is_identical_to(isolate()->factory()->arguments_string());
|
||||
}
|
||||
|
||||
|
||||
@ -2233,7 +2233,7 @@ Block* Parser::ParseVariableDeclarations(
|
||||
// Note that the function does different things depending on
|
||||
// the number of arguments (1 or 2).
|
||||
initialize = factory()->NewCallRuntime(
|
||||
isolate()->factory()->InitializeConstGlobal_symbol(),
|
||||
isolate()->factory()->InitializeConstGlobal_string(),
|
||||
Runtime::FunctionForId(Runtime::kInitializeConstGlobal),
|
||||
arguments);
|
||||
} else {
|
||||
@ -2256,7 +2256,7 @@ Block* Parser::ParseVariableDeclarations(
|
||||
// Note that the function does different things depending on
|
||||
// the number of arguments (2 or 3).
|
||||
initialize = factory()->NewCallRuntime(
|
||||
isolate()->factory()->InitializeVarGlobal_symbol(),
|
||||
isolate()->factory()->InitializeVarGlobal_string(),
|
||||
Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
|
||||
arguments);
|
||||
}
|
||||
@ -2368,7 +2368,7 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
|
||||
expr != NULL &&
|
||||
expr->AsVariableProxy() != NULL &&
|
||||
expr->AsVariableProxy()->name()->Equals(
|
||||
isolate()->heap()->native_symbol()) &&
|
||||
isolate()->heap()->native_string()) &&
|
||||
!scanner().literal_contains_escapes()) {
|
||||
return ParseNativeDeclaration(ok);
|
||||
}
|
||||
@ -2380,7 +2380,7 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
|
||||
scanner().HasAnyLineTerminatorBeforeNext() ||
|
||||
expr->AsVariableProxy() == NULL ||
|
||||
!expr->AsVariableProxy()->name()->Equals(
|
||||
isolate()->heap()->module_symbol()) ||
|
||||
isolate()->heap()->module_string()) ||
|
||||
scanner().literal_contains_escapes()) {
|
||||
ExpectSemicolon(CHECK_OK);
|
||||
}
|
||||
@ -2505,7 +2505,7 @@ Statement* Parser::ParseReturnStatement(bool* ok) {
|
||||
Scope* declaration_scope = top_scope_->DeclarationScope();
|
||||
if (declaration_scope->is_global_scope() ||
|
||||
declaration_scope->is_eval_scope()) {
|
||||
Handle<String> type = isolate()->factory()->illegal_return_symbol();
|
||||
Handle<String> type = isolate()->factory()->illegal_return_string();
|
||||
Expression* throw_error = NewThrowSyntaxError(type, Handle<Object>::null());
|
||||
return factory()->NewExpressionStatement(throw_error);
|
||||
}
|
||||
@ -2853,8 +2853,8 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
|
||||
// implementing stack allocated block scoped variables.
|
||||
Factory* heap_factory = isolate()->factory();
|
||||
Handle<String> tempstr =
|
||||
heap_factory->NewConsString(heap_factory->dot_for_symbol(), name);
|
||||
Handle<String> tempname = heap_factory->LookupSymbol(tempstr);
|
||||
heap_factory->NewConsString(heap_factory->dot_for_string(), name);
|
||||
Handle<String> tempname = heap_factory->InternalizeString(tempstr);
|
||||
Variable* temp = top_scope_->DeclarationScope()->NewTemporary(tempname);
|
||||
VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
|
||||
ForInStatement* loop = factory()->NewForInStatement(labels);
|
||||
@ -2898,7 +2898,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
|
||||
// the error at runtime.
|
||||
if (expression == NULL || !expression->IsValidLeftHandSide()) {
|
||||
Handle<String> type =
|
||||
isolate()->factory()->invalid_lhs_in_for_in_symbol();
|
||||
isolate()->factory()->invalid_lhs_in_for_in_string();
|
||||
expression = NewThrowReferenceError(type);
|
||||
}
|
||||
ForInStatement* loop = factory()->NewForInStatement(labels);
|
||||
@ -3012,7 +3012,7 @@ Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
|
||||
// TODO(ES5): Should change parsing for spec conformance.
|
||||
if (expression == NULL || !expression->IsValidLeftHandSide()) {
|
||||
Handle<String> type =
|
||||
isolate()->factory()->invalid_lhs_in_assignment_symbol();
|
||||
isolate()->factory()->invalid_lhs_in_assignment_string();
|
||||
expression = NewThrowReferenceError(type);
|
||||
}
|
||||
|
||||
@ -3253,7 +3253,7 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
|
||||
// error at runtime.
|
||||
if (expression == NULL || !expression->IsValidLeftHandSide()) {
|
||||
Handle<String> type =
|
||||
isolate()->factory()->invalid_lhs_in_prefix_op_symbol();
|
||||
isolate()->factory()->invalid_lhs_in_prefix_op_string();
|
||||
expression = NewThrowReferenceError(type);
|
||||
}
|
||||
|
||||
@ -3288,7 +3288,7 @@ Expression* Parser::ParsePostfixExpression(bool* ok) {
|
||||
// error at runtime.
|
||||
if (expression == NULL || !expression->IsValidLeftHandSide()) {
|
||||
Handle<String> type =
|
||||
isolate()->factory()->invalid_lhs_in_postfix_op_symbol();
|
||||
isolate()->factory()->invalid_lhs_in_postfix_op_string();
|
||||
expression = NewThrowReferenceError(type);
|
||||
}
|
||||
|
||||
@ -3363,7 +3363,7 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
|
||||
// they are actually direct calls to eval is determined at run time.
|
||||
VariableProxy* callee = result->AsVariableProxy();
|
||||
if (callee != NULL &&
|
||||
callee->IsVariable(isolate()->factory()->eval_symbol())) {
|
||||
callee->IsVariable(isolate()->factory()->eval_string())) {
|
||||
top_scope_->DeclarationScope()->RecordEvalCall();
|
||||
}
|
||||
result = factory()->NewCall(result, args, pos);
|
||||
@ -3470,7 +3470,7 @@ Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
|
||||
fni_->PushLiteralName(index->AsLiteral()->AsPropertyName());
|
||||
} else {
|
||||
fni_->PushLiteralName(
|
||||
isolate()->factory()->anonymous_function_symbol());
|
||||
isolate()->factory()->anonymous_function_string());
|
||||
}
|
||||
}
|
||||
Expect(Token::RBRACK, CHECK_OK);
|
||||
@ -3992,7 +3992,7 @@ ObjectLiteral::Property* Parser::ParseObjectLiteralGetSet(bool is_getter,
|
||||
next == Token::STRING || is_keyword) {
|
||||
Handle<String> name;
|
||||
if (is_keyword) {
|
||||
name = isolate_->factory()->LookupUtf8Symbol(Token::String(next));
|
||||
name = isolate_->factory()->InternalizeUtf8String(Token::String(next));
|
||||
} else {
|
||||
name = GetSymbol(CHECK_OK);
|
||||
}
|
||||
@ -4313,7 +4313,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
|
||||
|
||||
// We want a non-null handle as the function name.
|
||||
if (should_infer_name) {
|
||||
function_name = isolate()->factory()->empty_symbol();
|
||||
function_name = isolate()->factory()->empty_string();
|
||||
}
|
||||
|
||||
int num_parameters = 0;
|
||||
@ -4619,7 +4619,7 @@ Expression* Parser::ParseV8Intrinsic(bool* ok) {
|
||||
top_scope_->DeclarationScope()->ForceEagerCompilation();
|
||||
}
|
||||
|
||||
const Runtime::Function* function = Runtime::FunctionForSymbol(name);
|
||||
const Runtime::Function* function = Runtime::FunctionForName(name);
|
||||
|
||||
// Check for built-in IS_VAR macro.
|
||||
if (function != NULL &&
|
||||
@ -4906,7 +4906,7 @@ void Parser::RegisterTargetUse(Label* target, Target* stop) {
|
||||
|
||||
|
||||
Expression* Parser::NewThrowReferenceError(Handle<String> type) {
|
||||
return NewThrowError(isolate()->factory()->MakeReferenceError_symbol(),
|
||||
return NewThrowError(isolate()->factory()->MakeReferenceError_string(),
|
||||
type, HandleVector<Object>(NULL, 0));
|
||||
}
|
||||
|
||||
@ -4916,7 +4916,7 @@ Expression* Parser::NewThrowSyntaxError(Handle<String> type,
|
||||
int argc = first.is_null() ? 0 : 1;
|
||||
Vector< Handle<Object> > arguments = HandleVector<Object>(&first, argc);
|
||||
return NewThrowError(
|
||||
isolate()->factory()->MakeSyntaxError_symbol(), type, arguments);
|
||||
isolate()->factory()->MakeSyntaxError_string(), type, arguments);
|
||||
}
|
||||
|
||||
|
||||
@ -4928,7 +4928,7 @@ Expression* Parser::NewThrowTypeError(Handle<String> type,
|
||||
Vector< Handle<Object> > arguments =
|
||||
HandleVector<Object>(elements, ARRAY_SIZE(elements));
|
||||
return NewThrowError(
|
||||
isolate()->factory()->MakeTypeError_symbol(), type, arguments);
|
||||
isolate()->factory()->MakeTypeError_string(), type, arguments);
|
||||
}
|
||||
|
||||
|
||||
|
@ -113,7 +113,7 @@ CompleteParserRecorder::CompleteParserRecorder()
|
||||
literal_chars_(0),
|
||||
symbol_store_(0),
|
||||
symbol_keys_(0),
|
||||
symbol_table_(vector_compare),
|
||||
string_table_(vector_compare),
|
||||
symbol_id_(0) {
|
||||
}
|
||||
|
||||
@ -123,7 +123,7 @@ void CompleteParserRecorder::LogSymbol(int start,
|
||||
bool is_ascii,
|
||||
Vector<const byte> literal_bytes) {
|
||||
Key key = { is_ascii, literal_bytes };
|
||||
HashMap::Entry* entry = symbol_table_.Lookup(&key, hash, true);
|
||||
HashMap::Entry* entry = string_table_.Lookup(&key, hash, true);
|
||||
int id = static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
|
||||
if (id == 0) {
|
||||
// Copy literal contents for later comparison.
|
||||
|
@ -221,7 +221,7 @@ class CompleteParserRecorder: public FunctionLoggingParserRecorder {
|
||||
Collector<byte> literal_chars_;
|
||||
Collector<byte> symbol_store_;
|
||||
Collector<Key> symbol_keys_;
|
||||
HashMap symbol_table_;
|
||||
HashMap string_table_;
|
||||
int symbol_id_;
|
||||
};
|
||||
|
||||
|
@ -362,7 +362,7 @@ void PrettyPrinter::VisitThrow(Throw* node) {
|
||||
void PrettyPrinter::VisitProperty(Property* node) {
|
||||
Expression* key = node->key();
|
||||
Literal* literal = key->AsLiteral();
|
||||
if (literal != NULL && literal->handle()->IsSymbol()) {
|
||||
if (literal != NULL && literal->handle()->IsInternalizedString()) {
|
||||
Print("(");
|
||||
Visit(node->obj());
|
||||
Print(").");
|
||||
@ -1068,7 +1068,7 @@ void AstPrinter::VisitProperty(Property* node) {
|
||||
IndentedScope indent(this, "PROPERTY", node);
|
||||
Visit(node->obj());
|
||||
Literal* literal = node->key()->AsLiteral();
|
||||
if (literal != NULL && literal->handle()->IsSymbol()) {
|
||||
if (literal != NULL && literal->handle()->IsInternalizedString()) {
|
||||
PrintLiteralIndented("NAME", literal->handle(), false);
|
||||
} else {
|
||||
PrintIndentedVisit("KEY", node->key());
|
||||
|
@ -48,9 +48,9 @@ class Descriptor BASE_EMBEDDED {
|
||||
return Smi::cast(value)->value();
|
||||
}
|
||||
|
||||
MUST_USE_RESULT MaybeObject* KeyToSymbol() {
|
||||
if (!StringShape(key_).IsSymbol()) {
|
||||
MaybeObject* maybe_result = HEAP->LookupSymbol(key_);
|
||||
MUST_USE_RESULT MaybeObject* KeyToInternalizedString() {
|
||||
if (!StringShape(key_).IsInternalized()) {
|
||||
MaybeObject* maybe_result = HEAP->InternalizeString(key_);
|
||||
if (!maybe_result->To(&key_)) return maybe_result;
|
||||
}
|
||||
return key_;
|
||||
|
@ -253,7 +253,7 @@ bool Rewriter::Rewrite(CompilationInfo* info) {
|
||||
ZoneList<Statement*>* body = function->body();
|
||||
if (!body->is_empty()) {
|
||||
Variable* result = scope->NewTemporary(
|
||||
info->isolate()->factory()->result_symbol());
|
||||
info->isolate()->factory()->result_string());
|
||||
Processor processor(result, info->zone());
|
||||
processor.Process(body);
|
||||
if (processor.HasStackOverflow()) return false;
|
||||
|
133
src/runtime.cc
133
src/runtime.cc
@ -290,40 +290,41 @@ static Handle<Map> ComputeObjectLiteralMap(
|
||||
Isolate* isolate = context->GetIsolate();
|
||||
int properties_length = constant_properties->length();
|
||||
int number_of_properties = properties_length / 2;
|
||||
// Check that there are only symbols and array indices among keys.
|
||||
int number_of_symbol_keys = 0;
|
||||
// Check that there are only internal strings and array indices among keys.
|
||||
int number_of_string_keys = 0;
|
||||
for (int p = 0; p != properties_length; p += 2) {
|
||||
Object* key = constant_properties->get(p);
|
||||
uint32_t element_index = 0;
|
||||
if (key->IsSymbol()) {
|
||||
number_of_symbol_keys++;
|
||||
if (key->IsInternalizedString()) {
|
||||
number_of_string_keys++;
|
||||
} else if (key->ToArrayIndex(&element_index)) {
|
||||
// An index key does not require space in the property backing store.
|
||||
number_of_properties--;
|
||||
} else {
|
||||
// Bail out as a non-symbol non-index key makes caching impossible.
|
||||
// Bail out as a non-internalized-string non-index key makes caching
|
||||
// impossible.
|
||||
// ASSERT to make sure that the if condition after the loop is false.
|
||||
ASSERT(number_of_symbol_keys != number_of_properties);
|
||||
ASSERT(number_of_string_keys != number_of_properties);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If we only have symbols and array indices among keys then we can
|
||||
// use the map cache in the native context.
|
||||
// If we only have internalized strings and array indices among keys then we
|
||||
// can use the map cache in the native context.
|
||||
const int kMaxKeys = 10;
|
||||
if ((number_of_symbol_keys == number_of_properties) &&
|
||||
(number_of_symbol_keys < kMaxKeys)) {
|
||||
if ((number_of_string_keys == number_of_properties) &&
|
||||
(number_of_string_keys < kMaxKeys)) {
|
||||
// Create the fixed array with the key.
|
||||
Handle<FixedArray> keys =
|
||||
isolate->factory()->NewFixedArray(number_of_symbol_keys);
|
||||
if (number_of_symbol_keys > 0) {
|
||||
isolate->factory()->NewFixedArray(number_of_string_keys);
|
||||
if (number_of_string_keys > 0) {
|
||||
int index = 0;
|
||||
for (int p = 0; p < properties_length; p += 2) {
|
||||
Object* key = constant_properties->get(p);
|
||||
if (key->IsSymbol()) {
|
||||
if (key->IsInternalizedString()) {
|
||||
keys->set(index++, key);
|
||||
}
|
||||
}
|
||||
ASSERT(index == number_of_symbol_keys);
|
||||
ASSERT(index == number_of_string_keys);
|
||||
}
|
||||
*is_result_from_cache = true;
|
||||
return isolate->factory()->ObjectLiteralMapFromCache(context, keys);
|
||||
@ -396,7 +397,7 @@ static Handle<Object> CreateObjectLiteralBoilerplate(
|
||||
}
|
||||
Handle<Object> result;
|
||||
uint32_t element_index = 0;
|
||||
if (key->IsSymbol()) {
|
||||
if (key->IsInternalizedString()) {
|
||||
if (Handle<String>::cast(key)->AsArrayIndex(&element_index)) {
|
||||
// Array index as string (uint32).
|
||||
result = JSObject::SetOwnElement(
|
||||
@ -954,7 +955,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPrototype) {
|
||||
do {
|
||||
if (obj->IsAccessCheckNeeded() &&
|
||||
!isolate->MayNamedAccess(JSObject::cast(obj),
|
||||
isolate->heap()->Proto_symbol(),
|
||||
isolate->heap()->proto_string(),
|
||||
v8::ACCESS_GET)) {
|
||||
isolate->ReportFailedAccessCheck(JSObject::cast(obj), v8::ACCESS_GET);
|
||||
return isolate->heap()->undefined_value();
|
||||
@ -1779,7 +1780,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpInitializeObject) {
|
||||
CONVERT_ARG_CHECKED(String, source, 1);
|
||||
// If source is the empty string we set it to "(?:)" instead as
|
||||
// suggested by ECMA-262, 5th, section 15.10.4.1.
|
||||
if (source->length() == 0) source = isolate->heap()->query_colon_symbol();
|
||||
if (source->length() == 0) source = isolate->heap()->query_colon_string();
|
||||
|
||||
Object* global = args[2];
|
||||
if (!global->IsTrue()) global = isolate->heap()->false_value();
|
||||
@ -1816,27 +1817,27 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpInitializeObject) {
|
||||
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
|
||||
Heap* heap = isolate->heap();
|
||||
MaybeObject* result;
|
||||
result = regexp->SetLocalPropertyIgnoreAttributes(heap->source_symbol(),
|
||||
result = regexp->SetLocalPropertyIgnoreAttributes(heap->source_string(),
|
||||
source,
|
||||
final);
|
||||
// TODO(jkummerow): Turn these back into ASSERTs when we can be certain
|
||||
// that it never fires in Release mode in the wild.
|
||||
CHECK(!result->IsFailure());
|
||||
result = regexp->SetLocalPropertyIgnoreAttributes(heap->global_symbol(),
|
||||
result = regexp->SetLocalPropertyIgnoreAttributes(heap->global_string(),
|
||||
global,
|
||||
final);
|
||||
CHECK(!result->IsFailure());
|
||||
result =
|
||||
regexp->SetLocalPropertyIgnoreAttributes(heap->ignore_case_symbol(),
|
||||
regexp->SetLocalPropertyIgnoreAttributes(heap->ignore_case_string(),
|
||||
ignoreCase,
|
||||
final);
|
||||
CHECK(!result->IsFailure());
|
||||
result = regexp->SetLocalPropertyIgnoreAttributes(heap->multiline_symbol(),
|
||||
result = regexp->SetLocalPropertyIgnoreAttributes(heap->multiline_string(),
|
||||
multiline,
|
||||
final);
|
||||
CHECK(!result->IsFailure());
|
||||
result =
|
||||
regexp->SetLocalPropertyIgnoreAttributes(heap->last_index_symbol(),
|
||||
regexp->SetLocalPropertyIgnoreAttributes(heap->last_index_string(),
|
||||
Smi::FromInt(0),
|
||||
writable);
|
||||
CHECK(!result->IsFailure());
|
||||
@ -1860,7 +1861,7 @@ static Handle<JSFunction> InstallBuiltin(Isolate* isolate,
|
||||
Handle<JSObject> holder,
|
||||
const char* name,
|
||||
Builtins::Name builtin_name) {
|
||||
Handle<String> key = isolate->factory()->LookupUtf8Symbol(name);
|
||||
Handle<String> key = isolate->factory()->InternalizeUtf8String(name);
|
||||
Handle<Code> code(isolate->builtins()->builtin(builtin_name));
|
||||
Handle<JSFunction> optimized =
|
||||
isolate->factory()->NewFunction(key,
|
||||
@ -2084,7 +2085,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetReadOnlyPrototype) {
|
||||
RUNTIME_ASSERT(args.length() == 1);
|
||||
CONVERT_ARG_CHECKED(JSFunction, function, 0);
|
||||
|
||||
String* name = isolate->heap()->prototype_symbol();
|
||||
String* name = isolate->heap()->prototype_string();
|
||||
|
||||
if (function->HasFastProperties()) {
|
||||
// Construct a new field descriptor with updated attributes.
|
||||
@ -3768,13 +3769,13 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToRadixString) {
|
||||
// Slow case.
|
||||
CONVERT_DOUBLE_ARG_CHECKED(value, 0);
|
||||
if (isnan(value)) {
|
||||
return *isolate->factory()->nan_symbol();
|
||||
return *isolate->factory()->nan_string();
|
||||
}
|
||||
if (isinf(value)) {
|
||||
if (value < 0) {
|
||||
return *isolate->factory()->minus_infinity_symbol();
|
||||
return *isolate->factory()->minus_infinity_string();
|
||||
}
|
||||
return *isolate->factory()->infinity_symbol();
|
||||
return *isolate->factory()->infinity_string();
|
||||
}
|
||||
char* str = DoubleToRadixCString(value, radix);
|
||||
MaybeObject* result =
|
||||
@ -4756,7 +4757,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalPropertyNames) {
|
||||
int dest_pos = 0;
|
||||
for (int i = 0; i < total_property_count; i++) {
|
||||
Object* name = old_names->get(i);
|
||||
if (name == isolate->heap()->hidden_symbol()) {
|
||||
if (name == isolate->heap()->hidden_string()) {
|
||||
continue;
|
||||
}
|
||||
names->set(dest_pos++, name);
|
||||
@ -4917,8 +4918,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArgumentsProperty) {
|
||||
}
|
||||
|
||||
// Handle special arguments properties.
|
||||
if (key->Equals(isolate->heap()->length_symbol())) return Smi::FromInt(n);
|
||||
if (key->Equals(isolate->heap()->callee_symbol())) {
|
||||
if (key->Equals(isolate->heap()->length_string())) return Smi::FromInt(n);
|
||||
if (key->Equals(isolate->heap()->callee_string())) {
|
||||
Object* function = frame->function();
|
||||
if (function->IsJSFunction() &&
|
||||
!JSFunction::cast(function)->shared()->is_classic_mode()) {
|
||||
@ -4956,38 +4957,38 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_Typeof) {
|
||||
NoHandleAllocation ha(isolate);
|
||||
|
||||
Object* obj = args[0];
|
||||
if (obj->IsNumber()) return isolate->heap()->number_symbol();
|
||||
if (obj->IsNumber()) return isolate->heap()->number_string();
|
||||
HeapObject* heap_obj = HeapObject::cast(obj);
|
||||
|
||||
// typeof an undetectable object is 'undefined'
|
||||
if (heap_obj->map()->is_undetectable()) {
|
||||
return isolate->heap()->undefined_symbol();
|
||||
return isolate->heap()->undefined_string();
|
||||
}
|
||||
|
||||
InstanceType instance_type = heap_obj->map()->instance_type();
|
||||
if (instance_type < FIRST_NONSTRING_TYPE) {
|
||||
return isolate->heap()->string_symbol();
|
||||
return isolate->heap()->string_string();
|
||||
}
|
||||
|
||||
switch (instance_type) {
|
||||
case ODDBALL_TYPE:
|
||||
if (heap_obj->IsTrue() || heap_obj->IsFalse()) {
|
||||
return isolate->heap()->boolean_symbol();
|
||||
return isolate->heap()->boolean_string();
|
||||
}
|
||||
if (heap_obj->IsNull()) {
|
||||
return FLAG_harmony_typeof
|
||||
? isolate->heap()->null_symbol()
|
||||
: isolate->heap()->object_symbol();
|
||||
? isolate->heap()->null_string()
|
||||
: isolate->heap()->object_string();
|
||||
}
|
||||
ASSERT(heap_obj->IsUndefined());
|
||||
return isolate->heap()->undefined_symbol();
|
||||
return isolate->heap()->undefined_string();
|
||||
case JS_FUNCTION_TYPE:
|
||||
case JS_FUNCTION_PROXY_TYPE:
|
||||
return isolate->heap()->function_symbol();
|
||||
return isolate->heap()->function_string();
|
||||
default:
|
||||
// For any kind of object not handled above, the spec rule for
|
||||
// host objects gives that it is okay to return "object"
|
||||
return isolate->heap()->object_symbol();
|
||||
return isolate->heap()->object_string();
|
||||
}
|
||||
}
|
||||
|
||||
@ -6319,7 +6320,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) {
|
||||
|
||||
int special_length = special->length();
|
||||
if (!array->HasFastObjectElements()) {
|
||||
return isolate->Throw(isolate->heap()->illegal_argument_symbol());
|
||||
return isolate->Throw(isolate->heap()->illegal_argument_string());
|
||||
}
|
||||
FixedArray* fixed_array = FixedArray::cast(array->elements());
|
||||
if (fixed_array->length() < array_length) {
|
||||
@ -6353,21 +6354,21 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) {
|
||||
// Get the position and check that it is a positive smi.
|
||||
i++;
|
||||
if (i >= array_length) {
|
||||
return isolate->Throw(isolate->heap()->illegal_argument_symbol());
|
||||
return isolate->Throw(isolate->heap()->illegal_argument_string());
|
||||
}
|
||||
Object* next_smi = fixed_array->get(i);
|
||||
if (!next_smi->IsSmi()) {
|
||||
return isolate->Throw(isolate->heap()->illegal_argument_symbol());
|
||||
return isolate->Throw(isolate->heap()->illegal_argument_string());
|
||||
}
|
||||
pos = Smi::cast(next_smi)->value();
|
||||
if (pos < 0) {
|
||||
return isolate->Throw(isolate->heap()->illegal_argument_symbol());
|
||||
return isolate->Throw(isolate->heap()->illegal_argument_string());
|
||||
}
|
||||
}
|
||||
ASSERT(pos >= 0);
|
||||
ASSERT(len >= 0);
|
||||
if (pos > special_length || len > special_length - pos) {
|
||||
return isolate->Throw(isolate->heap()->illegal_argument_symbol());
|
||||
return isolate->Throw(isolate->heap()->illegal_argument_string());
|
||||
}
|
||||
increment = len;
|
||||
} else if (elt->IsString()) {
|
||||
@ -6379,7 +6380,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) {
|
||||
}
|
||||
} else {
|
||||
ASSERT(!elt->IsTheHole());
|
||||
return isolate->Throw(isolate->heap()->illegal_argument_symbol());
|
||||
return isolate->Throw(isolate->heap()->illegal_argument_string());
|
||||
}
|
||||
if (increment > String::kMaxLength - position) {
|
||||
isolate->context()->mark_out_of_memory();
|
||||
@ -6429,7 +6430,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderJoin) {
|
||||
CONVERT_ARG_CHECKED(String, separator, 2);
|
||||
|
||||
if (!array->HasFastObjectElements()) {
|
||||
return isolate->Throw(isolate->heap()->illegal_argument_symbol());
|
||||
return isolate->Throw(isolate->heap()->illegal_argument_string());
|
||||
}
|
||||
FixedArray* fixed_array = FixedArray::cast(array->elements());
|
||||
if (fixed_array->length() < array_length) {
|
||||
@ -6455,7 +6456,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderJoin) {
|
||||
Object* element_obj = fixed_array->get(i);
|
||||
if (!element_obj->IsString()) {
|
||||
// TODO(1161): handle this case.
|
||||
return isolate->Throw(isolate->heap()->illegal_argument_symbol());
|
||||
return isolate->Throw(isolate->heap()->illegal_argument_string());
|
||||
}
|
||||
String* element = String::cast(element_obj);
|
||||
int increment = element->length();
|
||||
@ -7451,11 +7452,11 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionBindArguments) {
|
||||
bound_function->set_function_bindings(*new_bindings);
|
||||
|
||||
// Update length.
|
||||
Handle<String> length_symbol = isolate->factory()->length_symbol();
|
||||
Handle<String> length_string = isolate->factory()->length_string();
|
||||
Handle<Object> new_length(args.at<Object>(3));
|
||||
PropertyAttributes attr =
|
||||
static_cast<PropertyAttributes>(DONT_DELETE | DONT_ENUM | READ_ONLY);
|
||||
ForceSetProperty(bound_function, length_symbol, new_length, attr);
|
||||
ForceSetProperty(bound_function, length_string, new_length, attr);
|
||||
return *bound_function;
|
||||
}
|
||||
|
||||
@ -7708,7 +7709,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ForceParallelRecompile) {
|
||||
HandleScope handle_scope(isolate);
|
||||
ASSERT(FLAG_parallel_recompilation && FLAG_manual_parallel_recompilation);
|
||||
if (!isolate->optimizing_compiler_thread()->IsQueueAvailable()) {
|
||||
return isolate->Throw(*isolate->factory()->LookupOneByteSymbol(
|
||||
return isolate->Throw(*isolate->factory()->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("Recompile queue is full.")));
|
||||
}
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
|
||||
@ -10163,7 +10164,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CheckExecutionState) {
|
||||
if (isolate->debug()->break_id() == 0 ||
|
||||
break_id != isolate->debug()->break_id()) {
|
||||
return isolate->Throw(
|
||||
isolate->heap()->illegal_execution_state_symbol());
|
||||
isolate->heap()->illegal_execution_state_string());
|
||||
}
|
||||
|
||||
return isolate->heap()->true_value();
|
||||
@ -11686,7 +11687,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_PrepareStep) {
|
||||
if (!maybe_check->ToObject(&check)) return maybe_check;
|
||||
}
|
||||
if (!args[1]->IsNumber() || !args[2]->IsNumber()) {
|
||||
return isolate->Throw(isolate->heap()->illegal_argument_symbol());
|
||||
return isolate->Throw(isolate->heap()->illegal_argument_string());
|
||||
}
|
||||
|
||||
// Get the step action and check validity.
|
||||
@ -11696,13 +11697,13 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_PrepareStep) {
|
||||
step_action != StepOut &&
|
||||
step_action != StepInMin &&
|
||||
step_action != StepMin) {
|
||||
return isolate->Throw(isolate->heap()->illegal_argument_symbol());
|
||||
return isolate->Throw(isolate->heap()->illegal_argument_string());
|
||||
}
|
||||
|
||||
// Get the number of steps.
|
||||
int step_count = NumberToInt32(args[2]);
|
||||
if (step_count < 1) {
|
||||
return isolate->Throw(isolate->heap()->illegal_argument_symbol());
|
||||
return isolate->Throw(isolate->heap()->illegal_argument_string());
|
||||
}
|
||||
|
||||
// Clear all current stepping setup.
|
||||
@ -11801,7 +11802,7 @@ static Handle<Object> GetArgumentsObject(Isolate* isolate,
|
||||
// does not support eval) then create an 'arguments' object.
|
||||
int index;
|
||||
if (scope_info->StackLocalCount() > 0) {
|
||||
index = scope_info->StackSlotIndex(isolate->heap()->arguments_symbol());
|
||||
index = scope_info->StackSlotIndex(isolate->heap()->arguments_string());
|
||||
if (index != -1) {
|
||||
return Handle<Object>(frame->GetExpression(index), isolate);
|
||||
}
|
||||
@ -11811,7 +11812,7 @@ static Handle<Object> GetArgumentsObject(Isolate* isolate,
|
||||
VariableMode mode;
|
||||
InitializationFlag init_flag;
|
||||
index = scope_info->ContextSlotIndex(
|
||||
isolate->heap()->arguments_symbol(), &mode, &init_flag);
|
||||
isolate->heap()->arguments_string(), &mode, &init_flag);
|
||||
if (index != -1) {
|
||||
return Handle<Object>(function_context->get(index), isolate);
|
||||
}
|
||||
@ -12669,7 +12670,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditRestartFrame) {
|
||||
const char* error_message =
|
||||
LiveEdit::RestartFrame(it.frame(), isolate->runtime_zone());
|
||||
if (error_message) {
|
||||
return *(isolate->factory()->LookupUtf8Symbol(error_message));
|
||||
return *(isolate->factory()->InternalizeUtf8String(error_message));
|
||||
}
|
||||
return heap->true_value();
|
||||
}
|
||||
@ -12859,7 +12860,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_MarkOneShotGetter) {
|
||||
ASSERT_EQ(args.length(), 1);
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
|
||||
HandleScope scope(isolate);
|
||||
Handle<String> key = isolate->factory()->hidden_stack_trace_symbol();
|
||||
Handle<String> key = isolate->factory()->hidden_stack_trace_string();
|
||||
JSObject::SetHiddenProperty(fun, key, key);
|
||||
return *fun;
|
||||
}
|
||||
@ -12871,7 +12872,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOverflowedStackTrace) {
|
||||
HandleScope scope(isolate);
|
||||
ASSERT_EQ(args.length(), 1);
|
||||
CONVERT_ARG_CHECKED(JSObject, error_object, 0);
|
||||
String* key = isolate->heap()->hidden_stack_trace_symbol();
|
||||
String* key = isolate->heap()->hidden_stack_trace_string();
|
||||
Object* result = error_object->GetHiddenProperty(key);
|
||||
RUNTIME_ASSERT(result->IsJSArray() ||
|
||||
result->IsString() ||
|
||||
@ -12886,7 +12887,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SetOverflowedStackTrace) {
|
||||
ASSERT_EQ(args.length(), 2);
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSObject, error_object, 0);
|
||||
CONVERT_ARG_HANDLE_CHECKED(HeapObject, value, 1);
|
||||
Handle<String> key = isolate->factory()->hidden_stack_trace_symbol();
|
||||
Handle<String> key = isolate->factory()->hidden_stack_trace_string();
|
||||
if (value->IsUndefined()) {
|
||||
error_object->DeleteHiddenProperty(*key);
|
||||
} else {
|
||||
@ -13246,14 +13247,14 @@ MaybeObject* Runtime::InitializeIntrinsicFunctionNames(Heap* heap,
|
||||
ASSERT(dictionary != NULL);
|
||||
ASSERT(StringDictionary::cast(dictionary)->NumberOfElements() == 0);
|
||||
for (int i = 0; i < kNumFunctions; ++i) {
|
||||
Object* name_symbol;
|
||||
{ MaybeObject* maybe_name_symbol =
|
||||
heap->LookupUtf8Symbol(kIntrinsicFunctions[i].name);
|
||||
if (!maybe_name_symbol->ToObject(&name_symbol)) return maybe_name_symbol;
|
||||
Object* name_string;
|
||||
{ MaybeObject* maybe_name_string =
|
||||
heap->InternalizeUtf8String(kIntrinsicFunctions[i].name);
|
||||
if (!maybe_name_string->ToObject(&name_string)) return maybe_name_string;
|
||||
}
|
||||
StringDictionary* string_dictionary = StringDictionary::cast(dictionary);
|
||||
{ MaybeObject* maybe_dictionary = string_dictionary->Add(
|
||||
String::cast(name_symbol),
|
||||
String::cast(name_string),
|
||||
Smi::FromInt(i),
|
||||
PropertyDetails(NONE, NORMAL));
|
||||
if (!maybe_dictionary->ToObject(&dictionary)) {
|
||||
@ -13267,7 +13268,7 @@ MaybeObject* Runtime::InitializeIntrinsicFunctionNames(Heap* heap,
|
||||
}
|
||||
|
||||
|
||||
const Runtime::Function* Runtime::FunctionForSymbol(Handle<String> name) {
|
||||
const Runtime::Function* Runtime::FunctionForName(Handle<String> name) {
|
||||
Heap* heap = name->GetHeap();
|
||||
int entry = heap->intrinsic_function_names()->FindEntry(*name);
|
||||
if (entry != kNotFound) {
|
||||
|
@ -642,15 +642,16 @@ class Runtime : public AllStatic {
|
||||
|
||||
static const int kNotFound = -1;
|
||||
|
||||
// Add symbols for all the intrinsic function names to a StringDictionary.
|
||||
// Add internalized strings for all the intrinsic function names to a
|
||||
// StringDictionary.
|
||||
// Returns failure if an allocation fails. In this case, it must be
|
||||
// retried with a new, empty StringDictionary, not with the same one.
|
||||
// Alternatively, heap initialization can be completely restarted.
|
||||
MUST_USE_RESULT static MaybeObject* InitializeIntrinsicFunctionNames(
|
||||
Heap* heap, Object* dictionary);
|
||||
|
||||
// Get the intrinsic function with the given name, which must be a symbol.
|
||||
static const Function* FunctionForSymbol(Handle<String> name);
|
||||
// Get the intrinsic function with the given name, which must be internalized.
|
||||
static const Function* FunctionForName(Handle<String> name);
|
||||
|
||||
// Get the intrinsic function with the given FunctionId.
|
||||
static const Function* FunctionForId(FunctionId id);
|
||||
|
@ -280,7 +280,7 @@ InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) {
|
||||
|
||||
|
||||
int ScopeInfo::StackSlotIndex(String* name) {
|
||||
ASSERT(name->IsSymbol());
|
||||
ASSERT(name->IsInternalizedString());
|
||||
if (length() > 0) {
|
||||
int start = StackLocalEntriesIndex();
|
||||
int end = StackLocalEntriesIndex() + StackLocalCount();
|
||||
@ -297,7 +297,7 @@ int ScopeInfo::StackSlotIndex(String* name) {
|
||||
int ScopeInfo::ContextSlotIndex(String* name,
|
||||
VariableMode* mode,
|
||||
InitializationFlag* init_flag) {
|
||||
ASSERT(name->IsSymbol());
|
||||
ASSERT(name->IsInternalizedString());
|
||||
ASSERT(mode != NULL);
|
||||
ASSERT(init_flag != NULL);
|
||||
if (length() > 0) {
|
||||
@ -329,7 +329,7 @@ int ScopeInfo::ContextSlotIndex(String* name,
|
||||
|
||||
|
||||
int ScopeInfo::ParameterIndex(String* name) {
|
||||
ASSERT(name->IsSymbol());
|
||||
ASSERT(name->IsInternalizedString());
|
||||
if (length() > 0) {
|
||||
// We must read parameters from the end since for
|
||||
// multiply declared parameters the value of the
|
||||
@ -349,7 +349,7 @@ int ScopeInfo::ParameterIndex(String* name) {
|
||||
|
||||
|
||||
int ScopeInfo::FunctionContextSlotIndex(String* name, VariableMode* mode) {
|
||||
ASSERT(name->IsSymbol());
|
||||
ASSERT(name->IsInternalizedString());
|
||||
ASSERT(mode != NULL);
|
||||
if (length() > 0) {
|
||||
if (FunctionVariableField::decode(Flags()) == CONTEXT &&
|
||||
@ -442,13 +442,13 @@ void ContextSlotCache::Update(Object* data,
|
||||
VariableMode mode,
|
||||
InitializationFlag init_flag,
|
||||
int slot_index) {
|
||||
String* symbol;
|
||||
String* internalized_name;
|
||||
ASSERT(slot_index > kNotFound);
|
||||
if (HEAP->LookupSymbolIfExists(name, &symbol)) {
|
||||
int index = Hash(data, symbol);
|
||||
if (HEAP->InternalizeStringIfExists(name, &internalized_name)) {
|
||||
int index = Hash(data, internalized_name);
|
||||
Key& key = keys_[index];
|
||||
key.data = data;
|
||||
key.name = symbol;
|
||||
key.name = internalized_name;
|
||||
// Please note value only takes a uint as index.
|
||||
values_[index] = Value(mode, init_flag, slot_index - kNotFound).raw();
|
||||
#ifdef DEBUG
|
||||
@ -470,8 +470,8 @@ void ContextSlotCache::ValidateEntry(Object* data,
|
||||
VariableMode mode,
|
||||
InitializationFlag init_flag,
|
||||
int slot_index) {
|
||||
String* symbol;
|
||||
if (HEAP->LookupSymbolIfExists(name, &symbol)) {
|
||||
String* internalized_name;
|
||||
if (HEAP->InternalizeStringIfExists(name, &internalized_name)) {
|
||||
int index = Hash(data, name);
|
||||
Key& key = keys_[index];
|
||||
ASSERT(key.data == data);
|
||||
|
@ -52,8 +52,8 @@ namespace internal {
|
||||
static bool Match(void* key1, void* key2) {
|
||||
String* name1 = *reinterpret_cast<String**>(key1);
|
||||
String* name2 = *reinterpret_cast<String**>(key2);
|
||||
ASSERT(name1->IsSymbol());
|
||||
ASSERT(name2->IsSymbol());
|
||||
ASSERT(name1->IsInternalizedString());
|
||||
ASSERT(name2->IsInternalizedString());
|
||||
return name1 == name2;
|
||||
}
|
||||
|
||||
@ -182,7 +182,7 @@ void Scope::SetDefaults(ScopeType type,
|
||||
Handle<ScopeInfo> scope_info) {
|
||||
outer_scope_ = outer_scope;
|
||||
type_ = type;
|
||||
scope_name_ = isolate_->factory()->empty_symbol();
|
||||
scope_name_ = isolate_->factory()->empty_string();
|
||||
dynamics_ = NULL;
|
||||
receiver_ = NULL;
|
||||
function_ = NULL;
|
||||
@ -335,7 +335,7 @@ void Scope::Initialize() {
|
||||
if (is_declaration_scope()) {
|
||||
Variable* var =
|
||||
variables_.Declare(this,
|
||||
isolate_->factory()->this_symbol(),
|
||||
isolate_->factory()->this_string(),
|
||||
VAR,
|
||||
false,
|
||||
Variable::THIS,
|
||||
@ -352,7 +352,7 @@ void Scope::Initialize() {
|
||||
// Note that it might never be accessed, in which case it won't be
|
||||
// allocated during variable allocation.
|
||||
variables_.Declare(this,
|
||||
isolate_->factory()->arguments_symbol(),
|
||||
isolate_->factory()->arguments_string(),
|
||||
VAR,
|
||||
true,
|
||||
Variable::ARGUMENTS,
|
||||
@ -1198,7 +1198,7 @@ bool Scope::MustAllocateInContext(Variable* var) {
|
||||
bool Scope::HasArgumentsParameter() {
|
||||
for (int i = 0; i < params_.length(); i++) {
|
||||
if (params_[i]->name().is_identical_to(
|
||||
isolate_->factory()->arguments_symbol())) {
|
||||
isolate_->factory()->arguments_string())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -1218,7 +1218,7 @@ void Scope::AllocateHeapSlot(Variable* var) {
|
||||
|
||||
void Scope::AllocateParameterLocals() {
|
||||
ASSERT(is_function_scope());
|
||||
Variable* arguments = LocalLookup(isolate_->factory()->arguments_symbol());
|
||||
Variable* arguments = LocalLookup(isolate_->factory()->arguments_string());
|
||||
ASSERT(arguments != NULL); // functions have 'arguments' declared implicitly
|
||||
|
||||
bool uses_nonstrict_arguments = false;
|
||||
@ -1274,7 +1274,7 @@ void Scope::AllocateParameterLocals() {
|
||||
|
||||
void Scope::AllocateNonParameterLocal(Variable* var) {
|
||||
ASSERT(var->scope() == this);
|
||||
ASSERT(!var->IsVariable(isolate_->factory()->result_symbol()) ||
|
||||
ASSERT(!var->IsVariable(isolate_->factory()->result_string()) ||
|
||||
!var->IsStackLocal());
|
||||
if (var->IsUnallocated() && MustAllocate(var)) {
|
||||
if (MustAllocateInContext(var)) {
|
||||
@ -1359,7 +1359,7 @@ void Scope::AllocateModulesRecursively(Scope* host_scope) {
|
||||
if (already_resolved()) return;
|
||||
if (is_module_scope()) {
|
||||
ASSERT(interface_->IsFrozen());
|
||||
Handle<String> name = isolate_->factory()->LookupOneByteSymbol(
|
||||
Handle<String> name = isolate_->factory()->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR(".module"));
|
||||
ASSERT(module_var_ == NULL);
|
||||
module_var_ = host_scope->NewInternal(name);
|
||||
|
@ -1356,9 +1356,9 @@ void PartialSerializer::SerializeObject(
|
||||
// should go through the root array or through the partial snapshot cache.
|
||||
// If this is not the case you may have to add something to the root array.
|
||||
ASSERT(!startup_serializer_->address_mapper()->IsMapped(heap_object));
|
||||
// All the symbols that the partial snapshot needs should be either in the
|
||||
// root table or in the partial snapshot cache.
|
||||
ASSERT(!heap_object->IsSymbol());
|
||||
// All the internalized strings that the partial snapshot needs should be
|
||||
// either in the root table or in the partial snapshot cache.
|
||||
ASSERT(!heap_object->IsInternalizedString());
|
||||
|
||||
if (address_mapper_.IsMapped(heap_object)) {
|
||||
int space = SpaceOfObject(heap_object);
|
||||
|
@ -638,7 +638,7 @@ class StartupSerializer : public Serializer {
|
||||
// Serialize the current state of the heap. The order is:
|
||||
// 1) Strong references.
|
||||
// 2) Partial snapshot cache.
|
||||
// 3) Weak references (e.g. the symbol table).
|
||||
// 3) Weak references (e.g. the string table).
|
||||
virtual void SerializeStrongReferences();
|
||||
virtual void SerializeObject(Object* o,
|
||||
HowToCode how_to_code,
|
||||
|
@ -493,7 +493,7 @@ void StringStream::PrintFunction(Object* f, Object* receiver, Code** code) {
|
||||
// Common case: on-stack function present and resolved.
|
||||
PrintPrototype(fun, receiver);
|
||||
*code = fun->code();
|
||||
} else if (f->IsSymbol()) {
|
||||
} else if (f->IsInternalizedString()) {
|
||||
// Unresolved and megamorphic calls: Instead of the function
|
||||
// we have the function name on the stack.
|
||||
PrintName(f);
|
||||
|
@ -63,7 +63,7 @@ Code* StubCache::Set(String* name, Map* map, Code* code) {
|
||||
// Validate that the name does not move on scavenge, and that we
|
||||
// can use identity checks instead of string equality checks.
|
||||
ASSERT(!heap()->InNewSpace(name));
|
||||
ASSERT(name->IsSymbol());
|
||||
ASSERT(name->IsInternalizedString());
|
||||
|
||||
// The state bits are not important to the hash function because
|
||||
// the stub cache only contains monomorphic stubs. Make sure that
|
||||
@ -410,7 +410,7 @@ Handle<Code> StubCache::ComputeStoreField(Handle<String> name,
|
||||
Handle<Code> StubCache::ComputeKeyedLoadElement(Handle<Map> receiver_map) {
|
||||
Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC);
|
||||
Handle<String> name =
|
||||
isolate()->factory()->KeyedLoadElementMonomorphic_symbol();
|
||||
isolate()->factory()->KeyedLoadElementMonomorphic_string();
|
||||
|
||||
Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate_);
|
||||
if (probe->IsCode()) return Handle<Code>::cast(probe);
|
||||
@ -438,8 +438,8 @@ Handle<Code> StubCache::ComputeKeyedStoreElement(
|
||||
stub_kind == KeyedStoreIC::STORE_AND_GROW_NO_TRANSITION);
|
||||
|
||||
Handle<String> name = stub_kind == KeyedStoreIC::STORE_NO_TRANSITION
|
||||
? isolate()->factory()->KeyedStoreElementMonomorphic_symbol()
|
||||
: isolate()->factory()->KeyedStoreAndGrowElementMonomorphic_symbol();
|
||||
? isolate()->factory()->KeyedStoreElementMonomorphic_string()
|
||||
: isolate()->factory()->KeyedStoreAndGrowElementMonomorphic_string();
|
||||
|
||||
Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate_);
|
||||
if (probe->IsCode()) return Handle<Code>::cast(probe);
|
||||
|
@ -321,8 +321,8 @@ static TypeInfo TypeFromCompareType(CompareIC::State state) {
|
||||
return TypeInfo::Smi();
|
||||
case CompareIC::NUMBER:
|
||||
return TypeInfo::Number();
|
||||
case CompareIC::SYMBOL:
|
||||
return TypeInfo::Symbol();
|
||||
case CompareIC::INTERNALIZED_STRING:
|
||||
return TypeInfo::InternalizedString();
|
||||
case CompareIC::STRING:
|
||||
return TypeInfo::String();
|
||||
case CompareIC::OBJECT:
|
||||
|
@ -65,12 +65,12 @@ class TypeInfo {
|
||||
static TypeInfo Integer32() { return TypeInfo(kInteger32); }
|
||||
// We know it's a Smi.
|
||||
static TypeInfo Smi() { return TypeInfo(kSmi); }
|
||||
// We know it's a Symbol.
|
||||
static TypeInfo Symbol() { return TypeInfo(kSymbol); }
|
||||
// We know it's a heap number.
|
||||
static TypeInfo Double() { return TypeInfo(kDouble); }
|
||||
// We know it's a string.
|
||||
static TypeInfo String() { return TypeInfo(kString); }
|
||||
// We know it's an internalized string.
|
||||
static TypeInfo InternalizedString() { return TypeInfo(kInternalizedString); }
|
||||
// We know it's a non-primitive (object) type.
|
||||
static TypeInfo NonPrimitive() { return TypeInfo(kNonPrimitive); }
|
||||
// We haven't started collecting info yet.
|
||||
@ -140,14 +140,14 @@ class TypeInfo {
|
||||
return ((type_ & kSmi) == kSmi);
|
||||
}
|
||||
|
||||
inline bool IsSymbol() {
|
||||
inline bool IsInternalizedString() {
|
||||
ASSERT(type_ != kUninitialized);
|
||||
return ((type_ & kSymbol) == kSymbol);
|
||||
return ((type_ & kInternalizedString) == kInternalizedString);
|
||||
}
|
||||
|
||||
inline bool IsNonSymbol() {
|
||||
inline bool IsNonInternalizedString() {
|
||||
ASSERT(type_ != kUninitialized);
|
||||
return ((type_ & kSymbol) == kString);
|
||||
return ((type_ & kInternalizedString) == kString);
|
||||
}
|
||||
|
||||
inline bool IsInteger32() {
|
||||
@ -181,7 +181,7 @@ class TypeInfo {
|
||||
case kNumber: return "Number";
|
||||
case kInteger32: return "Integer32";
|
||||
case kSmi: return "Smi";
|
||||
case kSymbol: return "Symbol";
|
||||
case kInternalizedString: return "InternalizedString";
|
||||
case kDouble: return "Double";
|
||||
case kString: return "String";
|
||||
case kNonPrimitive: return "Object";
|
||||
@ -193,16 +193,16 @@ class TypeInfo {
|
||||
|
||||
private:
|
||||
enum Type {
|
||||
kUnknown = 0, // 0000000
|
||||
kPrimitive = 0x10, // 0010000
|
||||
kNumber = 0x11, // 0010001
|
||||
kInteger32 = 0x13, // 0010011
|
||||
kSmi = 0x17, // 0010111
|
||||
kDouble = 0x19, // 0011001
|
||||
kString = 0x30, // 0110000
|
||||
kSymbol = 0x32, // 0110010
|
||||
kNonPrimitive = 0x40, // 1000000
|
||||
kUninitialized = 0x7f // 1111111
|
||||
kUnknown = 0, // 0000000
|
||||
kPrimitive = 0x10, // 0010000
|
||||
kNumber = 0x11, // 0010001
|
||||
kInteger32 = 0x13, // 0010011
|
||||
kSmi = 0x17, // 0010111
|
||||
kDouble = 0x19, // 0011001
|
||||
kString = 0x30, // 0110000
|
||||
kInternalizedString = 0x32, // 0110010
|
||||
kNonPrimitive = 0x40, // 1000000
|
||||
kUninitialized = 0x7f // 1111111
|
||||
};
|
||||
|
||||
explicit inline TypeInfo(Type t) : type_(t) { }
|
||||
|
@ -98,7 +98,7 @@ namespace internal {
|
||||
SC(alive_after_last_gc, V8.AliveAfterLastGC) \
|
||||
SC(objs_since_last_young, V8.ObjsSinceLastYoung) \
|
||||
SC(objs_since_last_full, V8.ObjsSinceLastFull) \
|
||||
SC(symbol_table_capacity, V8.SymbolTableCapacity) \
|
||||
SC(string_table_capacity, V8.StringTableCapacity) \
|
||||
SC(number_of_symbols, V8.NumberOfSymbols) \
|
||||
SC(script_wrappers, V8.ScriptWrappers) \
|
||||
SC(call_initialize_stubs, V8.CallInitializeStubs) \
|
||||
|
@ -76,7 +76,7 @@ Variable::Variable(Scope* scope,
|
||||
initialization_flag_(initialization_flag),
|
||||
interface_(interface) {
|
||||
// Names must be canonicalized for fast equality checks.
|
||||
ASSERT(name->IsSymbol());
|
||||
ASSERT(name->IsInternalizedString());
|
||||
// Var declared variables never need initialization.
|
||||
ASSERT(!(mode == VAR && initialization_flag == kNeedsInitialization));
|
||||
}
|
||||
|
@ -131,7 +131,7 @@ class Variable: public ZoneObject {
|
||||
|
||||
// True if the variable is named eval and not known to be shadowed.
|
||||
bool is_possibly_eval(Isolate* isolate) const {
|
||||
return IsVariable(isolate->factory()->eval_symbol());
|
||||
return IsVariable(isolate->factory()->eval_string());
|
||||
}
|
||||
|
||||
Variable* local_if_not_shadowed() const {
|
||||
|
@ -1639,7 +1639,7 @@ void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
|
||||
// Load the empty string into rbx, remove the receiver from the
|
||||
// stack, and jump back to the case where the argument is a string.
|
||||
__ bind(&no_arguments);
|
||||
__ LoadRoot(rbx, Heap::kEmptyStringRootIndex);
|
||||
__ LoadRoot(rbx, Heap::kempty_stringRootIndex);
|
||||
__ pop(rcx);
|
||||
__ lea(rsp, Operand(rsp, kPointerSize));
|
||||
__ push(rcx);
|
||||
|
@ -2350,7 +2350,7 @@ void ArrayLengthStub::Generate(MacroAssembler* masm) {
|
||||
// -- rdx : receiver
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
__ Cmp(rax, masm->isolate()->factory()->length_symbol());
|
||||
__ Cmp(rax, masm->isolate()->factory()->length_string());
|
||||
receiver = rdx;
|
||||
} else {
|
||||
ASSERT(kind() == Code::LOAD_IC);
|
||||
@ -2377,7 +2377,7 @@ void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
|
||||
// -- rdx : receiver
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
__ Cmp(rax, masm->isolate()->factory()->prototype_symbol());
|
||||
__ Cmp(rax, masm->isolate()->factory()->prototype_string());
|
||||
receiver = rdx;
|
||||
} else {
|
||||
ASSERT(kind() == Code::LOAD_IC);
|
||||
@ -2404,7 +2404,7 @@ void StringLengthStub::Generate(MacroAssembler* masm) {
|
||||
// -- rdx : receiver
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
__ Cmp(rax, masm->isolate()->factory()->length_symbol());
|
||||
__ Cmp(rax, masm->isolate()->factory()->length_string());
|
||||
receiver = rdx;
|
||||
} else {
|
||||
ASSERT(kind() == Code::LOAD_IC);
|
||||
@ -2442,7 +2442,7 @@ void StoreArrayLengthStub::Generate(MacroAssembler* masm) {
|
||||
Register value = rax;
|
||||
Register scratch = rbx;
|
||||
if (kind() == Code::KEYED_STORE_IC) {
|
||||
__ Cmp(rcx, masm->isolate()->factory()->length_symbol());
|
||||
__ Cmp(rcx, masm->isolate()->factory()->length_string());
|
||||
}
|
||||
|
||||
// Check that the receiver isn't a smi.
|
||||
@ -3014,7 +3014,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
||||
// (4) Cons string. Check that it's flat.
|
||||
// Replace subject with first string and reload instance type.
|
||||
__ CompareRoot(FieldOperand(rdi, ConsString::kSecondOffset),
|
||||
Heap::kEmptyStringRootIndex);
|
||||
Heap::kempty_stringRootIndex);
|
||||
__ j(not_equal, &runtime);
|
||||
__ movq(rdi, FieldOperand(rdi, ConsString::kFirstOffset));
|
||||
__ bind(&check_underlying);
|
||||
@ -3557,24 +3557,24 @@ static void CheckInputType(MacroAssembler* masm,
|
||||
__ CompareMap(input, masm->isolate()->factory()->heap_number_map(), NULL);
|
||||
__ j(not_equal, fail);
|
||||
}
|
||||
// We could be strict about symbol/string here, but as long as
|
||||
// We could be strict about internalized/non-internalized here, but as long as
|
||||
// hydrogen doesn't care, the stub doesn't have to care either.
|
||||
__ bind(&ok);
|
||||
}
|
||||
|
||||
|
||||
static void BranchIfNonSymbol(MacroAssembler* masm,
|
||||
Label* label,
|
||||
Register object,
|
||||
Register scratch) {
|
||||
static void BranchIfNotInternalizedString(MacroAssembler* masm,
|
||||
Label* label,
|
||||
Register object,
|
||||
Register scratch) {
|
||||
__ JumpIfSmi(object, label);
|
||||
__ movq(scratch, FieldOperand(object, HeapObject::kMapOffset));
|
||||
__ movzxbq(scratch,
|
||||
FieldOperand(scratch, Map::kInstanceTypeOffset));
|
||||
// Ensure that no non-strings have the symbol bit set.
|
||||
STATIC_ASSERT(LAST_TYPE < kNotStringTag + kIsSymbolMask);
|
||||
STATIC_ASSERT(kSymbolTag != 0);
|
||||
__ testb(scratch, Immediate(kIsSymbolMask));
|
||||
// Ensure that no non-strings have the internalized bit set.
|
||||
STATIC_ASSERT(LAST_TYPE < kNotStringTag + kIsInternalizedMask);
|
||||
STATIC_ASSERT(kInternalizedTag != 0);
|
||||
__ testb(scratch, Immediate(kIsInternalizedMask));
|
||||
__ j(zero, label);
|
||||
}
|
||||
|
||||
@ -3742,15 +3742,17 @@ void ICCompareStub::GenerateGeneric(MacroAssembler* masm) {
|
||||
// The number comparison code did not provide a valid result.
|
||||
__ bind(&non_number_comparison);
|
||||
|
||||
// Fast negative check for symbol-to-symbol equality.
|
||||
// Fast negative check for internalized-to-internalized equality.
|
||||
Label check_for_strings;
|
||||
if (cc == equal) {
|
||||
BranchIfNonSymbol(masm, &check_for_strings, rax, kScratchRegister);
|
||||
BranchIfNonSymbol(masm, &check_for_strings, rdx, kScratchRegister);
|
||||
BranchIfNotInternalizedString(
|
||||
masm, &check_for_strings, rax, kScratchRegister);
|
||||
BranchIfNotInternalizedString(
|
||||
masm, &check_for_strings, rdx, kScratchRegister);
|
||||
|
||||
// We've already checked for object identity, so if both operands
|
||||
// are symbols they aren't equal. Register eax (not rax) already holds a
|
||||
// non-zero value, which indicates not equal, so just return.
|
||||
// We've already checked for object identity, so if both operands are
|
||||
// internalized strings they aren't equal. Register eax (not rax) already
|
||||
// holds a non-zero value, which indicates not equal, so just return.
|
||||
__ ret(0);
|
||||
}
|
||||
|
||||
@ -4817,8 +4819,8 @@ void StringAddStub::Generate(MacroAssembler* masm) {
|
||||
// Look at the length of the result of adding the two strings.
|
||||
STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue / 2);
|
||||
__ SmiAdd(rbx, rbx, rcx);
|
||||
// Use the symbol table when adding two one character strings, as it
|
||||
// helps later optimizations to return a symbol here.
|
||||
// Use the string table when adding two one character strings, as it
|
||||
// helps later optimizations to return an internalized string here.
|
||||
__ SmiCompare(rbx, Smi::FromInt(2));
|
||||
__ j(not_equal, &longer_than_two);
|
||||
|
||||
@ -4830,10 +4832,10 @@ void StringAddStub::Generate(MacroAssembler* masm) {
|
||||
__ movzxbq(rbx, FieldOperand(rax, SeqOneByteString::kHeaderSize));
|
||||
__ movzxbq(rcx, FieldOperand(rdx, SeqOneByteString::kHeaderSize));
|
||||
|
||||
// Try to lookup two character string in symbol table. If it is not found
|
||||
// Try to lookup two character string in string table. If it is not found
|
||||
// just allocate a new one.
|
||||
Label make_two_character_string, make_flat_ascii_string;
|
||||
StringHelper::GenerateTwoCharacterSymbolTableProbe(
|
||||
StringHelper::GenerateTwoCharacterStringTableProbe(
|
||||
masm, rbx, rcx, r14, r11, rdi, r15, &make_two_character_string);
|
||||
__ IncrementCounter(counters->string_add_native(), 1);
|
||||
__ ret(2 * kPointerSize);
|
||||
@ -5132,7 +5134,7 @@ void StringHelper::GenerateCopyCharactersREP(MacroAssembler* masm,
|
||||
__ bind(&done);
|
||||
}
|
||||
|
||||
void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
|
||||
void StringHelper::GenerateTwoCharacterStringTableProbe(MacroAssembler* masm,
|
||||
Register c1,
|
||||
Register c2,
|
||||
Register scratch1,
|
||||
@ -5144,7 +5146,7 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
|
||||
Register scratch = scratch3;
|
||||
|
||||
// Make sure that both characters are not digits as such strings has a
|
||||
// different hash algorithm. Don't try to look for these in the symbol table.
|
||||
// different hash algorithm. Don't try to look for these in the string table.
|
||||
Label not_array_index;
|
||||
__ leal(scratch, Operand(c1, -'0'));
|
||||
__ cmpl(scratch, Immediate(static_cast<int>('9' - '0')));
|
||||
@ -5168,14 +5170,14 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
|
||||
// chars: two character string, char 1 in byte 0 and char 2 in byte 1.
|
||||
// hash: hash of two character string.
|
||||
|
||||
// Load the symbol table.
|
||||
Register symbol_table = c2;
|
||||
__ LoadRoot(symbol_table, Heap::kSymbolTableRootIndex);
|
||||
// Load the string table.
|
||||
Register string_table = c2;
|
||||
__ LoadRoot(string_table, Heap::kStringTableRootIndex);
|
||||
|
||||
// Calculate capacity mask from the symbol table capacity.
|
||||
// Calculate capacity mask from the string table capacity.
|
||||
Register mask = scratch2;
|
||||
__ SmiToInteger32(mask,
|
||||
FieldOperand(symbol_table, SymbolTable::kCapacityOffset));
|
||||
FieldOperand(string_table, StringTable::kCapacityOffset));
|
||||
__ decl(mask);
|
||||
|
||||
Register map = scratch4;
|
||||
@ -5183,31 +5185,31 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
|
||||
// Registers
|
||||
// chars: two character string, char 1 in byte 0 and char 2 in byte 1.
|
||||
// hash: hash of two character string (32-bit int)
|
||||
// symbol_table: symbol table
|
||||
// string_table: string table
|
||||
// mask: capacity mask (32-bit int)
|
||||
// map: -
|
||||
// scratch: -
|
||||
|
||||
// Perform a number of probes in the symbol table.
|
||||
// Perform a number of probes in the string table.
|
||||
static const int kProbes = 4;
|
||||
Label found_in_symbol_table;
|
||||
Label found_in_string_table;
|
||||
Label next_probe[kProbes];
|
||||
Register candidate = scratch; // Scratch register contains candidate.
|
||||
for (int i = 0; i < kProbes; i++) {
|
||||
// Calculate entry in symbol table.
|
||||
// Calculate entry in string table.
|
||||
__ movl(scratch, hash);
|
||||
if (i > 0) {
|
||||
__ addl(scratch, Immediate(SymbolTable::GetProbeOffset(i)));
|
||||
__ addl(scratch, Immediate(StringTable::GetProbeOffset(i)));
|
||||
}
|
||||
__ andl(scratch, mask);
|
||||
|
||||
// Load the entry from the symbol table.
|
||||
STATIC_ASSERT(SymbolTable::kEntrySize == 1);
|
||||
// Load the entry from the string table.
|
||||
STATIC_ASSERT(StringTable::kEntrySize == 1);
|
||||
__ movq(candidate,
|
||||
FieldOperand(symbol_table,
|
||||
FieldOperand(string_table,
|
||||
scratch,
|
||||
times_pointer_size,
|
||||
SymbolTable::kElementsStartOffset));
|
||||
StringTable::kElementsStartOffset));
|
||||
|
||||
// If entry is undefined no string with this hash can be found.
|
||||
Label is_string;
|
||||
@ -5220,7 +5222,7 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
|
||||
if (FLAG_debug_code) {
|
||||
__ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
|
||||
__ cmpq(kScratchRegister, candidate);
|
||||
__ Assert(equal, "oddball in symbol table is not undefined or the hole");
|
||||
__ Assert(equal, "oddball in string table is not undefined or the hole");
|
||||
}
|
||||
__ jmp(&next_probe[i]);
|
||||
|
||||
@ -5244,7 +5246,7 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
|
||||
__ movl(temp, FieldOperand(candidate, SeqOneByteString::kHeaderSize));
|
||||
__ andl(temp, Immediate(0x0000ffff));
|
||||
__ cmpl(chars, temp);
|
||||
__ j(equal, &found_in_symbol_table);
|
||||
__ j(equal, &found_in_string_table);
|
||||
__ bind(&next_probe[i]);
|
||||
}
|
||||
|
||||
@ -5253,7 +5255,7 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
|
||||
|
||||
// Scratch register contains result when we fall through to here.
|
||||
Register result = candidate;
|
||||
__ bind(&found_in_symbol_table);
|
||||
__ bind(&found_in_string_table);
|
||||
if (!result.is(rax)) {
|
||||
__ movq(rax, result);
|
||||
}
|
||||
@ -5384,7 +5386,7 @@ void SubStringStub::Generate(MacroAssembler* masm) {
|
||||
// Cons string. Check whether it is flat, then fetch first part.
|
||||
// Flat cons strings have an empty second part.
|
||||
__ CompareRoot(FieldOperand(rax, ConsString::kSecondOffset),
|
||||
Heap::kEmptyStringRootIndex);
|
||||
Heap::kempty_stringRootIndex);
|
||||
__ j(not_equal, &runtime);
|
||||
__ movq(rdi, FieldOperand(rax, ConsString::kFirstOffset));
|
||||
// Update instance type.
|
||||
@ -5831,8 +5833,8 @@ void ICCompareStub::GenerateNumbers(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void ICCompareStub::GenerateSymbols(MacroAssembler* masm) {
|
||||
ASSERT(state_ == CompareIC::SYMBOL);
|
||||
void ICCompareStub::GenerateInternalizedStrings(MacroAssembler* masm) {
|
||||
ASSERT(state_ == CompareIC::INTERNALIZED_STRING);
|
||||
ASSERT(GetCondition() == equal);
|
||||
|
||||
// Registers containing left and right operands respectively.
|
||||
@ -5846,17 +5848,17 @@ void ICCompareStub::GenerateSymbols(MacroAssembler* masm) {
|
||||
Condition cond = masm->CheckEitherSmi(left, right, tmp1);
|
||||
__ j(cond, &miss, Label::kNear);
|
||||
|
||||
// Check that both operands are symbols.
|
||||
// Check that both operands are internalized strings.
|
||||
__ movq(tmp1, FieldOperand(left, HeapObject::kMapOffset));
|
||||
__ movq(tmp2, FieldOperand(right, HeapObject::kMapOffset));
|
||||
__ movzxbq(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset));
|
||||
__ movzxbq(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset));
|
||||
STATIC_ASSERT(kSymbolTag != 0);
|
||||
STATIC_ASSERT(kInternalizedTag != 0);
|
||||
__ and_(tmp1, tmp2);
|
||||
__ testb(tmp1, Immediate(kIsSymbolMask));
|
||||
__ testb(tmp1, Immediate(kIsInternalizedMask));
|
||||
__ j(zero, &miss, Label::kNear);
|
||||
|
||||
// Symbols are compared by identity.
|
||||
// Internalized strings are compared by identity.
|
||||
Label done;
|
||||
__ cmpq(left, right);
|
||||
// Make sure rax is non-zero. At this point input operands are
|
||||
@ -5915,13 +5917,13 @@ void ICCompareStub::GenerateStrings(MacroAssembler* masm) {
|
||||
// Handle not identical strings.
|
||||
__ bind(¬_same);
|
||||
|
||||
// Check that both strings are symbols. If they are, we're done
|
||||
// Check that both strings are internalized strings. If they are, we're done
|
||||
// because we already know they are not identical.
|
||||
if (equality) {
|
||||
Label do_compare;
|
||||
STATIC_ASSERT(kSymbolTag != 0);
|
||||
STATIC_ASSERT(kInternalizedTag != 0);
|
||||
__ and_(tmp1, tmp2);
|
||||
__ testb(tmp1, Immediate(kIsSymbolMask));
|
||||
__ testb(tmp1, Immediate(kIsInternalizedMask));
|
||||
__ j(zero, &do_compare, Label::kNear);
|
||||
// Make sure rax is non-zero. At this point input operands are
|
||||
// guaranteed to be non-zero.
|
||||
@ -6069,10 +6071,10 @@ void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm,
|
||||
__ CompareRoot(entity_name, Heap::kTheHoleValueRootIndex);
|
||||
__ j(equal, &the_hole, Label::kNear);
|
||||
|
||||
// Check if the entry name is not a symbol.
|
||||
// Check if the entry name is not an internalized string.
|
||||
__ movq(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset));
|
||||
__ testb(FieldOperand(entity_name, Map::kInstanceTypeOffset),
|
||||
Immediate(kIsSymbolMask));
|
||||
Immediate(kIsInternalizedMask));
|
||||
__ j(zero, miss);
|
||||
|
||||
__ bind(&the_hole);
|
||||
@ -6201,14 +6203,14 @@ void StringDictionaryLookupStub::Generate(MacroAssembler* masm) {
|
||||
__ j(equal, &in_dictionary);
|
||||
|
||||
if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) {
|
||||
// If we hit a non symbol key during negative lookup
|
||||
// If we hit a non internalized string key during negative lookup
|
||||
// we have to bailout as this key might be equal to the
|
||||
// key we are looking for.
|
||||
|
||||
// Check if the entry name is not a symbol.
|
||||
// Check if the entry name is not an internalized string.
|
||||
__ movq(scratch, FieldOperand(scratch, HeapObject::kMapOffset));
|
||||
__ testb(FieldOperand(scratch, Map::kInstanceTypeOffset),
|
||||
Immediate(kIsSymbolMask));
|
||||
Immediate(kIsInternalizedMask));
|
||||
__ j(zero, &maybe_in_dictionary);
|
||||
}
|
||||
}
|
||||
|
@ -172,11 +172,11 @@ class StringHelper : public AllStatic {
|
||||
bool ascii);
|
||||
|
||||
|
||||
// Probe the symbol table for a two character string. If the string is
|
||||
// Probe the string table for a two character string. If the string is
|
||||
// not found by probing a jump to the label not_found is performed. This jump
|
||||
// does not guarantee that the string is not in the symbol table. If the
|
||||
// does not guarantee that the string is not in the string table. If the
|
||||
// string is found the code falls through with the string in register rax.
|
||||
static void GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
|
||||
static void GenerateTwoCharacterStringTableProbe(MacroAssembler* masm,
|
||||
Register c1,
|
||||
Register c2,
|
||||
Register scratch1,
|
||||
|
@ -554,7 +554,7 @@ void StringCharLoadGenerator::Generate(MacroAssembler* masm,
|
||||
// the string.
|
||||
__ bind(&cons_string);
|
||||
__ CompareRoot(FieldOperand(string, ConsString::kSecondOffset),
|
||||
Heap::kEmptyStringRootIndex);
|
||||
Heap::kempty_stringRootIndex);
|
||||
__ j(not_equal, call_runtime);
|
||||
__ movq(string, FieldOperand(string, ConsString::kFirstOffset));
|
||||
|
||||
|
@ -1611,7 +1611,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
ASSERT(!CompileTimeValue::IsCompileTimeValue(value));
|
||||
// Fall through.
|
||||
case ObjectLiteral::Property::COMPUTED:
|
||||
if (key->handle()->IsSymbol()) {
|
||||
if (key->handle()->IsInternalizedString()) {
|
||||
if (property->emit_store()) {
|
||||
VisitForAccumulatorValue(value);
|
||||
__ Move(rcx, key->handle());
|
||||
@ -2612,7 +2612,7 @@ void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
|
||||
__ CompareRoot(rcx, Heap::kHashTableMapRootIndex);
|
||||
__ j(equal, if_false);
|
||||
|
||||
// Look for valueOf symbol in the descriptor array, and indicate false if
|
||||
// Look for valueOf string in the descriptor array, and indicate false if
|
||||
// found. Since we omit an enumeration index check, if it is added via a
|
||||
// transition that shares its descriptor array, this is a false positive.
|
||||
Label entry, loop, done;
|
||||
@ -2634,11 +2634,11 @@ void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
|
||||
// Calculate location of the first key name.
|
||||
__ addq(rbx, Immediate(DescriptorArray::kFirstOffset));
|
||||
// Loop through all the keys in the descriptor array. If one of these is the
|
||||
// symbol valueOf the result is false.
|
||||
// internalized string "valueOf" the result is false.
|
||||
__ jmp(&entry);
|
||||
__ bind(&loop);
|
||||
__ movq(rdx, FieldOperand(rbx, 0));
|
||||
__ Cmp(rdx, FACTORY->value_of_symbol());
|
||||
__ Cmp(rdx, FACTORY->value_of_string());
|
||||
__ j(equal, if_false);
|
||||
__ addq(rbx, Immediate(DescriptorArray::kDescriptorSize * kPointerSize));
|
||||
__ bind(&entry);
|
||||
@ -2873,12 +2873,12 @@ void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
|
||||
|
||||
// Functions have class 'Function'.
|
||||
__ bind(&function);
|
||||
__ Move(rax, isolate()->factory()->function_class_symbol());
|
||||
__ Move(rax, isolate()->factory()->function_class_string());
|
||||
__ jmp(&done);
|
||||
|
||||
// Objects with a non-function constructor have class 'Object'.
|
||||
__ bind(&non_function_constructor);
|
||||
__ Move(rax, isolate()->factory()->Object_symbol());
|
||||
__ Move(rax, isolate()->factory()->Object_string());
|
||||
__ jmp(&done);
|
||||
|
||||
// Non-JS objects have class null.
|
||||
@ -3238,7 +3238,7 @@ void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
|
||||
__ bind(&index_out_of_range);
|
||||
// When the index is out of range, the spec requires us to return
|
||||
// the empty string.
|
||||
__ LoadRoot(result, Heap::kEmptyStringRootIndex);
|
||||
__ LoadRoot(result, Heap::kempty_stringRootIndex);
|
||||
__ jmp(&done);
|
||||
|
||||
__ bind(&need_conversion);
|
||||
@ -3564,7 +3564,7 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
|
||||
__ movq(array_length, FieldOperand(array, JSArray::kLengthOffset));
|
||||
__ SmiCompare(array_length, Smi::FromInt(0));
|
||||
__ j(not_zero, &non_trivial_array);
|
||||
__ LoadRoot(rax, Heap::kEmptyStringRootIndex);
|
||||
__ LoadRoot(rax, Heap::kempty_stringRootIndex);
|
||||
__ jmp(&return_result);
|
||||
|
||||
// Save the array length on the stack.
|
||||
@ -4228,12 +4228,12 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
||||
}
|
||||
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||
|
||||
if (check->Equals(isolate()->heap()->number_symbol())) {
|
||||
if (check->Equals(isolate()->heap()->number_string())) {
|
||||
__ JumpIfSmi(rax, if_true);
|
||||
__ movq(rax, FieldOperand(rax, HeapObject::kMapOffset));
|
||||
__ CompareRoot(rax, Heap::kHeapNumberMapRootIndex);
|
||||
Split(equal, if_true, if_false, fall_through);
|
||||
} else if (check->Equals(isolate()->heap()->string_symbol())) {
|
||||
} else if (check->Equals(isolate()->heap()->string_string())) {
|
||||
__ JumpIfSmi(rax, if_false);
|
||||
// Check for undetectable objects => false.
|
||||
__ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx);
|
||||
@ -4241,16 +4241,16 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
||||
__ testb(FieldOperand(rdx, Map::kBitFieldOffset),
|
||||
Immediate(1 << Map::kIsUndetectable));
|
||||
Split(zero, if_true, if_false, fall_through);
|
||||
} else if (check->Equals(isolate()->heap()->boolean_symbol())) {
|
||||
} else if (check->Equals(isolate()->heap()->boolean_string())) {
|
||||
__ CompareRoot(rax, Heap::kTrueValueRootIndex);
|
||||
__ j(equal, if_true);
|
||||
__ CompareRoot(rax, Heap::kFalseValueRootIndex);
|
||||
Split(equal, if_true, if_false, fall_through);
|
||||
} else if (FLAG_harmony_typeof &&
|
||||
check->Equals(isolate()->heap()->null_symbol())) {
|
||||
check->Equals(isolate()->heap()->null_string())) {
|
||||
__ CompareRoot(rax, Heap::kNullValueRootIndex);
|
||||
Split(equal, if_true, if_false, fall_through);
|
||||
} else if (check->Equals(isolate()->heap()->undefined_symbol())) {
|
||||
} else if (check->Equals(isolate()->heap()->undefined_string())) {
|
||||
__ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
|
||||
__ j(equal, if_true);
|
||||
__ JumpIfSmi(rax, if_false);
|
||||
@ -4259,14 +4259,14 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
||||
__ testb(FieldOperand(rdx, Map::kBitFieldOffset),
|
||||
Immediate(1 << Map::kIsUndetectable));
|
||||
Split(not_zero, if_true, if_false, fall_through);
|
||||
} else if (check->Equals(isolate()->heap()->function_symbol())) {
|
||||
} else if (check->Equals(isolate()->heap()->function_string())) {
|
||||
__ JumpIfSmi(rax, if_false);
|
||||
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
|
||||
__ CmpObjectType(rax, JS_FUNCTION_TYPE, rdx);
|
||||
__ j(equal, if_true);
|
||||
__ CmpInstanceType(rdx, JS_FUNCTION_PROXY_TYPE);
|
||||
Split(equal, if_true, if_false, fall_through);
|
||||
} else if (check->Equals(isolate()->heap()->object_symbol())) {
|
||||
} else if (check->Equals(isolate()->heap()->object_string())) {
|
||||
__ JumpIfSmi(rax, if_false);
|
||||
if (!FLAG_harmony_typeof) {
|
||||
__ CompareRoot(rax, Heap::kNullValueRootIndex);
|
||||
|
@ -101,8 +101,8 @@ static void GenerateStringDictionaryReceiverCheck(MacroAssembler* masm,
|
||||
// Helper function used to load a property from a dictionary backing storage.
|
||||
// This function may return false negatives, so miss_label
|
||||
// must always call a backup property load that is complete.
|
||||
// This function is safe to call if name is not a symbol, and will jump to
|
||||
// the miss_label in that case.
|
||||
// This function is safe to call if name is not an internalized string,
|
||||
// and will jump to the miss_label in that case.
|
||||
// The generated code assumes that the receiver has slow properties,
|
||||
// is not a global object and does not have interceptors.
|
||||
static void GenerateDictionaryLoad(MacroAssembler* masm,
|
||||
@ -160,8 +160,8 @@ static void GenerateDictionaryLoad(MacroAssembler* masm,
|
||||
// storage. This function may fail to store a property even though it
|
||||
// is in the dictionary, so code at miss_label must always call a
|
||||
// backup property store that is complete. This function is safe to
|
||||
// call if name is not a symbol, and will jump to the miss_label in
|
||||
// that case. The generated code assumes that the receiver has slow
|
||||
// call if name is not an internalized string, and will jump to the miss_label
|
||||
// in that case. The generated code assumes that the receiver has slow
|
||||
// properties, is not a global object and does not have interceptors.
|
||||
static void GenerateDictionaryStore(MacroAssembler* masm,
|
||||
Label* miss_label,
|
||||
@ -313,31 +313,31 @@ static void GenerateFastArrayLoad(MacroAssembler* masm,
|
||||
}
|
||||
|
||||
|
||||
// Checks whether a key is an array index string or a symbol string.
|
||||
// Falls through if the key is a symbol.
|
||||
// Checks whether a key is an array index string or an internalized string.
|
||||
// Falls through if the key is an internalized string.
|
||||
static void GenerateKeyStringCheck(MacroAssembler* masm,
|
||||
Register key,
|
||||
Register map,
|
||||
Register hash,
|
||||
Label* index_string,
|
||||
Label* not_symbol) {
|
||||
Label* not_internalized) {
|
||||
// Register use:
|
||||
// key - holds the key and is unchanged. Assumed to be non-smi.
|
||||
// Scratch registers:
|
||||
// map - used to hold the map of the key.
|
||||
// hash - used to hold the hash of the key.
|
||||
__ CmpObjectType(key, FIRST_NONSTRING_TYPE, map);
|
||||
__ j(above_equal, not_symbol);
|
||||
__ j(above_equal, not_internalized);
|
||||
// Is the string an array index, with cached numeric value?
|
||||
__ movl(hash, FieldOperand(key, String::kHashFieldOffset));
|
||||
__ testl(hash, Immediate(String::kContainsCachedArrayIndexMask));
|
||||
__ j(zero, index_string); // The value in hash is used at jump target.
|
||||
|
||||
// Is the string a symbol?
|
||||
STATIC_ASSERT(kSymbolTag != 0);
|
||||
// Is the string internalized?
|
||||
STATIC_ASSERT(kInternalizedTag != 0);
|
||||
__ testb(FieldOperand(map, Map::kInstanceTypeOffset),
|
||||
Immediate(kIsSymbolMask));
|
||||
__ j(zero, not_symbol);
|
||||
Immediate(kIsInternalizedMask));
|
||||
__ j(zero, not_internalized);
|
||||
}
|
||||
|
||||
|
||||
@ -421,7 +421,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
|
||||
int mask = (KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask);
|
||||
__ and_(rcx, Immediate(mask));
|
||||
|
||||
// Load the key (consisting of map and symbol) from the cache and
|
||||
// Load the key (consisting of map and internalized string) from the cache and
|
||||
// check for match.
|
||||
Label load_in_object_property;
|
||||
static const int kEntriesPerBucket = KeyedLookupCache::kEntriesPerBucket;
|
||||
@ -1075,7 +1075,7 @@ void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
|
||||
__ bind(&check_string);
|
||||
GenerateKeyStringCheck(masm, rcx, rax, rbx, &index_string, &slow_call);
|
||||
|
||||
// The key is known to be a symbol.
|
||||
// The key is known to be an internalized string.
|
||||
// If the receiver is a regular JS object with slow properties then do
|
||||
// a quick inline probe of the receiver's dictionary.
|
||||
// Otherwise do the monomorphic cache probe.
|
||||
@ -1102,7 +1102,7 @@ void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
|
||||
__ bind(&slow_call);
|
||||
// This branch is taken if:
|
||||
// - the receiver requires boxing or access check,
|
||||
// - the key is neither smi nor symbol,
|
||||
// - the key is neither smi nor internalized string,
|
||||
// - the value loaded is not a function,
|
||||
// - there is hope that the runtime will create a monomorphic call stub
|
||||
// that will get fetched next time.
|
||||
|
@ -2342,13 +2342,13 @@ void LCodeGen::EmitClassOfTest(Label* is_true,
|
||||
__ movq(temp, FieldOperand(temp, JSFunction::kSharedFunctionInfoOffset));
|
||||
__ movq(temp, FieldOperand(temp,
|
||||
SharedFunctionInfo::kInstanceClassNameOffset));
|
||||
// The class name we are testing against is a symbol because it's a literal.
|
||||
// The name in the constructor is a symbol because of the way the context is
|
||||
// booted. This routine isn't expected to work for random API-created
|
||||
// The class name we are testing against is internalized since it's a literal.
|
||||
// The name in the constructor is internalized because of the way the context
|
||||
// is booted. This routine isn't expected to work for random API-created
|
||||
// classes and it doesn't have to because you can't access it with natives
|
||||
// syntax. Since both sides are symbols it is sufficient to use an identity
|
||||
// comparison.
|
||||
ASSERT(class_name->IsSymbol());
|
||||
// syntax. Since both sides are internalized it is sufficient to use an
|
||||
// identity comparison.
|
||||
ASSERT(class_name->IsInternalizedString());
|
||||
__ Cmp(temp, class_name);
|
||||
// End with the answer in the z flag.
|
||||
}
|
||||
@ -5503,14 +5503,14 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
|
||||
Register input,
|
||||
Handle<String> type_name) {
|
||||
Condition final_branch_condition = no_condition;
|
||||
if (type_name->Equals(heap()->number_symbol())) {
|
||||
if (type_name->Equals(heap()->number_string())) {
|
||||
__ JumpIfSmi(input, true_label);
|
||||
__ CompareRoot(FieldOperand(input, HeapObject::kMapOffset),
|
||||
Heap::kHeapNumberMapRootIndex);
|
||||
|
||||
final_branch_condition = equal;
|
||||
|
||||
} else if (type_name->Equals(heap()->string_symbol())) {
|
||||
} else if (type_name->Equals(heap()->string_string())) {
|
||||
__ JumpIfSmi(input, false_label);
|
||||
__ CmpObjectType(input, FIRST_NONSTRING_TYPE, input);
|
||||
__ j(above_equal, false_label);
|
||||
@ -5518,17 +5518,17 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
|
||||
Immediate(1 << Map::kIsUndetectable));
|
||||
final_branch_condition = zero;
|
||||
|
||||
} else if (type_name->Equals(heap()->boolean_symbol())) {
|
||||
} else if (type_name->Equals(heap()->boolean_string())) {
|
||||
__ CompareRoot(input, Heap::kTrueValueRootIndex);
|
||||
__ j(equal, true_label);
|
||||
__ CompareRoot(input, Heap::kFalseValueRootIndex);
|
||||
final_branch_condition = equal;
|
||||
|
||||
} else if (FLAG_harmony_typeof && type_name->Equals(heap()->null_symbol())) {
|
||||
} else if (FLAG_harmony_typeof && type_name->Equals(heap()->null_string())) {
|
||||
__ CompareRoot(input, Heap::kNullValueRootIndex);
|
||||
final_branch_condition = equal;
|
||||
|
||||
} else if (type_name->Equals(heap()->undefined_symbol())) {
|
||||
} else if (type_name->Equals(heap()->undefined_string())) {
|
||||
__ CompareRoot(input, Heap::kUndefinedValueRootIndex);
|
||||
__ j(equal, true_label);
|
||||
__ JumpIfSmi(input, false_label);
|
||||
@ -5538,7 +5538,7 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
|
||||
Immediate(1 << Map::kIsUndetectable));
|
||||
final_branch_condition = not_zero;
|
||||
|
||||
} else if (type_name->Equals(heap()->function_symbol())) {
|
||||
} else if (type_name->Equals(heap()->function_string())) {
|
||||
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
|
||||
__ JumpIfSmi(input, false_label);
|
||||
__ CmpObjectType(input, JS_FUNCTION_TYPE, input);
|
||||
@ -5546,7 +5546,7 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
|
||||
__ CmpInstanceType(input, JS_FUNCTION_PROXY_TYPE);
|
||||
final_branch_condition = equal;
|
||||
|
||||
} else if (type_name->Equals(heap()->object_symbol())) {
|
||||
} else if (type_name->Equals(heap()->object_string())) {
|
||||
__ JumpIfSmi(input, false_label);
|
||||
if (!FLAG_harmony_typeof) {
|
||||
__ CompareRoot(input, Heap::kNullValueRootIndex);
|
||||
|
@ -110,14 +110,14 @@ static void ProbeTable(Isolate* isolate,
|
||||
// the property. This function may return false negatives, so miss_label
|
||||
// must always call a backup property check that is complete.
|
||||
// This function is safe to call if the receiver has fast properties.
|
||||
// Name must be a symbol and receiver must be a heap object.
|
||||
// Name must be an internalized string and receiver must be a heap object.
|
||||
static void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
|
||||
Label* miss_label,
|
||||
Register receiver,
|
||||
Handle<String> name,
|
||||
Register r0,
|
||||
Register r1) {
|
||||
ASSERT(name->IsSymbol());
|
||||
ASSERT(name->IsInternalizedString());
|
||||
Counters* counters = masm->isolate()->counters();
|
||||
__ IncrementCounter(counters->negative_lookups(), 1);
|
||||
__ IncrementCounter(counters->negative_lookups_miss(), 1);
|
||||
@ -949,8 +949,8 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
|
||||
if (!current->HasFastProperties() &&
|
||||
!current->IsJSGlobalObject() &&
|
||||
!current->IsJSGlobalProxy()) {
|
||||
if (!name->IsSymbol()) {
|
||||
name = factory()->LookupSymbol(name);
|
||||
if (!name->IsInternalizedString()) {
|
||||
name = factory()->InternalizeString(name);
|
||||
}
|
||||
ASSERT(current->property_dictionary()->FindEntry(*name) ==
|
||||
StringDictionary::kNotFound);
|
||||
@ -1877,7 +1877,7 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall(
|
||||
|
||||
if (index_out_of_range.is_linked()) {
|
||||
__ bind(&index_out_of_range);
|
||||
__ LoadRoot(rax, Heap::kEmptyStringRootIndex);
|
||||
__ LoadRoot(rax, Heap::kempty_stringRootIndex);
|
||||
__ ret((argc + 1) * kPointerSize);
|
||||
}
|
||||
__ bind(&miss);
|
||||
@ -2180,7 +2180,7 @@ void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
|
||||
break;
|
||||
|
||||
case STRING_CHECK:
|
||||
// Check that the object is a two-byte string or a symbol.
|
||||
// Check that the object is a string.
|
||||
__ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rax);
|
||||
__ j(above_equal, &miss);
|
||||
// Check that the maps starting from the prototype haven't changed.
|
||||
|
@ -121,7 +121,7 @@ TEST(StressJS) {
|
||||
v8::HandleScope scope;
|
||||
env->Enter();
|
||||
Handle<JSFunction> function =
|
||||
FACTORY->NewFunction(FACTORY->function_symbol(), FACTORY->null_value());
|
||||
FACTORY->NewFunction(FACTORY->function_string(), FACTORY->null_value());
|
||||
// Force the creation of an initial map and set the code to
|
||||
// something empty.
|
||||
FACTORY->NewJSObject(function);
|
||||
|
@ -613,8 +613,9 @@ THREADED_TEST(UsingExternalString) {
|
||||
// Trigger GCs so that the newly allocated string moves to old gen.
|
||||
HEAP->CollectGarbage(i::NEW_SPACE); // in survivor space now
|
||||
HEAP->CollectGarbage(i::NEW_SPACE); // in old gen now
|
||||
i::Handle<i::String> isymbol = FACTORY->SymbolFromString(istring);
|
||||
CHECK(isymbol->IsSymbol());
|
||||
i::Handle<i::String> isymbol =
|
||||
FACTORY->InternalizedStringFromString(istring);
|
||||
CHECK(isymbol->IsInternalizedString());
|
||||
}
|
||||
HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
||||
HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
||||
@ -631,8 +632,9 @@ THREADED_TEST(UsingExternalAsciiString) {
|
||||
// Trigger GCs so that the newly allocated string moves to old gen.
|
||||
HEAP->CollectGarbage(i::NEW_SPACE); // in survivor space now
|
||||
HEAP->CollectGarbage(i::NEW_SPACE); // in old gen now
|
||||
i::Handle<i::String> isymbol = FACTORY->SymbolFromString(istring);
|
||||
CHECK(isymbol->IsSymbol());
|
||||
i::Handle<i::String> isymbol =
|
||||
FACTORY->InternalizedStringFromString(istring);
|
||||
CHECK(isymbol->IsInternalizedString());
|
||||
}
|
||||
HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
||||
HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
||||
@ -3774,7 +3776,7 @@ THREADED_TEST(Equality) {
|
||||
CHECK_EQ(v8_num(1.00), v8_num(1));
|
||||
CHECK_NE(v8_num(1), v8_num(2));
|
||||
|
||||
// Assume String is not symbol.
|
||||
// Assume String is not internalized.
|
||||
CHECK(v8_str("a")->StrictEquals(v8_str("a")));
|
||||
CHECK(!v8_str("a")->StrictEquals(v8_str("b")));
|
||||
CHECK(!v8_str("5")->StrictEquals(v8_num(5)));
|
||||
@ -12880,7 +12882,7 @@ static void MorphAString(i::String* string,
|
||||
UC16VectorResource* uc16_resource) {
|
||||
CHECK(i::StringShape(string).IsExternal());
|
||||
if (string->IsOneByteRepresentation()) {
|
||||
// Check old map is not symbol or long.
|
||||
// Check old map is not internalized or long.
|
||||
CHECK(string->map() == HEAP->external_ascii_string_map());
|
||||
// Morph external string to be TwoByte string.
|
||||
string->set_map(HEAP->external_string_map());
|
||||
@ -12888,7 +12890,7 @@ static void MorphAString(i::String* string,
|
||||
i::ExternalTwoByteString::cast(string);
|
||||
morphed->set_resource(uc16_resource);
|
||||
} else {
|
||||
// Check old map is not symbol or long.
|
||||
// Check old map is not internalized or long.
|
||||
CHECK(string->map() == HEAP->external_string_map());
|
||||
// Morph external string to be ASCII string.
|
||||
string->set_map(HEAP->external_ascii_string_map());
|
||||
@ -15342,8 +15344,8 @@ TEST(VisitExternalStrings) {
|
||||
HEAP->CollectAllAvailableGarbage(); // Tenure string.
|
||||
// Turn into a symbol.
|
||||
i::Handle<i::String> string3_i = v8::Utils::OpenHandle(*string3);
|
||||
CHECK(!HEAP->LookupSymbol(*string3_i)->IsFailure());
|
||||
CHECK(string3_i->IsSymbol());
|
||||
CHECK(!HEAP->InternalizeString(*string3_i)->IsFailure());
|
||||
CHECK(string3_i->IsInternalizedString());
|
||||
|
||||
// We need to add usages for string* to avoid warnings in GCC 4.7
|
||||
CHECK(string0->IsExternal());
|
||||
@ -17845,7 +17847,7 @@ TEST(StringEmpty) {
|
||||
v8::HandleScope scope;
|
||||
LocalContext context;
|
||||
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||
i::Handle<i::Object> empty_string = FACTORY->empty_symbol();
|
||||
i::Handle<i::Object> empty_string = FACTORY->empty_string();
|
||||
CHECK(*v8::Utils::OpenHandle(*v8::String::Empty()) == *empty_string);
|
||||
CHECK(*v8::Utils::OpenHandle(*v8::String::Empty(isolate)) == *empty_string);
|
||||
|
||||
|
@ -94,17 +94,19 @@ static void InitializeVM() {
|
||||
|
||||
|
||||
static MaybeObject* GetGlobalProperty(const char* name) {
|
||||
Handle<String> symbol = FACTORY->LookupUtf8Symbol(name);
|
||||
return Isolate::Current()->context()->global_object()->GetProperty(*symbol);
|
||||
Handle<String> internalized_name = FACTORY->InternalizeUtf8String(name);
|
||||
return Isolate::Current()->context()->global_object()->GetProperty(
|
||||
*internalized_name);
|
||||
}
|
||||
|
||||
|
||||
static void SetGlobalProperty(const char* name, Object* value) {
|
||||
Isolate* isolate = Isolate::Current();
|
||||
Handle<Object> object(value, isolate);
|
||||
Handle<String> symbol = isolate->factory()->LookupUtf8Symbol(name);
|
||||
Handle<String> internalized_name =
|
||||
isolate->factory()->InternalizeUtf8String(name);
|
||||
Handle<JSObject> global(isolate->context()->global_object());
|
||||
SetProperty(isolate, global, symbol, object, NONE, kNonStrictMode);
|
||||
SetProperty(isolate, global, internalized_name, object, NONE, kNonStrictMode);
|
||||
}
|
||||
|
||||
|
||||
@ -295,16 +297,16 @@ TEST(C2JSFrames) {
|
||||
Execution::Call(fun0, global, 0, NULL, &has_pending_exception);
|
||||
CHECK(!has_pending_exception);
|
||||
|
||||
Object* foo_symbol =
|
||||
FACTORY->LookupOneByteSymbol(STATIC_ASCII_VECTOR("foo"))->
|
||||
Object* foo_string =
|
||||
FACTORY->InternalizeOneByteString(STATIC_ASCII_VECTOR("foo"))->
|
||||
ToObjectChecked();
|
||||
MaybeObject* fun1_object = isolate->context()->global_object()->
|
||||
GetProperty(String::cast(foo_symbol));
|
||||
GetProperty(String::cast(foo_string));
|
||||
Handle<Object> fun1(fun1_object->ToObjectChecked(), isolate);
|
||||
CHECK(fun1->IsJSFunction());
|
||||
|
||||
Handle<Object> argv[] =
|
||||
{ FACTORY->LookupOneByteSymbol(STATIC_ASCII_VECTOR("hello")) };
|
||||
{ FACTORY->InternalizeOneByteString(STATIC_ASCII_VECTOR("hello")) };
|
||||
Execution::Call(Handle<JSFunction>::cast(fun1),
|
||||
global,
|
||||
ARRAY_SIZE(argv),
|
||||
|
@ -154,7 +154,7 @@ class DebugLocalContext {
|
||||
Handle<JSGlobalProxy> global(Handle<JSGlobalProxy>::cast(
|
||||
v8::Utils::OpenHandle(*context_->Global())));
|
||||
Handle<v8::internal::String> debug_string =
|
||||
FACTORY->LookupOneByteSymbol(STATIC_ASCII_VECTOR("debug"));
|
||||
FACTORY->InternalizeOneByteString(STATIC_ASCII_VECTOR("debug"));
|
||||
SetProperty(isolate, global, debug_string,
|
||||
Handle<Object>(debug->debug_context()->global_proxy(), isolate),
|
||||
DONT_ENUM,
|
||||
|
@ -184,10 +184,10 @@ TEST(HeapObjects) {
|
||||
CHECK(s->IsString());
|
||||
CHECK_EQ(10, s->length());
|
||||
|
||||
String* object_symbol = String::cast(heap->Object_symbol());
|
||||
String* object_string = String::cast(heap->Object_string());
|
||||
CHECK(
|
||||
Isolate::Current()->context()->global_object()->HasLocalProperty(
|
||||
object_symbol));
|
||||
object_string));
|
||||
|
||||
// Check ToString for oddballs
|
||||
CheckOddball(isolate, heap->true_value(), "true");
|
||||
@ -233,10 +233,10 @@ TEST(GarbageCollection) {
|
||||
// Check GC.
|
||||
heap->CollectGarbage(NEW_SPACE);
|
||||
|
||||
Handle<String> name = factory->LookupUtf8Symbol("theFunction");
|
||||
Handle<String> prop_name = factory->LookupUtf8Symbol("theSlot");
|
||||
Handle<String> prop_namex = factory->LookupUtf8Symbol("theSlotx");
|
||||
Handle<String> obj_name = factory->LookupUtf8Symbol("theObject");
|
||||
Handle<String> name = factory->InternalizeUtf8String("theFunction");
|
||||
Handle<String> prop_name = factory->InternalizeUtf8String("theSlot");
|
||||
Handle<String> prop_namex = factory->InternalizeUtf8String("theSlotx");
|
||||
Handle<String> obj_name = factory->InternalizeUtf8String("theObject");
|
||||
|
||||
{
|
||||
HandleScope inner_scope(isolate);
|
||||
@ -564,15 +564,15 @@ static const char* not_so_random_string_table[] = {
|
||||
};
|
||||
|
||||
|
||||
static void CheckSymbols(const char** strings) {
|
||||
static void CheckInternalizedStrings(const char** strings) {
|
||||
for (const char* string = *strings; *strings != 0; string = *strings++) {
|
||||
Object* a;
|
||||
MaybeObject* maybe_a = HEAP->LookupUtf8Symbol(string);
|
||||
// LookupUtf8Symbol may return a failure if a GC is needed.
|
||||
MaybeObject* maybe_a = HEAP->InternalizeUtf8String(string);
|
||||
// InternalizeUtf8String may return a failure if a GC is needed.
|
||||
if (!maybe_a->ToObject(&a)) continue;
|
||||
CHECK(a->IsSymbol());
|
||||
CHECK(a->IsInternalizedString());
|
||||
Object* b;
|
||||
MaybeObject* maybe_b = HEAP->LookupUtf8Symbol(string);
|
||||
MaybeObject* maybe_b = HEAP->InternalizeUtf8String(string);
|
||||
if (!maybe_b->ToObject(&b)) continue;
|
||||
CHECK_EQ(b, a);
|
||||
CHECK(String::cast(b)->IsUtf8EqualTo(CStrVector(string)));
|
||||
@ -580,11 +580,11 @@ static void CheckSymbols(const char** strings) {
|
||||
}
|
||||
|
||||
|
||||
TEST(SymbolTable) {
|
||||
TEST(StringTable) {
|
||||
InitializeVM();
|
||||
|
||||
CheckSymbols(not_so_random_string_table);
|
||||
CheckSymbols(not_so_random_string_table);
|
||||
CheckInternalizedStrings(not_so_random_string_table);
|
||||
CheckInternalizedStrings(not_so_random_string_table);
|
||||
}
|
||||
|
||||
|
||||
@ -592,14 +592,14 @@ TEST(FunctionAllocation) {
|
||||
InitializeVM();
|
||||
|
||||
v8::HandleScope sc;
|
||||
Handle<String> name = FACTORY->LookupUtf8Symbol("theFunction");
|
||||
Handle<String> name = FACTORY->InternalizeUtf8String("theFunction");
|
||||
Handle<JSFunction> function =
|
||||
FACTORY->NewFunction(name, FACTORY->undefined_value());
|
||||
Handle<Map> initial_map =
|
||||
FACTORY->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
|
||||
function->set_initial_map(*initial_map);
|
||||
|
||||
Handle<String> prop_name = FACTORY->LookupUtf8Symbol("theSlot");
|
||||
Handle<String> prop_name = FACTORY->InternalizeUtf8String("theSlot");
|
||||
Handle<JSObject> obj = FACTORY->NewJSObject(function);
|
||||
obj->SetProperty(
|
||||
*prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked();
|
||||
@ -615,14 +615,14 @@ TEST(ObjectProperties) {
|
||||
InitializeVM();
|
||||
|
||||
v8::HandleScope sc;
|
||||
String* object_symbol = String::cast(HEAP->Object_symbol());
|
||||
String* object_string = String::cast(HEAP->Object_string());
|
||||
Object* raw_object = Isolate::Current()->context()->global_object()->
|
||||
GetProperty(object_symbol)->ToObjectChecked();
|
||||
GetProperty(object_string)->ToObjectChecked();
|
||||
JSFunction* object_function = JSFunction::cast(raw_object);
|
||||
Handle<JSFunction> constructor(object_function);
|
||||
Handle<JSObject> obj = FACTORY->NewJSObject(constructor);
|
||||
Handle<String> first = FACTORY->LookupUtf8Symbol("first");
|
||||
Handle<String> second = FACTORY->LookupUtf8Symbol("second");
|
||||
Handle<String> first = FACTORY->InternalizeUtf8String("first");
|
||||
Handle<String> second = FACTORY->InternalizeUtf8String("second");
|
||||
|
||||
// check for empty
|
||||
CHECK(!obj->HasLocalProperty(*first));
|
||||
@ -666,19 +666,19 @@ TEST(ObjectProperties) {
|
||||
CHECK(!obj->HasLocalProperty(*first));
|
||||
CHECK(!obj->HasLocalProperty(*second));
|
||||
|
||||
// check string and symbol match
|
||||
// check string and internalized string match
|
||||
const char* string1 = "fisk";
|
||||
Handle<String> s1 = FACTORY->NewStringFromAscii(CStrVector(string1));
|
||||
obj->SetProperty(
|
||||
*s1, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
|
||||
Handle<String> s1_symbol = FACTORY->LookupUtf8Symbol(string1);
|
||||
CHECK(obj->HasLocalProperty(*s1_symbol));
|
||||
Handle<String> s1_string = FACTORY->InternalizeUtf8String(string1);
|
||||
CHECK(obj->HasLocalProperty(*s1_string));
|
||||
|
||||
// check symbol and string match
|
||||
// check internalized string and string match
|
||||
const char* string2 = "fugl";
|
||||
Handle<String> s2_symbol = FACTORY->LookupUtf8Symbol(string2);
|
||||
Handle<String> s2_string = FACTORY->InternalizeUtf8String(string2);
|
||||
obj->SetProperty(
|
||||
*s2_symbol, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
|
||||
*s2_string, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
|
||||
Handle<String> s2 = FACTORY->NewStringFromAscii(CStrVector(string2));
|
||||
CHECK(obj->HasLocalProperty(*s2));
|
||||
}
|
||||
@ -688,14 +688,14 @@ TEST(JSObjectMaps) {
|
||||
InitializeVM();
|
||||
|
||||
v8::HandleScope sc;
|
||||
Handle<String> name = FACTORY->LookupUtf8Symbol("theFunction");
|
||||
Handle<String> name = FACTORY->InternalizeUtf8String("theFunction");
|
||||
Handle<JSFunction> function =
|
||||
FACTORY->NewFunction(name, FACTORY->undefined_value());
|
||||
Handle<Map> initial_map =
|
||||
FACTORY->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
|
||||
function->set_initial_map(*initial_map);
|
||||
|
||||
Handle<String> prop_name = FACTORY->LookupUtf8Symbol("theSlot");
|
||||
Handle<String> prop_name = FACTORY->InternalizeUtf8String("theSlot");
|
||||
Handle<JSObject> obj = FACTORY->NewJSObject(function);
|
||||
|
||||
// Set a propery
|
||||
@ -712,7 +712,7 @@ TEST(JSArray) {
|
||||
InitializeVM();
|
||||
|
||||
v8::HandleScope sc;
|
||||
Handle<String> name = FACTORY->LookupUtf8Symbol("Array");
|
||||
Handle<String> name = FACTORY->InternalizeUtf8String("Array");
|
||||
Object* raw_object = Isolate::Current()->context()->global_object()->
|
||||
GetProperty(*name)->ToObjectChecked();
|
||||
Handle<JSFunction> function = Handle<JSFunction>(
|
||||
@ -759,14 +759,14 @@ TEST(JSObjectCopy) {
|
||||
InitializeVM();
|
||||
|
||||
v8::HandleScope sc;
|
||||
String* object_symbol = String::cast(HEAP->Object_symbol());
|
||||
String* object_string = String::cast(HEAP->Object_string());
|
||||
Object* raw_object = Isolate::Current()->context()->global_object()->
|
||||
GetProperty(object_symbol)->ToObjectChecked();
|
||||
GetProperty(object_string)->ToObjectChecked();
|
||||
JSFunction* object_function = JSFunction::cast(raw_object);
|
||||
Handle<JSFunction> constructor(object_function);
|
||||
Handle<JSObject> obj = FACTORY->NewJSObject(constructor);
|
||||
Handle<String> first = FACTORY->LookupUtf8Symbol("first");
|
||||
Handle<String> second = FACTORY->LookupUtf8Symbol("second");
|
||||
Handle<String> first = FACTORY->InternalizeUtf8String("first");
|
||||
Handle<String> second = FACTORY->InternalizeUtf8String("second");
|
||||
|
||||
obj->SetProperty(
|
||||
*first, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
|
||||
@ -821,10 +821,11 @@ TEST(StringAllocation) {
|
||||
non_ascii[3 * i + 2] = chars[2];
|
||||
}
|
||||
Handle<String> non_ascii_sym =
|
||||
FACTORY->LookupUtf8Symbol(Vector<const char>(non_ascii, 3 * length));
|
||||
FACTORY->InternalizeUtf8String(
|
||||
Vector<const char>(non_ascii, 3 * length));
|
||||
CHECK_EQ(length, non_ascii_sym->length());
|
||||
Handle<String> ascii_sym =
|
||||
FACTORY->LookupOneByteSymbol(OneByteVector(ascii, length));
|
||||
FACTORY->InternalizeOneByteString(OneByteVector(ascii, length));
|
||||
CHECK_EQ(length, ascii_sym->length());
|
||||
Handle<String> non_ascii_str =
|
||||
FACTORY->NewStringFromUtf8(Vector<const char>(non_ascii, 3 * length));
|
||||
@ -1001,7 +1002,7 @@ TEST(TestCodeFlushing) {
|
||||
" var z = x + y;"
|
||||
"};"
|
||||
"foo()";
|
||||
Handle<String> foo_name = FACTORY->LookupUtf8Symbol("foo");
|
||||
Handle<String> foo_name = FACTORY->InternalizeUtf8String("foo");
|
||||
|
||||
// This compile will add the code to the compilation cache.
|
||||
{ v8::HandleScope scope;
|
||||
@ -1048,7 +1049,7 @@ TEST(TestCodeFlushingIncremental) {
|
||||
" var z = x + y;"
|
||||
"};"
|
||||
"foo()";
|
||||
Handle<String> foo_name = FACTORY->LookupUtf8Symbol("foo");
|
||||
Handle<String> foo_name = FACTORY->InternalizeUtf8String("foo");
|
||||
|
||||
// This compile will add the code to the compilation cache.
|
||||
{ v8::HandleScope scope;
|
||||
@ -1118,8 +1119,8 @@ TEST(TestCodeFlushingIncrementalScavenge) {
|
||||
" var x = 23;"
|
||||
"};"
|
||||
"bar();";
|
||||
Handle<String> foo_name = FACTORY->LookupUtf8Symbol("foo");
|
||||
Handle<String> bar_name = FACTORY->LookupUtf8Symbol("bar");
|
||||
Handle<String> foo_name = FACTORY->InternalizeUtf8String("foo");
|
||||
Handle<String> bar_name = FACTORY->InternalizeUtf8String("bar");
|
||||
|
||||
// Perfrom one initial GC to enable code flushing.
|
||||
HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
|
||||
@ -1182,7 +1183,7 @@ TEST(TestCodeFlushingIncrementalAbort) {
|
||||
" var z = x + y;"
|
||||
"};"
|
||||
"foo()";
|
||||
Handle<String> foo_name = FACTORY->LookupUtf8Symbol("foo");
|
||||
Handle<String> foo_name = FACTORY->InternalizeUtf8String("foo");
|
||||
|
||||
// This compile will add the code to the compilation cache.
|
||||
{ v8::HandleScope scope;
|
||||
@ -2261,7 +2262,7 @@ TEST(Regress2211) {
|
||||
|
||||
// Check values.
|
||||
CHECK_EQ(hash,
|
||||
internal_obj->GetHiddenProperty(heap->identity_hash_symbol()));
|
||||
internal_obj->GetHiddenProperty(heap->identity_hash_string()));
|
||||
CHECK(value->Equals(obj->GetHiddenValue(v8_str("key string"))));
|
||||
|
||||
// Check size.
|
||||
@ -2536,7 +2537,7 @@ TEST(Regression144230) {
|
||||
// Fourth is the tricky part. Make sure the code containing the CallIC is
|
||||
// visited first without clearing the IC. The shared function info is then
|
||||
// visited later, causing the CallIC to be cleared.
|
||||
Handle<String> name = FACTORY->LookupUtf8Symbol("call");
|
||||
Handle<String> name = isolate->factory()->InternalizeUtf8String("call");
|
||||
Handle<GlobalObject> global(isolate->context()->global_object());
|
||||
MaybeObject* maybe_call = global->GetProperty(*name);
|
||||
JSFunction* call = JSFunction::cast(maybe_call->ToObjectChecked());
|
||||
|
@ -184,8 +184,8 @@ TEST(MarkCompactCollector) {
|
||||
JSObject::kHeaderSize)->ToObjectChecked();
|
||||
|
||||
// allocate a garbage
|
||||
String* func_name =
|
||||
String::cast(HEAP->LookupUtf8Symbol("theFunction")->ToObjectChecked());
|
||||
String* func_name = String::cast(
|
||||
HEAP->InternalizeUtf8String("theFunction")->ToObjectChecked());
|
||||
SharedFunctionInfo* function_share = SharedFunctionInfo::cast(
|
||||
HEAP->AllocateSharedFunctionInfo(func_name)->ToObjectChecked());
|
||||
JSFunction* function = JSFunction::cast(
|
||||
@ -203,8 +203,8 @@ TEST(MarkCompactCollector) {
|
||||
HEAP->AllocateJSObject(function)->ToObjectChecked());
|
||||
HEAP->CollectGarbage(OLD_POINTER_SPACE);
|
||||
|
||||
func_name =
|
||||
String::cast(HEAP->LookupUtf8Symbol("theFunction")->ToObjectChecked());
|
||||
func_name = String::cast(
|
||||
HEAP->InternalizeUtf8String("theFunction")->ToObjectChecked());
|
||||
CHECK(Isolate::Current()->context()->global_object()->
|
||||
HasLocalProperty(func_name));
|
||||
Object* func_value = Isolate::Current()->context()->global_object()->
|
||||
@ -214,11 +214,11 @@ TEST(MarkCompactCollector) {
|
||||
|
||||
obj = JSObject::cast(HEAP->AllocateJSObject(function)->ToObjectChecked());
|
||||
String* obj_name =
|
||||
String::cast(HEAP->LookupUtf8Symbol("theObject")->ToObjectChecked());
|
||||
String::cast(HEAP->InternalizeUtf8String("theObject")->ToObjectChecked());
|
||||
Isolate::Current()->context()->global_object()->SetProperty(
|
||||
obj_name, obj, NONE, kNonStrictMode)->ToObjectChecked();
|
||||
String* prop_name =
|
||||
String::cast(HEAP->LookupUtf8Symbol("theSlot")->ToObjectChecked());
|
||||
String::cast(HEAP->InternalizeUtf8String("theSlot")->ToObjectChecked());
|
||||
obj->SetProperty(prop_name,
|
||||
Smi::FromInt(23),
|
||||
NONE,
|
||||
@ -227,7 +227,7 @@ TEST(MarkCompactCollector) {
|
||||
HEAP->CollectGarbage(OLD_POINTER_SPACE);
|
||||
|
||||
obj_name =
|
||||
String::cast(HEAP->LookupUtf8Symbol("theObject")->ToObjectChecked());
|
||||
String::cast(HEAP->InternalizeUtf8String("theObject")->ToObjectChecked());
|
||||
CHECK(Isolate::Current()->context()->global_object()->
|
||||
HasLocalProperty(obj_name));
|
||||
CHECK(Isolate::Current()->context()->global_object()->
|
||||
@ -235,7 +235,7 @@ TEST(MarkCompactCollector) {
|
||||
obj = JSObject::cast(Isolate::Current()->context()->global_object()->
|
||||
GetProperty(obj_name)->ToObjectChecked());
|
||||
prop_name =
|
||||
String::cast(HEAP->LookupUtf8Symbol("theSlot")->ToObjectChecked());
|
||||
String::cast(HEAP->InternalizeUtf8String("theSlot")->ToObjectChecked());
|
||||
CHECK(obj->GetProperty(prop_name) == Smi::FromInt(23));
|
||||
}
|
||||
|
||||
|
0
test/cctest/test-parsing.cc
Executable file → Normal file
0
test/cctest/test-parsing.cc
Executable file → Normal file
@ -83,10 +83,10 @@ TEST(CrankshaftRandom) {
|
||||
|
||||
CompileRun("function f() { return Math.random(); }");
|
||||
|
||||
Object* symbol = FACTORY->LookupOneByteSymbol(STATIC_ASCII_VECTOR("f"))->
|
||||
Object* string = FACTORY->InternalizeOneByteString(STATIC_ASCII_VECTOR("f"))->
|
||||
ToObjectChecked();
|
||||
MaybeObject* fun_object =
|
||||
context->global_object()->GetProperty(String::cast(symbol));
|
||||
context->global_object()->GetProperty(String::cast(string));
|
||||
Handle<JSFunction> fun(JSFunction::cast(fun_object->ToObjectChecked()));
|
||||
|
||||
// Optimize function.
|
||||
|
@ -288,8 +288,8 @@ static void SanityCheck() {
|
||||
#endif
|
||||
CHECK(Isolate::Current()->global_object()->IsJSObject());
|
||||
CHECK(Isolate::Current()->native_context()->IsContext());
|
||||
CHECK(HEAP->symbol_table()->IsSymbolTable());
|
||||
CHECK(!FACTORY->LookupOneByteSymbol(
|
||||
CHECK(HEAP->string_table()->IsStringTable());
|
||||
CHECK(!FACTORY->InternalizeOneByteString(
|
||||
STATIC_ASCII_VECTOR("Empty"))->IsFailure());
|
||||
}
|
||||
|
||||
|
@ -173,7 +173,7 @@ TEST(Regress2060a) {
|
||||
LocalContext context;
|
||||
v8::HandleScope scope;
|
||||
Handle<JSFunction> function =
|
||||
FACTORY->NewFunction(FACTORY->function_symbol(), FACTORY->null_value());
|
||||
FACTORY->NewFunction(FACTORY->function_string(), FACTORY->null_value());
|
||||
Handle<JSObject> key = FACTORY->NewJSObject(function);
|
||||
Handle<JSWeakMap> weakmap = AllocateJSWeakMap();
|
||||
|
||||
@ -209,7 +209,7 @@ TEST(Regress2060b) {
|
||||
LocalContext context;
|
||||
v8::HandleScope scope;
|
||||
Handle<JSFunction> function =
|
||||
FACTORY->NewFunction(FACTORY->function_symbol(), FACTORY->null_value());
|
||||
FACTORY->NewFunction(FACTORY->function_string(), FACTORY->null_value());
|
||||
|
||||
// Start second old-space page so that keys land on evacuation candidate.
|
||||
Page* first_page = HEAP->old_pointer_space()->anchor()->next_page();
|
||||
|
Loading…
Reference in New Issue
Block a user