Implement ES6 Symbol
authorutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 31 Jan 2015 01:23:56 +0000 (01:23 +0000)
committerutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 31 Jan 2015 01:23:56 +0000 (01:23 +0000)
commitdba9ac2b694ceae6146ebb22b0bda4f6ddb802c7
tree3c9bd29d9c611fe6420984016ce6fd0909db23c0
parent2a02ae2c6cf3da40a9b7157d080ead67dfeab869
Implement ES6 Symbol
https://bugs.webkit.org/show_bug.cgi?id=140435

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

This patch implements ES6 Symbol. In this patch, we don't support
Symbol.keyFor, Symbol.for, Object.getOwnPropertySymbols. They will be
supported in the subsequent patches.

Since ES6 Symbol is introduced as new primitive value, we implement
Symbol as a derived class from JSCell. And now JSValue accepts Symbol*
as a new primitive value.

Symbol has a *unique* flagged StringImpl* as an `uid`. Which pointer
value represents the Symbol's identity. So don't compare Symbol's
JSCell pointer value for comparison.
This enables re-producing Symbol primitive value from StringImpl* uid
by executing`Symbol::create(vm, uid)`. This is needed to produce
Symbol primitive values from stored StringImpl* in `Object.getOwnPropertySymbols`.

And Symbol.[[Description]] is folded into the string value of Symbol's uid.
By doing so, we can represent ES6 Symbol without extending current PropertyTable key; StringImpl*.

* CMakeLists.txt:
* DerivedSources.make:
* JavaScriptCore.order:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
* JavaScriptCore.xcodeproj/project.pbxproj:
* builtins/BuiltinExecutables.cpp:
(JSC::BuiltinExecutables::createBuiltinExecutable):
* builtins/BuiltinNames.h:
* dfg/DFGOperations.cpp:
(JSC::DFG::operationPutByValInternal):
* inspector/JSInjectedScriptHost.cpp:
(Inspector::JSInjectedScriptHost::subtype):
* interpreter/Interpreter.cpp:
* jit/JITOperations.cpp:
(JSC::getByVal):
* llint/LLIntData.cpp:
(JSC::LLInt::Data::performAssertions):
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::getByVal):
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* llint/LowLevelInterpreter.asm:
* runtime/CommonIdentifiers.h:
* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL):
* runtime/CommonSlowPaths.h:
(JSC::CommonSlowPaths::opIn):
* runtime/ExceptionHelpers.cpp:
(JSC::createUndefinedVariableError):
* runtime/JSCJSValue.cpp:
(JSC::JSValue::synthesizePrototype):
(JSC::JSValue::dumpInContextAssumingStructure):
(JSC::JSValue::toStringSlowCase):
* runtime/JSCJSValue.h:
* runtime/JSCJSValueInlines.h:
(JSC::JSValue::isSymbol):
(JSC::JSValue::isPrimitive):
(JSC::JSValue::toPropertyKey):

It represents ToPropertyKey abstract operation in the ES6 spec.
It cleans up the old implementation's `isName` checks.
And to prevent performance regressions in
    js/regress/fold-get-by-id-to-multi-get-by-offset-rare-int.html
    js/regress/fold-get-by-id-to-multi-get-by-offset.html
we annnotate this function as ALWAYS_INLINE.

(JSC::JSValue::getPropertySlot):
(JSC::JSValue::get):
(JSC::JSValue::equalSlowCaseInline):
(JSC::JSValue::strictEqualSlowCaseInline):
* runtime/JSCell.cpp:
(JSC::JSCell::put):
(JSC::JSCell::putByIndex):
(JSC::JSCell::toPrimitive):
(JSC::JSCell::getPrimitiveNumber):
(JSC::JSCell::toNumber):
(JSC::JSCell::toObject):
* runtime/JSCell.h:
* runtime/JSCellInlines.h:
(JSC::JSCell::isSymbol):
(JSC::JSCell::toBoolean):
(JSC::JSCell::pureToBoolean):
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
(JSC::JSGlobalObject::visitChildren):
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::symbolPrototype):
(JSC::JSGlobalObject::symbolObjectStructure):
* runtime/JSONObject.cpp:
(JSC::Stringifier::Stringifier):
* runtime/JSSymbolTableObject.cpp:
(JSC::JSSymbolTableObject::getOwnNonIndexPropertyNames):
* runtime/JSType.h:
* runtime/JSTypeInfo.h:
(JSC::TypeInfo::isName): Deleted.
* runtime/MapData.cpp:
(JSC::MapData::find):
(JSC::MapData::add):
(JSC::MapData::remove):
(JSC::MapData::replaceAndPackBackingStore):
* runtime/MapData.h:
(JSC::MapData::clear):
* runtime/NameInstance.h: Removed.
* runtime/NamePrototype.cpp: Removed.
* runtime/ObjectConstructor.cpp:
(JSC::objectConstructorGetOwnPropertyDescriptor):
(JSC::objectConstructorDefineProperty):
* runtime/ObjectPrototype.cpp:
(JSC::objectProtoFuncHasOwnProperty):
(JSC::objectProtoFuncDefineGetter):
(JSC::objectProtoFuncDefineSetter):
(JSC::objectProtoFuncLookupGetter):
(JSC::objectProtoFuncLookupSetter):
(JSC::objectProtoFuncPropertyIsEnumerable):
* runtime/Operations.cpp:
(JSC::jsTypeStringForValue):
(JSC::jsIsObjectType):
* runtime/PrivateName.h:
(JSC::PrivateName::PrivateName):
(JSC::PrivateName::operator==):
(JSC::PrivateName::operator!=):
* runtime/PropertyMapHashTable.h:
(JSC::PropertyTable::find):
(JSC::PropertyTable::get):
* runtime/PropertyName.h:
(JSC::PropertyName::PropertyName):
(JSC::PropertyName::publicName):
* runtime/SmallStrings.h:
* runtime/StringConstructor.cpp:
(JSC::callStringConstructor):

In ES6, String constructor accepts Symbol to execute `String(symbol)`.

* runtime/Structure.cpp:
(JSC::Structure::getPropertyNamesFromStructure):
* runtime/StructureInlines.h:
(JSC::Structure::prototypeForLookup):
* runtime/Symbol.cpp: Added.
(JSC::Symbol::Symbol):
(JSC::SymbolObject::create):
(JSC::Symbol::toPrimitive):
(JSC::Symbol::toBoolean):
(JSC::Symbol::getPrimitiveNumber):
(JSC::Symbol::toObject):
(JSC::Symbol::toNumber):
(JSC::Symbol::destroy):
(JSC::Symbol::descriptiveString):
* runtime/Symbol.h: Added.
(JSC::Symbol::createStructure):
(JSC::Symbol::create):
(JSC::Symbol::privateName):
(JSC::Symbol::finishCreation):
(JSC::asSymbol):
* runtime/SymbolConstructor.cpp: Renamed from Source/JavaScriptCore/runtime/NameConstructor.cpp.
(JSC::SymbolConstructor::SymbolConstructor):
(JSC::SymbolConstructor::finishCreation):
(JSC::callSymbol):
(JSC::SymbolConstructor::getConstructData):
(JSC::SymbolConstructor::getCallData):
* runtime/SymbolConstructor.h: Renamed from Source/JavaScriptCore/runtime/NameConstructor.h.
(JSC::SymbolConstructor::create):
(JSC::SymbolConstructor::createStructure):
* runtime/SymbolObject.cpp: Renamed from Source/JavaScriptCore/runtime/NameInstance.cpp.
(JSC::SymbolObject::SymbolObject):
(JSC::SymbolObject::finishCreation):
(JSC::SymbolObject::defaultValue):

Now JSC doesn't support @@toPrimitive. So instead of it, we implement
Symbol.prototype[@@toPrimitive] as ES5 Symbol.[[DefaultValue]].

* runtime/SymbolObject.h: Added.
(JSC::SymbolObject::create):
(JSC::SymbolObject::internalValue):
(JSC::SymbolObject::createStructure):
* runtime/SymbolPrototype.cpp: Added.
(JSC::SymbolPrototype::SymbolPrototype):
(JSC::SymbolPrototype::finishCreation):
(JSC::SymbolPrototype::getOwnPropertySlot):
(JSC::symbolProtoFuncToString):
(JSC::symbolProtoFuncValueOf):
* runtime/SymbolPrototype.h: Renamed from Source/JavaScriptCore/runtime/NamePrototype.h.
(JSC::SymbolPrototype::create):
(JSC::SymbolPrototype::createStructure):

SymbolPrototype object is ordinary JS object. Not wrapper object of Symbol.
It is tested in js/symbol-prototype-is-ordinary-object.html.

* runtime/VM.cpp:
(JSC::VM::VM):
* runtime/VM.h:

Source/WTF:

Introduce new unique string mechanizm into StringImpl.
It is used for implementing Symbol which holds a [[Description]] value.

* wtf/text/AtomicString.h:
(WTF::AtomicString::add):
(WTF::AtomicString::addWithStringTableProvider):

Previously, we checked `isAtomic()` or `!length()`. This guard can filter out EmptyUnique.
But now, we introduced new unique StringImpl. Since it has an actual string value, we need to check `isUnique()`.

* wtf/text/StringImpl.cpp:
(WTF::StringImpl::~StringImpl):
(WTF::StringImpl::createUnique):

In createUnique, we leverage Substring mechanizm to produce a new unique
string from an existing string.

* wtf/text/StringImpl.h:
(WTF::StringImpl::StringImpl):
(WTF::StringImpl::createUniqueEmpty):
(WTF::StringImpl::flagIsUnique):
(WTF::StringImpl::isUnique):
(WTF::StringImpl::setIsAtomic):
(WTF::StringImpl::createEmptyUnique): Deleted.
(WTF::StringImpl::isEmptyUnique): Deleted.

Instead of EmptyUnique, we introduced new flag to StringImpl, `isUnique`.
While EmptyUnique cannot hold any string values except for empty string,
the unique StringImpl can hold any String values.
We fold the Symbol's descriptiveString value here.

* wtf/text/StringStatics.cpp:
(WTF::StringImpl::hashAndFlagsForUnique):
(WTF::StringImpl::hashAndFlagsForEmptyUnique): Deleted.

LayoutTests:

* js/script-tests/symbol-abstract-equality-comparison.js: Added.
(Pair):
(relationalOperators.forEach):
* js/script-tests/symbol-abstract-relational-comparison.js: Added.
(relationalOperators.forEach):
* js/script-tests/symbol-in-map.js: Added.
(set shouldBe):
* js/script-tests/symbol-object.js: Added.
* js/script-tests/symbol-prototype-is-ordinary-object.js: Added.
* js/script-tests/symbol-strict-equality-comparison.js: Added.
(Pair):
(relationalOperators.forEach):
* js/script-tests/symbol-tostring.js: Added.
* js/script-tests/symbols.js: Renamed from LayoutTests/js/script-tests/names.js.
(forIn):
* js/symbol-abstract-equality-comparison-expected.txt: Added.
* js/symbol-abstract-equality-comparison.html: Copied from LayoutTests/js/names.html.
* js/symbol-abstract-relational-comparison-expected.txt: Added.
* js/symbol-abstract-relational-comparison.html: Copied from LayoutTests/js/names.html.
* js/symbol-in-map-expected.txt: Added.
* js/symbol-in-map.html: Copied from LayoutTests/js/names.html.
* js/symbol-object-expected.txt: Added.
* js/symbol-object.html: Copied from LayoutTests/js/names.html.
* js/symbol-prototype-is-ordinary-object-expected.txt: Added.
* js/symbol-prototype-is-ordinary-object.html: Copied from LayoutTests/js/names.html.
* js/symbol-strict-equality-comparison-expected.txt: Added.
* js/symbol-strict-equality-comparison.html: Copied from LayoutTests/js/names.html.
* js/symbol-tostring-expected.txt: Added.
* js/symbol-tostring.html: Copied from LayoutTests/js/names.html.
* js/symbols-expected.txt: Renamed from LayoutTests/js/names-expected.txt.
* js/symbols.html: Renamed from LayoutTests/js/names.html.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@179429 268f45cc-cd09-0410-ab3c-d52691b4dbfc
86 files changed:
LayoutTests/ChangeLog
LayoutTests/js/script-tests/symbol-abstract-equality-comparison.js [new file with mode: 0644]
LayoutTests/js/script-tests/symbol-abstract-relational-comparison.js [new file with mode: 0644]
LayoutTests/js/script-tests/symbol-in-map.js [new file with mode: 0644]
LayoutTests/js/script-tests/symbol-object.js [new file with mode: 0644]
LayoutTests/js/script-tests/symbol-prototype-is-ordinary-object.js [new file with mode: 0644]
LayoutTests/js/script-tests/symbol-strict-equality-comparison.js [new file with mode: 0644]
LayoutTests/js/script-tests/symbol-tostring.js [new file with mode: 0644]
LayoutTests/js/script-tests/symbols.js [moved from LayoutTests/js/script-tests/names.js with 88% similarity]
LayoutTests/js/symbol-abstract-equality-comparison-expected.txt [new file with mode: 0644]
LayoutTests/js/symbol-abstract-equality-comparison.html [new file with mode: 0644]
LayoutTests/js/symbol-abstract-relational-comparison-expected.txt [new file with mode: 0644]
LayoutTests/js/symbol-abstract-relational-comparison.html [new file with mode: 0644]
LayoutTests/js/symbol-in-map-expected.txt [new file with mode: 0644]
LayoutTests/js/symbol-in-map.html [new file with mode: 0644]
LayoutTests/js/symbol-object-expected.txt [new file with mode: 0644]
LayoutTests/js/symbol-object.html [new file with mode: 0644]
LayoutTests/js/symbol-prototype-is-ordinary-object-expected.txt [new file with mode: 0644]
LayoutTests/js/symbol-prototype-is-ordinary-object.html [new file with mode: 0644]
LayoutTests/js/symbol-strict-equality-comparison-expected.txt [new file with mode: 0644]
LayoutTests/js/symbol-strict-equality-comparison.html [new file with mode: 0644]
LayoutTests/js/symbol-tostring-expected.txt [new file with mode: 0644]
LayoutTests/js/symbol-tostring.html [new file with mode: 0644]
LayoutTests/js/symbols-expected.txt [moved from LayoutTests/js/names-expected.txt with 88% similarity]
LayoutTests/js/symbols.html [moved from LayoutTests/js/names.html with 80% similarity]
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/DerivedSources.make
Source/JavaScriptCore/JavaScriptCore.order
Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj
Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/builtins/BuiltinExecutables.cpp
Source/JavaScriptCore/builtins/BuiltinNames.h
Source/JavaScriptCore/dfg/DFGOperations.cpp
Source/JavaScriptCore/inspector/JSInjectedScriptHost.cpp
Source/JavaScriptCore/interpreter/Interpreter.cpp
Source/JavaScriptCore/jit/JITOperations.cpp
Source/JavaScriptCore/llint/LLIntData.cpp
Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
Source/JavaScriptCore/llint/LowLevelInterpreter.asm
Source/JavaScriptCore/runtime/CommonIdentifiers.h
Source/JavaScriptCore/runtime/CommonSlowPaths.cpp
Source/JavaScriptCore/runtime/CommonSlowPaths.h
Source/JavaScriptCore/runtime/ExceptionHelpers.cpp
Source/JavaScriptCore/runtime/JSCJSValue.cpp
Source/JavaScriptCore/runtime/JSCJSValue.h
Source/JavaScriptCore/runtime/JSCJSValueInlines.h
Source/JavaScriptCore/runtime/JSCell.cpp
Source/JavaScriptCore/runtime/JSCell.h
Source/JavaScriptCore/runtime/JSCellInlines.h
Source/JavaScriptCore/runtime/JSGlobalObject.cpp
Source/JavaScriptCore/runtime/JSGlobalObject.h
Source/JavaScriptCore/runtime/JSONObject.cpp
Source/JavaScriptCore/runtime/JSSymbolTableObject.cpp
Source/JavaScriptCore/runtime/JSType.h
Source/JavaScriptCore/runtime/JSTypeInfo.h
Source/JavaScriptCore/runtime/MapData.cpp
Source/JavaScriptCore/runtime/MapData.h
Source/JavaScriptCore/runtime/NameInstance.h [deleted file]
Source/JavaScriptCore/runtime/NamePrototype.cpp [deleted file]
Source/JavaScriptCore/runtime/ObjectConstructor.cpp
Source/JavaScriptCore/runtime/ObjectPrototype.cpp
Source/JavaScriptCore/runtime/Operations.cpp
Source/JavaScriptCore/runtime/PrivateName.h
Source/JavaScriptCore/runtime/PropertyMapHashTable.h
Source/JavaScriptCore/runtime/PropertyName.h
Source/JavaScriptCore/runtime/SmallStrings.h
Source/JavaScriptCore/runtime/StringConstructor.cpp
Source/JavaScriptCore/runtime/Structure.cpp
Source/JavaScriptCore/runtime/StructureInlines.h
Source/JavaScriptCore/runtime/Symbol.cpp [new file with mode: 0644]
Source/JavaScriptCore/runtime/Symbol.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/SymbolConstructor.cpp [moved from Source/JavaScriptCore/runtime/NameConstructor.cpp with 58% similarity]
Source/JavaScriptCore/runtime/SymbolConstructor.h [moved from Source/JavaScriptCore/runtime/NameConstructor.h with 74% similarity]
Source/JavaScriptCore/runtime/SymbolObject.cpp [moved from Source/JavaScriptCore/runtime/NameInstance.cpp with 66% similarity]
Source/JavaScriptCore/runtime/SymbolObject.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/SymbolPrototype.cpp [new file with mode: 0644]
Source/JavaScriptCore/runtime/SymbolPrototype.h [moved from Source/JavaScriptCore/runtime/NamePrototype.h with 72% similarity]
Source/JavaScriptCore/runtime/VM.cpp
Source/JavaScriptCore/runtime/VM.h
Source/WTF/ChangeLog
Source/WTF/wtf/text/AtomicString.h
Source/WTF/wtf/text/StringImpl.cpp
Source/WTF/wtf/text/StringImpl.h
Source/WTF/wtf/text/StringStatics.cpp