diff options
Diffstat (limited to 'Source/JavaScriptCore/runtime')
43 files changed, 758 insertions, 204 deletions
diff --git a/Source/JavaScriptCore/runtime/Arguments.cpp b/Source/JavaScriptCore/runtime/Arguments.cpp index 1fd05fd9e..4628cec8d 100644 --- a/Source/JavaScriptCore/runtime/Arguments.cpp +++ b/Source/JavaScriptCore/runtime/Arguments.cpp @@ -358,6 +358,9 @@ void Arguments::tearOff(CallFrame* callFrame) if (!d->numArguments) return; + // Must be called for the same call frame from which it was created. + ASSERT(bitwise_cast<WriteBarrier<Unknown>*>(callFrame) == d->registers); + d->registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[d->numArguments]); d->registers = d->registerArray.get() + CallFrame::offsetFor(d->numArguments + 1); @@ -367,7 +370,28 @@ void Arguments::tearOff(CallFrame* callFrame) return; } - InlineCallFrame* inlineCallFrame = callFrame->inlineCallFrame(); + tearOffForInlineCallFrame( + callFrame->globalData(), callFrame->registers(), callFrame->inlineCallFrame()); +} + +void Arguments::tearOff(CallFrame* callFrame, InlineCallFrame* inlineCallFrame) +{ + if (isTornOff()) + return; + + if (!d->numArguments) + return; + + d->registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[d->numArguments]); + d->registers = d->registerArray.get() + CallFrame::offsetFor(d->numArguments + 1); + + tearOffForInlineCallFrame( + callFrame->globalData(), callFrame->registers() + inlineCallFrame->stackOffset, + inlineCallFrame); +} + +void Arguments::tearOffForInlineCallFrame(JSGlobalData& globalData, Register* registers, InlineCallFrame* inlineCallFrame) +{ for (size_t i = 0; i < d->numArguments; ++i) { ValueRecovery& recovery = inlineCallFrame->arguments[i + 1]; // In the future we'll support displaced recoveries (indicating that the @@ -376,7 +400,7 @@ void Arguments::tearOff(CallFrame* callFrame) // it's much less likely that we'll support in-register recoveries since // this code does not (easily) have access to registers. JSValue value; - Register* location = &callFrame->registers()[CallFrame::argumentOffset(i)]; + Register* location = ®isters[CallFrame::argumentOffset(i)]; switch (recovery.technique()) { case AlreadyInRegisterFile: value = location->jsValue(); @@ -404,7 +428,7 @@ void Arguments::tearOff(CallFrame* callFrame) ASSERT_NOT_REACHED(); break; } - argument(i).set(callFrame->globalData(), this, value); + argument(i).set(globalData, this, value); } } diff --git a/Source/JavaScriptCore/runtime/Arguments.h b/Source/JavaScriptCore/runtime/Arguments.h index 5925ed491..90eed25fa 100644 --- a/Source/JavaScriptCore/runtime/Arguments.h +++ b/Source/JavaScriptCore/runtime/Arguments.h @@ -41,16 +41,20 @@ namespace JSC { unsigned numArguments; + // We make these full byte booleans to make them easy to test from the JIT, + // and because even if they were single-bit booleans we still wouldn't save + // any space. + bool overrodeLength; + bool overrodeCallee; + bool overrodeCaller; + bool isStrictMode; + WriteBarrier<Unknown>* registers; OwnArrayPtr<WriteBarrier<Unknown> > registerArray; OwnArrayPtr<bool> deletedArguments; WriteBarrier<JSFunction> callee; - bool overrodeLength : 1; - bool overrodeCallee : 1; - bool overrodeCaller : 1; - bool isStrictMode : 1; }; class Arguments : public JSNonFinalObject { @@ -63,6 +67,13 @@ namespace JSC { arguments->finishCreation(callFrame); return arguments; } + + static Arguments* create(JSGlobalData& globalData, CallFrame* callFrame, InlineCallFrame* inlineCallFrame) + { + Arguments* arguments = new (NotNull, allocateCell<Arguments>(globalData.heap)) Arguments(callFrame); + arguments->finishCreation(callFrame, inlineCallFrame); + return arguments; + } enum { MaxArguments = 0x10000 }; @@ -71,6 +82,8 @@ namespace JSC { Arguments(CallFrame*); Arguments(CallFrame*, NoParametersType); + + void tearOffForInlineCallFrame(JSGlobalData& globalData, Register*, InlineCallFrame*); public: static const ClassInfo s_info; @@ -88,6 +101,7 @@ namespace JSC { void copyToArguments(ExecState*, CallFrame*, uint32_t length); void tearOff(CallFrame*); + void tearOff(CallFrame*, InlineCallFrame*); bool isTornOff() const { return d->registerArray; } void didTearOffActivation(JSGlobalData& globalData, JSActivation* activation) { @@ -101,11 +115,14 @@ namespace JSC { { return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); } + + static ptrdiff_t offsetOfData() { return OBJECT_OFFSETOF(Arguments, d); } protected: static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags; void finishCreation(CallFrame*); + void finishCreation(CallFrame*, InlineCallFrame*); private: static void destroy(JSCell*); @@ -173,6 +190,26 @@ namespace JSC { tearOff(callFrame); } + inline void Arguments::finishCreation(CallFrame* callFrame, InlineCallFrame* inlineCallFrame) + { + Base::finishCreation(callFrame->globalData()); + ASSERT(inherits(&s_info)); + + JSFunction* callee = inlineCallFrame->callee.get(); + d->numArguments = inlineCallFrame->arguments.size() - 1; + d->registers = reinterpret_cast<WriteBarrier<Unknown>*>(callFrame->registers()) + inlineCallFrame->stackOffset; + d->callee.set(callFrame->globalData(), this, callee); + d->overrodeLength = false; + d->overrodeCallee = false; + d->overrodeCaller = false; + d->isStrictMode = jsCast<FunctionExecutable*>(inlineCallFrame->executable.get())->isStrictMode(); + + // The bytecode generator omits op_tear_off_activation in cases of no + // declared parameters, so we need to tear off immediately. + if (d->isStrictMode || !callee->jsExecutable()->parameterCount()) + tearOff(callFrame, inlineCallFrame); + } + } // namespace JSC #endif // Arguments_h diff --git a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp index b73a1296a..b0adb7f0f 100644 --- a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp +++ b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp @@ -797,7 +797,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState* exec) cachedCall.setArgument(2, thisObj); JSValue result = cachedCall.call(); - if (result.toBoolean(exec)) + if (result.toBoolean()) resultArray->putDirectIndex(exec, filterIndex++, v); } if (k == length) @@ -818,7 +818,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState* exec) eachArguments.append(thisObj); JSValue result = call(exec, function, callType, callData, applyThis, eachArguments); - if (result.toBoolean(exec)) + if (result.toBoolean()) resultArray->putDirectIndex(exec, filterIndex++, v); } return JSValue::encode(resultArray); @@ -917,7 +917,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncEvery(ExecState* exec) cachedCall.setArgument(1, jsNumber(k)); cachedCall.setArgument(2, thisObj); JSValue result = cachedCall.call(); - if (!result.toBoolean(cachedCall.newCallFrame(exec))) + if (!result.toBoolean()) return JSValue::encode(jsBoolean(false)); } } @@ -934,7 +934,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncEvery(ExecState* exec) if (exec->hadException()) return JSValue::encode(jsUndefined()); - bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments).toBoolean(exec); + bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments).toBoolean(); if (!predicateResult) { result = jsBoolean(false); break; @@ -1025,7 +1025,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSome(ExecState* exec) cachedCall.setArgument(1, jsNumber(k)); cachedCall.setArgument(2, thisObj); JSValue result = cachedCall.call(); - if (result.toBoolean(cachedCall.newCallFrame(exec))) + if (result.toBoolean()) return JSValue::encode(jsBoolean(true)); } } @@ -1042,7 +1042,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSome(ExecState* exec) if (exec->hadException()) return JSValue::encode(jsUndefined()); - bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments).toBoolean(exec); + bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments).toBoolean(); if (predicateResult) { result = jsBoolean(true); break; diff --git a/Source/JavaScriptCore/runtime/BooleanConstructor.cpp b/Source/JavaScriptCore/runtime/BooleanConstructor.cpp index 9b666292c..090be0aaa 100644 --- a/Source/JavaScriptCore/runtime/BooleanConstructor.cpp +++ b/Source/JavaScriptCore/runtime/BooleanConstructor.cpp @@ -49,7 +49,7 @@ void BooleanConstructor::finishCreation(ExecState* exec, BooleanPrototype* boole JSObject* constructBoolean(ExecState* exec, const ArgList& args) { BooleanObject* obj = BooleanObject::create(exec->globalData(), asInternalFunction(exec->callee())->globalObject()->booleanObjectStructure()); - obj->setInternalValue(exec->globalData(), jsBoolean(args.at(0).toBoolean(exec))); + obj->setInternalValue(exec->globalData(), jsBoolean(args.at(0).toBoolean())); return obj; } @@ -68,7 +68,7 @@ ConstructType BooleanConstructor::getConstructData(JSCell*, ConstructData& const // ECMA 15.6.1 static EncodedJSValue JSC_HOST_CALL callBooleanConstructor(ExecState* exec) { - return JSValue::encode(jsBoolean(exec->argument(0).toBoolean(exec))); + return JSValue::encode(jsBoolean(exec->argument(0).toBoolean())); } CallType BooleanConstructor::getCallData(JSCell*, CallData& callData) diff --git a/Source/JavaScriptCore/runtime/CommonSlowPaths.h b/Source/JavaScriptCore/runtime/CommonSlowPaths.h index c41ced7ee..0d3480104 100644 --- a/Source/JavaScriptCore/runtime/CommonSlowPaths.h +++ b/Source/JavaScriptCore/runtime/CommonSlowPaths.h @@ -30,6 +30,7 @@ #include "CodeSpecializationKind.h" #include "ExceptionHelpers.h" #include "JSArray.h" +#include "NameInstance.h" namespace JSC { @@ -109,6 +110,9 @@ inline bool opIn(ExecState* exec, JSValue propName, JSValue baseVal) if (propName.getUInt32(i)) return baseObj->hasProperty(exec, i); + if (isName(propName)) + return baseObj->hasProperty(exec, jsCast<NameInstance*>(propName.asCell())->privateName()); + Identifier property(exec, propName.toString(exec)->value(exec)); if (exec->globalData().exception) return false; diff --git a/Source/JavaScriptCore/runtime/Executable.cpp b/Source/JavaScriptCore/runtime/Executable.cpp index 3690c2c33..0a6425a59 100644 --- a/Source/JavaScriptCore/runtime/Executable.cpp +++ b/Source/JavaScriptCore/runtime/Executable.cpp @@ -181,9 +181,9 @@ JSObject* EvalExecutable::compileOptimized(ExecState* exec, ScopeChainNode* scop } #if ENABLE(JIT) -bool EvalExecutable::jitCompile(JSGlobalData& globalData) +bool EvalExecutable::jitCompile(ExecState* exec) { - return jitCompileIfAppropriate(globalData, m_evalCodeBlock, m_jitCodeForCall, JITCode::bottomTierJIT(), JITCompilationCanFail); + return jitCompileIfAppropriate(exec, m_evalCodeBlock, m_jitCodeForCall, JITCode::bottomTierJIT(), JITCompilationCanFail); } #endif @@ -244,7 +244,7 @@ JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scope } #if ENABLE(JIT) - if (!prepareForExecution(*globalData, m_evalCodeBlock, m_jitCodeForCall, jitType)) + if (!prepareForExecution(exec, m_evalCodeBlock, m_jitCodeForCall, jitType)) return 0; #endif @@ -330,9 +330,9 @@ JSObject* ProgramExecutable::compileOptimized(ExecState* exec, ScopeChainNode* s } #if ENABLE(JIT) -bool ProgramExecutable::jitCompile(JSGlobalData& globalData) +bool ProgramExecutable::jitCompile(ExecState* exec) { - return jitCompileIfAppropriate(globalData, m_programCodeBlock, m_jitCodeForCall, JITCode::bottomTierJIT(), JITCompilationCanFail); + return jitCompileIfAppropriate(exec, m_programCodeBlock, m_jitCodeForCall, JITCode::bottomTierJIT(), JITCompilationCanFail); } #endif @@ -376,7 +376,7 @@ JSObject* ProgramExecutable::compileInternal(ExecState* exec, ScopeChainNode* sc } #if ENABLE(JIT) - if (!prepareForExecution(*globalData, m_programCodeBlock, m_jitCodeForCall, jitType)) + if (!prepareForExecution(exec, m_programCodeBlock, m_jitCodeForCall, jitType)) return 0; #endif @@ -479,14 +479,14 @@ JSObject* FunctionExecutable::compileOptimizedForConstruct(ExecState* exec, Scop } #if ENABLE(JIT) -bool FunctionExecutable::jitCompileForCall(JSGlobalData& globalData) +bool FunctionExecutable::jitCompileForCall(ExecState* exec) { - return jitCompileFunctionIfAppropriate(globalData, m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, m_symbolTable, JITCode::bottomTierJIT(), JITCompilationCanFail); + return jitCompileFunctionIfAppropriate(exec, m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, m_symbolTable, JITCode::bottomTierJIT(), JITCompilationCanFail); } -bool FunctionExecutable::jitCompileForConstruct(JSGlobalData& globalData) +bool FunctionExecutable::jitCompileForConstruct(ExecState* exec) { - return jitCompileFunctionIfAppropriate(globalData, m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, m_symbolTable, JITCode::bottomTierJIT(), JITCompilationCanFail); + return jitCompileFunctionIfAppropriate(exec, m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, m_symbolTable, JITCode::bottomTierJIT(), JITCompilationCanFail); } #endif @@ -551,7 +551,7 @@ JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChain m_symbolTable = m_codeBlockForCall->sharedSymbolTable(); #if ENABLE(JIT) - if (!prepareFunctionForExecution(exec->globalData(), m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, m_symbolTable, jitType, CodeForCall)) + if (!prepareFunctionForExecution(exec, m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, m_symbolTable, jitType, CodeForCall)) return 0; #endif @@ -593,7 +593,7 @@ JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, Scope m_symbolTable = m_codeBlockForConstruct->sharedSymbolTable(); #if ENABLE(JIT) - if (!prepareFunctionForExecution(exec->globalData(), m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, m_symbolTable, jitType, CodeForConstruct)) + if (!prepareFunctionForExecution(exec, m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, m_symbolTable, jitType, CodeForConstruct)) return 0; #endif diff --git a/Source/JavaScriptCore/runtime/Executable.h b/Source/JavaScriptCore/runtime/Executable.h index d8367ecc8..debb3e369 100644 --- a/Source/JavaScriptCore/runtime/Executable.h +++ b/Source/JavaScriptCore/runtime/Executable.h @@ -345,7 +345,7 @@ namespace JSC { #if ENABLE(JIT) void jettisonOptimizedCode(JSGlobalData&); - bool jitCompile(JSGlobalData&); + bool jitCompile(ExecState*); #endif EvalCodeBlock& generatedBytecode() @@ -420,7 +420,7 @@ namespace JSC { #if ENABLE(JIT) void jettisonOptimizedCode(JSGlobalData&); - bool jitCompile(JSGlobalData&); + bool jitCompile(ExecState*); #endif ProgramCodeBlock& generatedBytecode() @@ -522,7 +522,7 @@ namespace JSC { #if ENABLE(JIT) void jettisonOptimizedCodeForCall(JSGlobalData&); - bool jitCompileForCall(JSGlobalData&); + bool jitCompileForCall(ExecState*); #endif bool isGeneratedForCall() const @@ -550,7 +550,7 @@ namespace JSC { #if ENABLE(JIT) void jettisonOptimizedCodeForConstruct(JSGlobalData&); - bool jitCompileForConstruct(JSGlobalData&); + bool jitCompileForConstruct(ExecState*); #endif bool isGeneratedForConstruct() const @@ -599,12 +599,12 @@ namespace JSC { } } - bool jitCompileFor(JSGlobalData& globalData, CodeSpecializationKind kind) + bool jitCompileFor(ExecState* exec, CodeSpecializationKind kind) { if (kind == CodeForCall) - return jitCompileForCall(globalData); + return jitCompileForCall(exec); ASSERT(kind == CodeForConstruct); - return jitCompileForConstruct(globalData); + return jitCompileForConstruct(exec); } #endif diff --git a/Source/JavaScriptCore/runtime/ExecutionHarness.h b/Source/JavaScriptCore/runtime/ExecutionHarness.h index e58e6fc74..4cc37f3b7 100644 --- a/Source/JavaScriptCore/runtime/ExecutionHarness.h +++ b/Source/JavaScriptCore/runtime/ExecutionHarness.h @@ -36,32 +36,32 @@ namespace JSC { template<typename CodeBlockType> -inline bool prepareForExecution(JSGlobalData& globalData, OwnPtr<CodeBlockType>& codeBlock, JITCode& jitCode, JITCode::JITType jitType) +inline bool prepareForExecution(ExecState* exec, OwnPtr<CodeBlockType>& codeBlock, JITCode& jitCode, JITCode::JITType jitType) { #if ENABLE(LLINT) if (JITCode::isBaselineCode(jitType)) { // Start off in the low level interpreter. - LLInt::getEntrypoint(globalData, codeBlock.get(), jitCode); + LLInt::getEntrypoint(exec->globalData(), codeBlock.get(), jitCode); codeBlock->setJITCode(jitCode, MacroAssemblerCodePtr()); return true; } #endif // ENABLE(LLINT) - return jitCompileIfAppropriate(globalData, codeBlock, jitCode, jitType, JITCode::isBaselineCode(jitType) ? JITCompilationMustSucceed : JITCompilationCanFail); + return jitCompileIfAppropriate(exec, codeBlock, jitCode, jitType, JITCode::isBaselineCode(jitType) ? JITCompilationMustSucceed : JITCompilationCanFail); } -inline bool prepareFunctionForExecution(JSGlobalData& globalData, OwnPtr<FunctionCodeBlock>& codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck, SharedSymbolTable*& symbolTable, JITCode::JITType jitType, CodeSpecializationKind kind) +inline bool prepareFunctionForExecution(ExecState* exec, OwnPtr<FunctionCodeBlock>& codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck, SharedSymbolTable*& symbolTable, JITCode::JITType jitType, CodeSpecializationKind kind) { #if ENABLE(LLINT) if (JITCode::isBaselineCode(jitType)) { // Start off in the low level interpreter. - LLInt::getFunctionEntrypoint(globalData, kind, jitCode, jitCodeWithArityCheck); + LLInt::getFunctionEntrypoint(exec->globalData(), kind, jitCode, jitCodeWithArityCheck); codeBlock->setJITCode(jitCode, jitCodeWithArityCheck); return true; } #else UNUSED_PARAM(kind); #endif // ENABLE(LLINT) - return jitCompileFunctionIfAppropriate(globalData, codeBlock, jitCode, jitCodeWithArityCheck, symbolTable, jitType, JITCode::isBaselineCode(jitType) ? JITCompilationMustSucceed : JITCompilationCanFail); + return jitCompileFunctionIfAppropriate(exec, codeBlock, jitCode, jitCodeWithArityCheck, symbolTable, jitType, JITCode::isBaselineCode(jitType) ? JITCompilationMustSucceed : JITCompilationCanFail); } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/JSActivation.cpp b/Source/JavaScriptCore/runtime/JSActivation.cpp index f8883187e..5417b0023 100644 --- a/Source/JavaScriptCore/runtime/JSActivation.cpp +++ b/Source/JavaScriptCore/runtime/JSActivation.cpp @@ -92,7 +92,7 @@ void JSActivation::visitChildren(JSCell* cell, SlotVisitor& visitor) inline bool JSActivation::symbolTableGet(PropertyName propertyName, PropertySlot& slot) { - SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl()); + SymbolTableEntry entry = symbolTable().inlineGet(propertyName.publicName()); if (entry.isNull()) return false; if (m_isTornOff && entry.getIndex() >= m_numCapturedVars) @@ -107,7 +107,7 @@ inline bool JSActivation::symbolTablePut(ExecState* exec, PropertyName propertyN JSGlobalData& globalData = exec->globalData(); ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); - SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl()); + SymbolTableEntry entry = symbolTable().inlineGet(propertyName.publicName()); if (entry.isNull()) return false; if (entry.isReadOnly()) { @@ -141,7 +141,7 @@ inline bool JSActivation::symbolTablePutWithAttributes(JSGlobalData& globalData, { ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); - SymbolTable::iterator iter = symbolTable().find(propertyName.impl()); + SymbolTable::iterator iter = symbolTable().find(propertyName.publicName()); if (iter == symbolTable().end()) return false; SymbolTableEntry& entry = iter->second; diff --git a/Source/JavaScriptCore/runtime/JSCell.h b/Source/JavaScriptCore/runtime/JSCell.h index fa675fbca..0233f0fec 100644 --- a/Source/JavaScriptCore/runtime/JSCell.h +++ b/Source/JavaScriptCore/runtime/JSCell.h @@ -96,7 +96,7 @@ namespace JSC { // Basic conversions. JS_EXPORT_PRIVATE JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const; bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const; - bool toBoolean(ExecState*) const; + bool toBoolean() const; JS_EXPORT_PRIVATE double toNumber(ExecState*) const; JS_EXPORT_PRIVATE JSObject* toObject(ExecState*, JSGlobalObject*) const; diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.cpp b/Source/JavaScriptCore/runtime/JSGlobalData.cpp index 91ff9cefb..a13eb79c5 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalData.cpp +++ b/Source/JavaScriptCore/runtime/JSGlobalData.cpp @@ -57,6 +57,10 @@ #include <wtf/Threading.h> #include <wtf/WTFThreadData.h> +#if ENABLE(DFG_JIT) +#include "ConservativeRoots.h" +#endif + #if ENABLE(REGEXP_TRACING) #include "RegExp.h" #endif @@ -82,6 +86,7 @@ extern const HashTable numberConstructorTable; extern const HashTable numberPrototypeTable; JS_EXPORTDATA extern const HashTable objectConstructorTable; extern const HashTable objectPrototypeTable; +extern const HashTable privateNamePrototypeTable; extern const HashTable regExpTable; extern const HashTable regExpConstructorTable; extern const HashTable regExpPrototypeTable; @@ -113,8 +118,8 @@ static bool enableAssembler(ExecutableAllocator& executableAllocator) } #endif -JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType threadStackType, HeapSize heapSize) - : heap(this, heapSize) +JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType threadStackType, HeapType heapType) + : heap(this, heapType) , globalDataType(globalDataType) , clientData(0) , topCallFrame(CallFrame::noCaller()) @@ -131,6 +136,7 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread , numberPrototypeTable(fastNew<HashTable>(JSC::numberPrototypeTable)) , objectConstructorTable(fastNew<HashTable>(JSC::objectConstructorTable)) , objectPrototypeTable(fastNew<HashTable>(JSC::objectPrototypeTable)) + , privateNamePrototypeTable(fastNew<HashTable>(JSC::privateNamePrototypeTable)) , regExpTable(fastNew<HashTable>(JSC::regExpTable)) , regExpConstructorTable(fastNew<HashTable>(JSC::regExpConstructorTable)) , regExpPrototypeTable(fastNew<HashTable>(JSC::regExpPrototypeTable)) @@ -237,6 +243,7 @@ JSGlobalData::~JSGlobalData() numberPrototypeTable->deleteTable(); objectConstructorTable->deleteTable(); objectPrototypeTable->deleteTable(); + privateNamePrototypeTable->deleteTable(); regExpTable->deleteTable(); regExpConstructorTable->deleteTable(); regExpPrototypeTable->deleteTable(); @@ -256,6 +263,7 @@ JSGlobalData::~JSGlobalData() fastDelete(const_cast<HashTable*>(numberPrototypeTable)); fastDelete(const_cast<HashTable*>(objectConstructorTable)); fastDelete(const_cast<HashTable*>(objectPrototypeTable)); + fastDelete(const_cast<HashTable*>(privateNamePrototypeTable)); fastDelete(const_cast<HashTable*>(regExpTable)); fastDelete(const_cast<HashTable*>(regExpConstructorTable)); fastDelete(const_cast<HashTable*>(regExpPrototypeTable)); @@ -282,19 +290,19 @@ JSGlobalData::~JSGlobalData() #endif } -PassRefPtr<JSGlobalData> JSGlobalData::createContextGroup(ThreadStackType type, HeapSize heapSize) +PassRefPtr<JSGlobalData> JSGlobalData::createContextGroup(ThreadStackType type, HeapType heapType) { - return adoptRef(new JSGlobalData(APIContextGroup, type, heapSize)); + return adoptRef(new JSGlobalData(APIContextGroup, type, heapType)); } -PassRefPtr<JSGlobalData> JSGlobalData::create(ThreadStackType type, HeapSize heapSize) +PassRefPtr<JSGlobalData> JSGlobalData::create(ThreadStackType type, HeapType heapType) { - return adoptRef(new JSGlobalData(Default, type, heapSize)); + return adoptRef(new JSGlobalData(Default, type, heapType)); } -PassRefPtr<JSGlobalData> JSGlobalData::createLeaked(ThreadStackType type, HeapSize heapSize) +PassRefPtr<JSGlobalData> JSGlobalData::createLeaked(ThreadStackType type, HeapType heapType) { - return create(type, heapSize); + return create(type, heapType); } bool JSGlobalData::sharedInstanceExists() @@ -450,6 +458,19 @@ void releaseExecutableMemory(JSGlobalData& globalData) globalData.releaseExecutableMemory(); } +#if ENABLE(DFG_JIT) +void JSGlobalData::gatherConservativeRoots(ConservativeRoots& conservativeRoots) +{ + for (size_t i = 0; i < scratchBuffers.size(); i++) { + ScratchBuffer* scratchBuffer = scratchBuffers[i]; + if (scratchBuffer->activeLength()) { + void* bufferStart = scratchBuffer->dataBuffer(); + conservativeRoots.add(bufferStart, static_cast<void*>(static_cast<char*>(bufferStart) + scratchBuffer->activeLength())); + } + } +} +#endif + #if ENABLE(REGEXP_TRACING) void JSGlobalData::addRegExpToTrace(RegExp* regExp) { diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.h b/Source/JavaScriptCore/runtime/JSGlobalData.h index 177d80298..c39a01920 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalData.h +++ b/Source/JavaScriptCore/runtime/JSGlobalData.h @@ -123,7 +123,34 @@ namespace JSC { size_t m_storageOffset; size_t m_lengthOffset; }; - + +#if ENABLE(DFG_JIT) + class ConservativeRoots; + + struct ScratchBuffer { + ScratchBuffer() + : m_activeLength(0) + { + } + + static ScratchBuffer* create(size_t size) + { + ScratchBuffer* result = new (fastMalloc(ScratchBuffer::allocationSize(size))) ScratchBuffer; + + return result; + } + + static size_t allocationSize(size_t bufferSize) { return sizeof(size_t) + bufferSize; } + void setActiveLength(size_t activeLength) { m_activeLength = activeLength; } + size_t activeLength() const { return m_activeLength; }; + size_t* activeLengthPtr() { return &m_activeLength; }; + void* dataBuffer() { return m_buffer; } + + size_t m_activeLength; + void* m_buffer[0]; + }; +#endif + class JSGlobalData : public RefCounted<JSGlobalData> { public: // WebCore has a one-to-one mapping of threads to JSGlobalDatas; @@ -145,9 +172,9 @@ namespace JSC { static bool sharedInstanceExists(); JS_EXPORT_PRIVATE static JSGlobalData& sharedInstance(); - JS_EXPORT_PRIVATE static PassRefPtr<JSGlobalData> create(ThreadStackType, HeapSize = SmallHeap); - JS_EXPORT_PRIVATE static PassRefPtr<JSGlobalData> createLeaked(ThreadStackType, HeapSize = SmallHeap); - static PassRefPtr<JSGlobalData> createContextGroup(ThreadStackType, HeapSize = SmallHeap); + JS_EXPORT_PRIVATE static PassRefPtr<JSGlobalData> create(ThreadStackType, HeapType = SmallHeap); + JS_EXPORT_PRIVATE static PassRefPtr<JSGlobalData> createLeaked(ThreadStackType, HeapType = SmallHeap); + static PassRefPtr<JSGlobalData> createContextGroup(ThreadStackType, HeapType = SmallHeap); JS_EXPORT_PRIVATE ~JSGlobalData(); void makeUsableFromMultipleThreads() { heap.machineThreads().makeUsableFromMultipleThreads(); } @@ -171,6 +198,7 @@ namespace JSC { const HashTable* numberPrototypeTable; const HashTable* objectConstructorTable; const HashTable* objectPrototypeTable; + const HashTable* privateNamePrototypeTable; const HashTable* regExpTable; const HashTable* regExpConstructorTable; const HashTable* regExpPrototypeTable; @@ -278,10 +306,10 @@ namespace JSC { #if ENABLE(DFG_JIT) uint32_t osrExitIndex; void* osrExitJumpDestination; - Vector<void*> scratchBuffers; + Vector<ScratchBuffer*> scratchBuffers; size_t sizeOfLastScratchBuffer; - void* scratchBufferForSize(size_t size) + ScratchBuffer* scratchBufferForSize(size_t size) { if (!size) return 0; @@ -292,12 +320,16 @@ namespace JSC { // total memory usage is somewhere around // max(scratch buffer size) * 4. sizeOfLastScratchBuffer = size * 2; - - scratchBuffers.append(fastMalloc(sizeOfLastScratchBuffer)); + + scratchBuffers.append(ScratchBuffer::create(sizeOfLastScratchBuffer)); } - - return scratchBuffers.last(); + + ScratchBuffer* result = scratchBuffers.last(); + result->setActiveLength(0); + return result; } + + void gatherConservativeRoots(ConservativeRoots&); #endif HashMap<OpaqueJSClass*, OwnPtr<OpaqueJSClassContextData> > opaqueJSClassData; @@ -373,7 +405,7 @@ namespace JSC { private: friend class LLIntOffsetsExtractor; - JSGlobalData(GlobalDataType, ThreadStackType, HeapSize); + JSGlobalData(GlobalDataType, ThreadStackType, HeapType); static JSGlobalData*& sharedInstanceInternal(); void createNativeThunk(); #if ENABLE(ASSEMBLER) && (ENABLE(CLASSIC_INTERPRETER) || ENABLE(LLINT)) diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp index da55c0191..2a4231537 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp +++ b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp @@ -56,6 +56,9 @@ #include "Interpreter.h" #include "Lookup.h" #include "MathObject.h" +#include "NameConstructor.h" +#include "NameInstance.h" +#include "NamePrototype.h" #include "NativeErrorConstructor.h" #include "NativeErrorPrototype.h" #include "NumberConstructor.h" @@ -78,7 +81,7 @@ namespace JSC { const ClassInfo JSGlobalObject::s_info = { "GlobalObject", &JSVariableObject::s_info, 0, ExecState::globalObjectTable, CREATE_METHOD_TABLE(JSGlobalObject) }; -const GlobalObjectMethodTable JSGlobalObject::s_globalObjectMethodTable = { &allowsAccessFrom, &supportsProfiling, &supportsRichSourceInfo, &shouldInterruptScript }; +const GlobalObjectMethodTable JSGlobalObject::s_globalObjectMethodTable = { &allowsAccessFrom, &supportsProfiling, &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptExperimentsEnabled }; /* Source for JSGlobalObject.lut.h @begin globalObjectTable @@ -306,6 +309,15 @@ void JSGlobalObject::reset(JSValue prototype) }; addStaticGlobals(staticGlobals, WTF_ARRAY_LENGTH(staticGlobals)); + if (m_experimentsEnabled) { + NamePrototype* privateNamePrototype = NamePrototype::create(exec, NamePrototype::createStructure(exec->globalData(), this, m_objectPrototype.get())); + m_privateNameStructure.set(exec->globalData(), this, NameInstance::createStructure(exec->globalData(), this, privateNamePrototype)); + + JSCell* privateNameConstructor = NameConstructor::create(exec, this, NameConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), privateNamePrototype); + privateNamePrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, privateNameConstructor, DontEnum); + putDirectWithoutTransition(exec->globalData(), Identifier(exec, "Name"), privateNameConstructor, DontEnum); + } + resetPrototype(exec->globalData(), prototype); } diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.h b/Source/JavaScriptCore/runtime/JSGlobalObject.h index a330f5f1c..59b49755b 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalObject.h +++ b/Source/JavaScriptCore/runtime/JSGlobalObject.h @@ -68,6 +68,9 @@ namespace JSC { typedef bool (*ShouldInterruptScriptFunctionPtr)(const JSGlobalObject*); ShouldInterruptScriptFunctionPtr shouldInterruptScript; + + typedef bool (*JavaScriptExperimentsEnabledFunctionPtr)(const JSGlobalObject*); + JavaScriptExperimentsEnabledFunctionPtr javaScriptExperimentsEnabled; }; class JSGlobalObject : public JSVariableObject { @@ -130,6 +133,7 @@ namespace JSC { WriteBarrier<Structure> m_namedFunctionStructure; size_t m_functionNameOffset; WriteBarrier<Structure> m_numberObjectStructure; + WriteBarrier<Structure> m_privateNameStructure; WriteBarrier<Structure> m_regExpMatchesArrayStructure; WriteBarrier<Structure> m_regExpStructure; WriteBarrier<Structure> m_stringObjectStructure; @@ -144,6 +148,7 @@ namespace JSC { SymbolTable m_symbolTable; bool m_evalEnabled; + bool m_experimentsEnabled; static JS_EXPORTDATA const GlobalObjectMethodTable s_globalObjectMethodTable; const GlobalObjectMethodTable* m_globalObjectMethodTable; @@ -183,6 +188,7 @@ namespace JSC { { Base::finishCreation(globalData); structure()->setGlobalObject(globalData, this); + m_experimentsEnabled = m_globalObjectMethodTable->javaScriptExperimentsEnabled(this); init(this); } @@ -190,6 +196,7 @@ namespace JSC { { Base::finishCreation(globalData); structure()->setGlobalObject(globalData, this); + m_experimentsEnabled = m_globalObjectMethodTable->javaScriptExperimentsEnabled(this); init(thisValue); } @@ -263,6 +270,7 @@ namespace JSC { Structure* namedFunctionStructure() const { return m_namedFunctionStructure.get(); } size_t functionNameOffset() const { return m_functionNameOffset; } Structure* numberObjectStructure() const { return m_numberObjectStructure.get(); } + Structure* privateNameStructure() const { return m_privateNameStructure.get(); } Structure* internalFunctionStructure() const { return m_internalFunctionStructure.get(); } Structure* regExpMatchesArrayStructure() const { return m_regExpMatchesArrayStructure.get(); } Structure* regExpStructure() const { return m_regExpStructure.get(); } @@ -290,6 +298,7 @@ namespace JSC { JS_EXPORT_PRIVATE ExecState* globalExec(); static bool shouldInterruptScript(const JSGlobalObject*) { return true; } + static bool javaScriptExperimentsEnabled(const JSGlobalObject*) { return false; } bool isDynamicScope(bool& requiresDynamicChecks) const; @@ -376,7 +385,7 @@ namespace JSC { inline bool JSGlobalObject::symbolTableHasProperty(PropertyName propertyName) { - SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl()); + SymbolTableEntry entry = symbolTable().inlineGet(propertyName.publicName()); return !entry.isNull(); } diff --git a/Source/JavaScriptCore/runtime/JSObject.cpp b/Source/JavaScriptCore/runtime/JSObject.cpp index baba28b46..8d9e4a96b 100644 --- a/Source/JavaScriptCore/runtime/JSObject.cpp +++ b/Source/JavaScriptCore/runtime/JSObject.cpp @@ -422,11 +422,6 @@ void JSObject::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNa getClassPropertyNames(exec, object->classInfo(), propertyNames, mode); } -bool JSObject::toBoolean(ExecState*) const -{ - return true; -} - double JSObject::toNumber(ExecState* exec) const { JSValue primitive = toPrimitive(exec, PreferNumber); diff --git a/Source/JavaScriptCore/runtime/JSObject.h b/Source/JavaScriptCore/runtime/JSObject.h index 0a4f1c745..67aa1516c 100644 --- a/Source/JavaScriptCore/runtime/JSObject.h +++ b/Source/JavaScriptCore/runtime/JSObject.h @@ -138,7 +138,6 @@ namespace JSC { JS_EXPORT_PRIVATE static void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); JSValue toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const; - JS_EXPORT_PRIVATE bool toBoolean(ExecState*) const; bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const; JS_EXPORT_PRIVATE double toNumber(ExecState*) const; JS_EXPORT_PRIVATE JSString* toString(ExecState*) const; diff --git a/Source/JavaScriptCore/runtime/JSString.cpp b/Source/JavaScriptCore/runtime/JSString.cpp index 7faa393c3..ad6bd3812 100644 --- a/Source/JavaScriptCore/runtime/JSString.cpp +++ b/Source/JavaScriptCore/runtime/JSString.cpp @@ -230,7 +230,7 @@ bool JSString::getPrimitiveNumber(ExecState* exec, double& number, JSValue& resu return false; } -bool JSString::toBoolean(ExecState*) const +bool JSString::toBoolean() const { return m_length; } diff --git a/Source/JavaScriptCore/runtime/JSString.h b/Source/JavaScriptCore/runtime/JSString.h index 4ba9b79ad..5079e8583 100644 --- a/Source/JavaScriptCore/runtime/JSString.h +++ b/Source/JavaScriptCore/runtime/JSString.h @@ -134,7 +134,7 @@ namespace JSC { unsigned length() { return m_length; } JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const; - JS_EXPORT_PRIVATE bool toBoolean(ExecState*) const; + JS_EXPORT_PRIVATE bool toBoolean() const; bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const; JSObject* toObject(ExecState*, JSGlobalObject*) const; double toNumber(ExecState*) const; @@ -468,23 +468,23 @@ namespace JSC { inline bool isJSString(JSValue v) { return v.isCell() && v.asCell()->classInfo() == &JSString::s_info; } - inline bool JSCell::toBoolean(ExecState* exec) const + inline bool JSCell::toBoolean() const { if (isString()) - return static_cast<const JSString*>(this)->toBoolean(exec); + return static_cast<const JSString*>(this)->toBoolean(); return !structure()->typeInfo().masqueradesAsUndefined(); } // --- JSValue inlines ---------------------------- - inline bool JSValue::toBoolean(ExecState* exec) const + inline bool JSValue::toBoolean() const { if (isInt32()) return asInt32(); if (isDouble()) return asDouble() > 0.0 || asDouble() < 0.0; // false for NaN if (isCell()) - return asCell()->toBoolean(exec); + return asCell()->toBoolean(); return isTrue(); // false, null, and undefined all convert to false. } diff --git a/Source/JavaScriptCore/runtime/JSType.h b/Source/JavaScriptCore/runtime/JSType.h index 880240e60..c9603437b 100644 --- a/Source/JavaScriptCore/runtime/JSType.h +++ b/Source/JavaScriptCore/runtime/JSType.h @@ -45,6 +45,7 @@ enum JSType { ObjectType, FinalObjectType, JSFunctionType, + NameInstanceType, NumberObjectType, ErrorInstanceType, GlobalThisType, diff --git a/Source/JavaScriptCore/runtime/JSTypeInfo.h b/Source/JavaScriptCore/runtime/JSTypeInfo.h index 83a3594db..8c62fa166 100644 --- a/Source/JavaScriptCore/runtime/JSTypeInfo.h +++ b/Source/JavaScriptCore/runtime/JSTypeInfo.h @@ -67,6 +67,7 @@ namespace JSC { bool isObject() const { return type() >= ObjectType; } bool isFinalObject() const { return type() == FinalObjectType; } bool isNumberObject() const { return type() == NumberObjectType; } + bool isName() const { return type() == NameInstanceType; } bool masqueradesAsUndefined() const { return isSetOnFlags1(MasqueradesAsUndefined); } bool implementsHasInstance() const { return isSetOnFlags1(ImplementsHasInstance); } diff --git a/Source/JavaScriptCore/runtime/JSValue.cpp b/Source/JavaScriptCore/runtime/JSValue.cpp index 628642f71..e10867176 100644 --- a/Source/JavaScriptCore/runtime/JSValue.cpp +++ b/Source/JavaScriptCore/runtime/JSValue.cpp @@ -172,7 +172,7 @@ void JSValue::putToPrimitive(ExecState* exec, PropertyName propertyName, JSValue return; } -char* JSValue::description() +char* JSValue::description() const { static const size_t size = 128; static char description[size]; diff --git a/Source/JavaScriptCore/runtime/JSValue.h b/Source/JavaScriptCore/runtime/JSValue.h index 40cf69979..27046097c 100644 --- a/Source/JavaScriptCore/runtime/JSValue.h +++ b/Source/JavaScriptCore/runtime/JSValue.h @@ -197,7 +197,7 @@ namespace JSC { JSValue toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const; bool getPrimitiveNumber(ExecState*, double& number, JSValue&); - bool toBoolean(ExecState*) const; + bool toBoolean() const; // toNumber conversion is expected to be side effect free if an exception has // been set in the ExecState already. @@ -240,7 +240,7 @@ namespace JSC { JSCell* asCell() const; JS_EXPORT_PRIVATE bool isValidCallee(); - char* description(); + char* description() const; JS_EXPORT_PRIVATE JSObject* synthesizePrototype(ExecState*) const; diff --git a/Source/JavaScriptCore/runtime/JSVariableObject.cpp b/Source/JavaScriptCore/runtime/JSVariableObject.cpp index 3a4df7464..eb9dfd4be 100644 --- a/Source/JavaScriptCore/runtime/JSVariableObject.cpp +++ b/Source/JavaScriptCore/runtime/JSVariableObject.cpp @@ -45,7 +45,7 @@ void JSVariableObject::destroy(JSCell* cell) bool JSVariableObject::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName) { JSVariableObject* thisObject = jsCast<JSVariableObject*>(cell); - if (thisObject->symbolTable().contains(propertyName.impl())) + if (thisObject->symbolTable().contains(propertyName.publicName())) return false; return JSObject::deleteProperty(thisObject, exec, propertyName); @@ -65,7 +65,7 @@ void JSVariableObject::getOwnPropertyNames(JSObject* object, ExecState* exec, Pr bool JSVariableObject::symbolTableGet(PropertyName propertyName, PropertyDescriptor& descriptor) { - SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl()); + SymbolTableEntry entry = symbolTable().inlineGet(propertyName.publicName()); if (!entry.isNull()) { descriptor.setDescriptor(registerAt(entry.getIndex()).get(), entry.getAttributes() | DontDelete); return true; diff --git a/Source/JavaScriptCore/runtime/JSVariableObject.h b/Source/JavaScriptCore/runtime/JSVariableObject.h index 8b7587b5c..ea2798457 100644 --- a/Source/JavaScriptCore/runtime/JSVariableObject.h +++ b/Source/JavaScriptCore/runtime/JSVariableObject.h @@ -102,7 +102,7 @@ namespace JSC { inline bool JSVariableObject::symbolTableGet(PropertyName propertyName, PropertySlot& slot) { - SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl()); + SymbolTableEntry entry = symbolTable().inlineGet(propertyName.publicName()); if (!entry.isNull()) { slot.setValue(registerAt(entry.getIndex()).get()); return true; @@ -112,7 +112,7 @@ namespace JSC { inline bool JSVariableObject::symbolTableGet(PropertyName propertyName, PropertySlot& slot, bool& slotIsWriteable) { - SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl()); + SymbolTableEntry entry = symbolTable().inlineGet(propertyName.publicName()); if (!entry.isNull()) { slot.setValue(registerAt(entry.getIndex()).get()); slotIsWriteable = !entry.isReadOnly(); @@ -126,7 +126,7 @@ namespace JSC { JSGlobalData& globalData = exec->globalData(); ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); - SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl()); + SymbolTableEntry entry = symbolTable().inlineGet(propertyName.publicName()); if (entry.isNull()) return false; if (entry.isReadOnly()) { @@ -142,7 +142,7 @@ namespace JSC { { ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); - SymbolTable::iterator iter = symbolTable().find(propertyName.impl()); + SymbolTable::iterator iter = symbolTable().find(propertyName.publicName()); if (iter == symbolTable().end()) return false; SymbolTableEntry& entry = iter->second; diff --git a/Source/JavaScriptCore/runtime/Lookup.cpp b/Source/JavaScriptCore/runtime/Lookup.cpp index 30d982d2c..a6a349974 100644 --- a/Source/JavaScriptCore/runtime/Lookup.cpp +++ b/Source/JavaScriptCore/runtime/Lookup.cpp @@ -76,7 +76,10 @@ bool setUpStaticFunctionSlot(ExecState* exec, const HashEntry* entry, JSObject* if (thisObj->staticFunctionsReified()) return false; - JSFunction* function = JSFunction::create(exec, thisObj->globalObject(), entry->functionLength(), propertyName.ustring(), entry->function(), entry->intrinsic()); + StringImpl* name = propertyName.publicName(); + ASSERT(name); + + JSFunction* function = JSFunction::create(exec, thisObj->globalObject(), entry->functionLength(), name, entry->function(), entry->intrinsic()); thisObj->putDirect(exec->globalData(), propertyName, function, entry->attributes()); location = thisObj->getDirectLocation(exec->globalData(), propertyName); } diff --git a/Source/JavaScriptCore/runtime/Lookup.h b/Source/JavaScriptCore/runtime/Lookup.h index d6806ae0c..a75b521cd 100644 --- a/Source/JavaScriptCore/runtime/Lookup.h +++ b/Source/JavaScriptCore/runtime/Lookup.h @@ -199,17 +199,21 @@ namespace JSC { } private: - ALWAYS_INLINE const HashEntry* entry(PropertyName identifier) const + ALWAYS_INLINE const HashEntry* entry(PropertyName propertyName) const { + StringImpl* impl = propertyName.publicName(); + if (!impl) + return 0; + ASSERT(table); - const HashEntry* entry = &table[identifier.impl()->existingHash() & compactHashSizeMask]; + const HashEntry* entry = &table[impl->existingHash() & compactHashSizeMask]; if (!entry->key()) return 0; do { - if (entry->key() == identifier.impl()) + if (entry->key() == impl) return entry; entry = entry->next(); } while (entry); diff --git a/Source/JavaScriptCore/runtime/NameConstructor.cpp b/Source/JavaScriptCore/runtime/NameConstructor.cpp new file mode 100644 index 000000000..63f1f647a --- /dev/null +++ b/Source/JavaScriptCore/runtime/NameConstructor.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "NameConstructor.h" + +#include "JSGlobalObject.h" +#include "NamePrototype.h" + +namespace JSC { + +ASSERT_CLASS_FITS_IN_CELL(NameConstructor); +ASSERT_HAS_TRIVIAL_DESTRUCTOR(NameConstructor); + +const ClassInfo NameConstructor::s_info = { "Function", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(NameConstructor) }; + +NameConstructor::NameConstructor(JSGlobalObject* globalObject, Structure* structure) + : InternalFunction(globalObject, structure) +{ +} + +void NameConstructor::finishCreation(ExecState* exec, NamePrototype* prototype) +{ + Base::finishCreation(exec->globalData(), prototype->classInfo()->className); + putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, prototype, DontEnum | DontDelete | ReadOnly); + putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(1), DontDelete | ReadOnly | DontEnum); +} + +static EncodedJSValue JSC_HOST_CALL constructPrivateName(ExecState* exec) +{ + JSValue publicName = exec->argumentCount() ? exec->argument(0) : jsUndefined(); + return JSValue::encode(NameInstance::create(exec->globalData(), exec->lexicalGlobalObject()->privateNameStructure(), publicName.toString(exec))); +} + +ConstructType NameConstructor::getConstructData(JSCell*, ConstructData& constructData) +{ + constructData.native.function = constructPrivateName; + return ConstructTypeHost; +} + +CallType NameConstructor::getCallData(JSCell*, CallData& callData) +{ + callData.native.function = constructPrivateName; + return CallTypeHost; +} + +} // namespace JSC diff --git a/Source/JavaScriptCore/runtime/NameConstructor.h b/Source/JavaScriptCore/runtime/NameConstructor.h new file mode 100644 index 000000000..16c5eef68 --- /dev/null +++ b/Source/JavaScriptCore/runtime/NameConstructor.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef NameConstructor_h +#define NameConstructor_h + +#include "InternalFunction.h" +#include "NameInstance.h" + +namespace JSC { + +class NamePrototype; + +class NameConstructor : public InternalFunction { +public: + typedef InternalFunction Base; + + static NameConstructor* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, NamePrototype* prototype) + { + NameConstructor* constructor = new (NotNull, allocateCell<NameConstructor>(*exec->heap())) NameConstructor(globalObject, structure); + constructor->finishCreation(exec, prototype); + return constructor; + } + + static const ClassInfo s_info; + + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + { + return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); + } + +protected: + void finishCreation(ExecState*, NamePrototype*); + +private: + NameConstructor(JSGlobalObject*, Structure*); + static ConstructType getConstructData(JSCell*, ConstructData&); + static CallType getCallData(JSCell*, CallData&); +}; + +} // namespace JSC + +#endif // NameConstructor_h diff --git a/Source/JavaScriptCore/runtime/NameInstance.cpp b/Source/JavaScriptCore/runtime/NameInstance.cpp new file mode 100644 index 000000000..aae290cb2 --- /dev/null +++ b/Source/JavaScriptCore/runtime/NameInstance.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "NameInstance.h" + +namespace JSC { + +const ClassInfo NameInstance::s_info = { "Name", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(NameInstance) }; + +NameInstance::NameInstance(JSGlobalData& globalData, Structure* structure, JSString* nameString) + : Base(globalData, structure) +{ + m_nameString.set(globalData, this, nameString); +} + +void NameInstance::destroy(JSCell* cell) +{ + jsCast<NameInstance*>(cell)->NameInstance::~NameInstance(); +} + +} // namespace JSC diff --git a/Source/JavaScriptCore/runtime/NameInstance.h b/Source/JavaScriptCore/runtime/NameInstance.h new file mode 100644 index 000000000..c5931e8ef --- /dev/null +++ b/Source/JavaScriptCore/runtime/NameInstance.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef NameInstance_h +#define NameInstance_h + +#include "JSObject.h" +#include "PrivateName.h" + +namespace JSC { + +class NameInstance : public JSNonFinalObject { +public: + typedef JSNonFinalObject Base; + + static const ClassInfo s_info; + + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + { + return Structure::create(globalData, globalObject, prototype, TypeInfo(NameInstanceType, StructureFlags), &s_info); + } + + static NameInstance* create(JSGlobalData& globalData, Structure* structure, JSString* nameString) + { + NameInstance* name = new (NotNull, allocateCell<NameInstance>(globalData.heap)) NameInstance(globalData, structure, nameString); + name->finishCreation(globalData); + return name; + } + + const PrivateName& privateName() { return m_privateName; } + JSString* nameString() { return m_nameString.get(); } + +protected: + static void destroy(JSCell*); + + NameInstance(JSGlobalData&, Structure*, JSString*); + + void finishCreation(JSGlobalData& globalData) + { + Base::finishCreation(globalData); + ASSERT(inherits(&s_info)); + } + + PrivateName m_privateName; + WriteBarrier<JSString> m_nameString; +}; + +inline bool isName(JSValue v) +{ + return v.isCell() && v.asCell()->structure()->typeInfo().isName(); +} + +} // namespace JSC + +#endif // NameInstance_h diff --git a/Source/JavaScriptCore/runtime/NamePrototype.cpp b/Source/JavaScriptCore/runtime/NamePrototype.cpp new file mode 100644 index 000000000..3e52856b6 --- /dev/null +++ b/Source/JavaScriptCore/runtime/NamePrototype.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "NamePrototype.h" + +#include "Error.h" + +namespace JSC { + +ASSERT_CLASS_FITS_IN_CELL(NamePrototype); + +static EncodedJSValue JSC_HOST_CALL privateNameProtoFuncToString(ExecState*); + +} + +#include "NamePrototype.lut.h" + +namespace JSC { + +const ClassInfo NamePrototype::s_info = { "Name", &Base::s_info, 0, ExecState::privateNamePrototypeTable, CREATE_METHOD_TABLE(NamePrototype) }; + +/* Source for NamePrototype.lut.h +@begin privateNamePrototypeTable + toString privateNameProtoFuncToString DontEnum|Function 0 +@end +*/ + +ASSERT_CLASS_FITS_IN_CELL(NamePrototype); + +NamePrototype::NamePrototype(ExecState* exec, Structure* structure) + : Base(exec->globalData(), structure, jsEmptyString(exec)) +{ +} + +void NamePrototype::finishCreation(ExecState* exec) +{ + Base::finishCreation(exec->globalData()); + ASSERT(inherits(&s_info)); +} + +bool NamePrototype::getOwnPropertySlot(JSCell* cell, ExecState* exec, PropertyName propertyName, PropertySlot &slot) +{ + return getStaticFunctionSlot<Base>(exec, ExecState::privateNamePrototypeTable(exec), jsCast<NamePrototype*>(cell), propertyName, slot); +} + +bool NamePrototype::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor) +{ + return getStaticFunctionDescriptor<Base>(exec, ExecState::privateNamePrototypeTable(exec), jsCast<NamePrototype*>(object), propertyName, descriptor); +} + +// ------------------------------ Functions --------------------------- + +EncodedJSValue JSC_HOST_CALL privateNameProtoFuncToString(ExecState* exec) +{ + JSValue thisValue = exec->hostThisValue(); + if (!thisValue.isObject()) + return throwVMTypeError(exec); + + JSObject* thisObject = asObject(thisValue); + if (!thisObject->inherits(&NameInstance::s_info)) + return throwVMTypeError(exec); + + return JSValue::encode(jsCast<NameInstance*>(thisObject)->nameString()); +} + +} // namespace JSC diff --git a/Source/JavaScriptCore/runtime/NamePrototype.h b/Source/JavaScriptCore/runtime/NamePrototype.h new file mode 100644 index 000000000..5d86decfd --- /dev/null +++ b/Source/JavaScriptCore/runtime/NamePrototype.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef NamePrototype_h +#define NamePrototype_h + +#include "NameInstance.h" + +namespace JSC { + +class NamePrototype : public NameInstance { +public: + typedef NameInstance Base; + + static NamePrototype* create(ExecState* exec, Structure* structure) + { + NamePrototype* prototype = new (NotNull, allocateCell<NamePrototype>(*exec->heap())) NamePrototype(exec, structure); + prototype->finishCreation(exec); + return prototype; + } + + static const ClassInfo s_info; + + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + { + return Structure::create(globalData, globalObject, prototype, TypeInfo(NameInstanceType, StructureFlags), &s_info); + } + +protected: + NamePrototype(ExecState*, Structure*); + void finishCreation(ExecState*); + + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | NameInstance::StructureFlags; + +private: + static bool getOwnPropertySlot(JSCell*, ExecState*, PropertyName, PropertySlot&); + static bool getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, PropertyDescriptor&); +}; + +} // namespace JSC + +#endif // NamePrototype_h diff --git a/Source/JavaScriptCore/runtime/ObjectConstructor.cpp b/Source/JavaScriptCore/runtime/ObjectConstructor.cpp index 5a6fcddf0..7b6a5f669 100644 --- a/Source/JavaScriptCore/runtime/ObjectConstructor.cpp +++ b/Source/JavaScriptCore/runtime/ObjectConstructor.cpp @@ -214,14 +214,14 @@ static bool toPropertyDescriptor(ExecState* exec, JSValue in, PropertyDescriptor PropertySlot enumerableSlot(description); if (description->getPropertySlot(exec, exec->propertyNames().enumerable, enumerableSlot)) { - desc.setEnumerable(enumerableSlot.getValue(exec, exec->propertyNames().enumerable).toBoolean(exec)); + desc.setEnumerable(enumerableSlot.getValue(exec, exec->propertyNames().enumerable).toBoolean()); if (exec->hadException()) return false; } PropertySlot configurableSlot(description); if (description->getPropertySlot(exec, exec->propertyNames().configurable, configurableSlot)) { - desc.setConfigurable(configurableSlot.getValue(exec, exec->propertyNames().configurable).toBoolean(exec)); + desc.setConfigurable(configurableSlot.getValue(exec, exec->propertyNames().configurable).toBoolean()); if (exec->hadException()) return false; } @@ -236,7 +236,7 @@ static bool toPropertyDescriptor(ExecState* exec, JSValue in, PropertyDescriptor PropertySlot writableSlot(description); if (description->getPropertySlot(exec, exec->propertyNames().writable, writableSlot)) { - desc.setWritable(writableSlot.getValue(exec, exec->propertyNames().writable).toBoolean(exec)); + desc.setWritable(writableSlot.getValue(exec, exec->propertyNames().writable).toBoolean()); if (exec->hadException()) return false; } diff --git a/Source/JavaScriptCore/runtime/PrivateName.h b/Source/JavaScriptCore/runtime/PrivateName.h new file mode 100644 index 000000000..91254fc26 --- /dev/null +++ b/Source/JavaScriptCore/runtime/PrivateName.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PrivateName_h +#define PrivateName_h + +#include <wtf/text/StringImpl.h> + +namespace JSC { + +class PrivateName { +public: + PrivateName() + : m_impl(StringImpl::createEmptyUnique()) + { + } + + StringImpl* uid() const { return m_impl.get(); } + +private: + RefPtr<StringImpl> m_impl; +}; + +} + +#endif diff --git a/Source/JavaScriptCore/runtime/PropertyMapHashTable.h b/Source/JavaScriptCore/runtime/PropertyMapHashTable.h index 7c8cabb7b..c47f3476a 100644 --- a/Source/JavaScriptCore/runtime/PropertyMapHashTable.h +++ b/Source/JavaScriptCore/runtime/PropertyMapHashTable.h @@ -325,7 +325,7 @@ inline PropertyTable::const_iterator PropertyTable::end() const inline PropertyTable::find_iterator PropertyTable::find(const KeyType& key) { ASSERT(key); - ASSERT(key->isIdentifier()); + ASSERT(key->isIdentifier() || key->isEmptyUnique()); unsigned hash = key->existingHash(); unsigned step = 0; @@ -369,7 +369,8 @@ inline PropertyTable::find_iterator PropertyTable::findWithString(const KeyType& unsigned entryIndex = m_index[hash & m_indexMask]; if (entryIndex == EmptyEntryIndex) return std::make_pair((ValueType*)0, hash & m_indexMask); - if (equal(key, table()[entryIndex - 1].key)) + const KeyType& keyInMap = table()[entryIndex - 1].key; + if (equal(key, keyInMap) && keyInMap->isIdentifier()) return std::make_pair(&table()[entryIndex - 1], hash & m_indexMask); #if DUMP_PROPERTYMAP_STATS diff --git a/Source/JavaScriptCore/runtime/PropertyName.h b/Source/JavaScriptCore/runtime/PropertyName.h index d2258b471..7253756fa 100644 --- a/Source/JavaScriptCore/runtime/PropertyName.h +++ b/Source/JavaScriptCore/runtime/PropertyName.h @@ -27,6 +27,7 @@ #define PropertyName_h #include "Identifier.h" +#include "PrivateName.h" namespace JSC { @@ -80,15 +81,33 @@ public: PropertyName(const Identifier& propertyName) : m_impl(propertyName.impl()) { + ASSERT(!m_impl || m_impl->isIdentifier()); } - StringImpl* impl() const { return m_impl; } - UString ustring() const { return m_impl; } + PropertyName(const PrivateName& propertyName) + : m_impl(propertyName.uid()) + { + ASSERT(m_impl && m_impl->isEmptyUnique()); + } + + StringImpl* uid() const + { + ASSERT(!m_impl || (m_impl->isIdentifier() == !m_impl->isEmptyUnique())); + return m_impl; + } + + StringImpl* publicName() const + { + ASSERT(!m_impl || (m_impl->isIdentifier() == !m_impl->isEmptyUnique())); + return m_impl->isIdentifier() ? m_impl : 0; + } static const uint32_t NotAnIndex = UINT_MAX; + uint32_t asIndex() { - return toUInt32FromStringImpl(m_impl); + ASSERT(!m_impl || (m_impl->isIdentifier() == !m_impl->isEmptyUnique())); + return m_impl ? toUInt32FromStringImpl(m_impl) : NotAnIndex; } private: @@ -97,32 +116,32 @@ private: inline bool operator==(PropertyName a, const Identifier& b) { - return a.impl() == b.impl(); + return a.uid() == b.impl(); } inline bool operator==(const Identifier& a, PropertyName b) { - return a.impl() == b.impl(); + return a.impl() == b.uid(); } inline bool operator==(PropertyName a, PropertyName b) { - return a.impl() == b.impl(); + return a.uid() == b.uid(); } inline bool operator!=(PropertyName a, const Identifier& b) { - return a.impl() != b.impl(); + return a.uid() != b.impl(); } inline bool operator!=(const Identifier& a, PropertyName b) { - return a.impl() != b.impl(); + return a.impl() != b.uid(); } inline bool operator!=(PropertyName a, PropertyName b) { - return a.impl() != b.impl(); + return a.uid() != b.uid(); } } diff --git a/Source/JavaScriptCore/runtime/RegExpCache.cpp b/Source/JavaScriptCore/runtime/RegExpCache.cpp index 36ea326e6..53a13a4b5 100644 --- a/Source/JavaScriptCore/runtime/RegExpCache.cpp +++ b/Source/JavaScriptCore/runtime/RegExpCache.cpp @@ -36,17 +36,15 @@ namespace JSC { RegExp* RegExpCache::lookupOrCreate(const UString& patternString, RegExpFlags flags) { RegExpKey key(flags, patternString); - RegExpCacheMap::iterator result = m_weakCache.find(key); - if (result != m_weakCache.end()) - return result->second.get(); + if (RegExp* regExp = m_weakCache.get(key)) + return regExp; + RegExp* regExp = RegExp::createWithoutCaching(*m_globalData, patternString, flags); #if ENABLE(REGEXP_TRACING) m_globalData->addRegExpToTrace(regExp); #endif - // We need to do a second lookup to add the RegExp as - // allocating it may have caused a gc cycle, which in - // turn may have removed items from the cache. - m_weakCache.add(key, PassWeak<RegExp>(regExp, this)); + + weakAdd(m_weakCache, key, PassWeak<RegExp>(regExp, this)); return regExp; } @@ -59,7 +57,7 @@ RegExpCache::RegExpCache(JSGlobalData* globalData) void RegExpCache::finalize(Handle<Unknown> handle, void*) { RegExp* regExp = static_cast<RegExp*>(handle.get().asCell()); - m_weakCache.remove(regExp->key()); + weakRemove(m_weakCache, regExp->key(), regExp); regExp->invalidateCode(); } @@ -79,9 +77,14 @@ void RegExpCache::invalidateCode() for (int i = 0; i < maxStrongCacheableEntries; i++) m_strongCache[i].clear(); m_nextEntryInStrongCache = 0; + RegExpCacheMap::iterator end = m_weakCache.end(); - for (RegExpCacheMap::iterator ptr = m_weakCache.begin(); ptr != end; ++ptr) - ptr->second->invalidateCode(); + for (RegExpCacheMap::iterator it = m_weakCache.begin(); it != end; ++it) { + RegExp* regExp = it->second.get(); + if (!regExp) // Skip zombies. + continue; + regExp->invalidateCode(); + } } } diff --git a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp index 879511ac2..2c0f0c000 100644 --- a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp +++ b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp @@ -249,9 +249,9 @@ void setRegExpConstructorInput(ExecState* exec, JSObject* baseObject, JSValue va asRegExpConstructor(baseObject)->setInput(exec, value.toString(exec)); } -void setRegExpConstructorMultiline(ExecState* exec, JSObject* baseObject, JSValue value) +void setRegExpConstructorMultiline(ExecState*, JSObject* baseObject, JSValue value) { - asRegExpConstructor(baseObject)->setMultiline(value.toBoolean(exec)); + asRegExpConstructor(baseObject)->setMultiline(value.toBoolean()); } // ECMA 15.10.4 diff --git a/Source/JavaScriptCore/runtime/RegExpKey.h b/Source/JavaScriptCore/runtime/RegExpKey.h index b4847f971..cdaff27f5 100644 --- a/Source/JavaScriptCore/runtime/RegExpKey.h +++ b/Source/JavaScriptCore/runtime/RegExpKey.h @@ -103,6 +103,7 @@ template<> struct DefaultHash<JSC::RegExpKey> { }; template<> struct HashTraits<JSC::RegExpKey> : GenericHashTraits<JSC::RegExpKey> { + static const bool emptyValueIsZero = true; static void constructDeletedValue(JSC::RegExpKey& slot) { slot.flagsValue = JSC::DeletedValueFlags; } static bool isDeletedValue(const JSC::RegExpKey& value) { return value.flagsValue == JSC::DeletedValueFlags; } }; diff --git a/Source/JavaScriptCore/runtime/RegExpPrototype.cpp b/Source/JavaScriptCore/runtime/RegExpPrototype.cpp index 24c7c8027..6080a1c99 100644 --- a/Source/JavaScriptCore/runtime/RegExpPrototype.cpp +++ b/Source/JavaScriptCore/runtime/RegExpPrototype.cpp @@ -147,11 +147,11 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState* exec) char postfix[5] = { '/', 0, 0, 0, 0 }; int index = 1; - if (thisObject->get(exec, exec->propertyNames().global).toBoolean(exec)) + if (thisObject->get(exec, exec->propertyNames().global).toBoolean()) postfix[index++] = 'g'; - if (thisObject->get(exec, exec->propertyNames().ignoreCase).toBoolean(exec)) + if (thisObject->get(exec, exec->propertyNames().ignoreCase).toBoolean()) postfix[index++] = 'i'; - if (thisObject->get(exec, exec->propertyNames().multiline).toBoolean(exec)) + if (thisObject->get(exec, exec->propertyNames().multiline).toBoolean()) postfix[index] = 'm'; UString source = thisObject->get(exec, exec->propertyNames().source).toString(exec)->value(exec); // If source is empty, use "/(?:)/" to avoid colliding with comment syntax diff --git a/Source/JavaScriptCore/runtime/Structure.cpp b/Source/JavaScriptCore/runtime/Structure.cpp index 693f3f317..b22deb0fa 100644 --- a/Source/JavaScriptCore/runtime/Structure.cpp +++ b/Source/JavaScriptCore/runtime/Structure.cpp @@ -67,7 +67,7 @@ bool StructureTransitionTable::contains(StringImpl* rep, unsigned attributes) co Structure* transition = singleTransition(); return transition && transition->m_nameInPrevious == rep && transition->m_attributesInPrevious == attributes; } - return map()->contains(make_pair(rep, attributes)); + return map()->get(make_pair(rep, attributes)); } inline Structure* StructureTransitionTable::get(StringImpl* rep, unsigned attributes) const @@ -101,13 +101,7 @@ inline void StructureTransitionTable::add(JSGlobalData& globalData, Structure* s // Newer versions of the STL have an std::make_pair function that takes rvalue references. // When either of the parameters are bitfields, the C++ compiler will try to bind them as lvalues, which is invalid. To work around this, use unary "+" to make the parameter an rvalue. // See https://bugs.webkit.org/show_bug.cgi?id=59261 for more details - TransitionMap::AddResult result = map()->add(globalData, make_pair(structure->m_nameInPrevious, +structure->m_attributesInPrevious), structure); - if (!result.isNewEntry) { - // There already is an entry! - we should only hit this when despecifying. - ASSERT(result.iterator.get().second->m_specificValueInPrevious); - ASSERT(!structure->m_specificValueInPrevious); - map()->set(globalData, result.iterator.get().first, structure); - } + map()->set(globalData, make_pair(structure->m_nameInPrevious, +structure->m_attributesInPrevious), structure); } void Structure::dumpStatistics() @@ -275,7 +269,7 @@ size_t Structure::suggestedNewPropertyStorageSize() void Structure::despecifyDictionaryFunction(JSGlobalData& globalData, PropertyName propertyName) { - StringImpl* rep = propertyName.impl(); + StringImpl* rep = propertyName.uid(); materializePropertyMapIfNecessary(globalData); @@ -292,7 +286,7 @@ Structure* Structure::addPropertyTransitionToExistingStructure(Structure* struct ASSERT(!structure->isDictionary()); ASSERT(structure->isObject()); - if (Structure* existingTransition = structure->m_transitionTable.get(propertyName.impl(), attributes)) { + if (Structure* existingTransition = structure->m_transitionTable.get(propertyName.uid(), attributes)) { JSCell* specificValueInPrevious = existingTransition->m_specificValueInPrevious.get(); if (specificValueInPrevious && specificValueInPrevious != specificValue) return 0; @@ -313,7 +307,7 @@ Structure* Structure::addPropertyTransition(JSGlobalData& globalData, Structure* // In this case we clear the value of specificFunction which will result // in us adding a non-specific transition, and any subsequent lookup in // Structure::addPropertyTransitionToExistingStructure will just use that. - if (specificValue && structure->m_transitionTable.contains(propertyName.impl(), attributes)) + if (specificValue && structure->m_transitionTable.contains(propertyName.uid(), attributes)) specificValue = 0; ASSERT(!structure->isDictionary()); @@ -336,7 +330,7 @@ Structure* Structure::addPropertyTransition(JSGlobalData& globalData, Structure* transition->m_cachedPrototypeChain.setMayBeNull(globalData, transition, structure->m_cachedPrototypeChain.get()); transition->m_previous.set(globalData, transition, structure); - transition->m_nameInPrevious = propertyName.impl(); + transition->m_nameInPrevious = propertyName.uid(); transition->m_attributesInPrevious = attributes; transition->m_specificValueInPrevious.setMayBeNull(globalData, transition, specificValue); @@ -425,7 +419,7 @@ Structure* Structure::attributeChangeTransition(JSGlobalData& globalData, Struct } ASSERT(structure->m_propertyTable); - PropertyMapEntry* entry = structure->m_propertyTable->find(propertyName.impl()).first; + PropertyMapEntry* entry = structure->m_propertyTable->find(propertyName.uid()).first; ASSERT(entry); entry->attributes = attributes; @@ -650,7 +644,7 @@ size_t Structure::get(JSGlobalData& globalData, PropertyName propertyName, unsig if (!m_propertyTable) return WTF::notFound; - PropertyMapEntry* entry = m_propertyTable->find(propertyName.impl()).first; + PropertyMapEntry* entry = m_propertyTable->find(propertyName.uid()).first; if (!entry) return WTF::notFound; @@ -665,7 +659,7 @@ bool Structure::despecifyFunction(JSGlobalData& globalData, PropertyName propert if (!m_propertyTable) return false; - PropertyMapEntry* entry = m_propertyTable->find(propertyName.impl()).first; + PropertyMapEntry* entry = m_propertyTable->find(propertyName.uid()).first; if (!entry) return false; @@ -693,7 +687,7 @@ size_t Structure::putSpecificValue(JSGlobalData& globalData, PropertyName proper if (attributes & DontEnum) m_hasNonEnumerableProperties = true; - StringImpl* rep = propertyName.impl(); + StringImpl* rep = propertyName.uid(); if (!m_propertyTable) createPropertyMap(); @@ -715,7 +709,7 @@ size_t Structure::remove(PropertyName propertyName) { checkConsistency(); - StringImpl* rep = propertyName.impl(); + StringImpl* rep = propertyName.uid(); if (!m_propertyTable) return notFound; @@ -753,7 +747,7 @@ void Structure::getPropertyNamesFromStructure(JSGlobalData& globalData, Property PropertyTable::iterator end = m_propertyTable->end(); for (PropertyTable::iterator iter = m_propertyTable->begin(); iter != end; ++iter) { ASSERT(m_hasNonEnumerableProperties || !(iter->attributes & DontEnum)); - if (!(iter->attributes & DontEnum) || (mode == IncludeDontEnumProperties)) { + if (iter->key->isIdentifier() && (!(iter->attributes & DontEnum) || mode == IncludeDontEnumProperties)) { if (knownUnique) propertyNames.addKnownUnique(iter->key); else diff --git a/Source/JavaScriptCore/runtime/Structure.h b/Source/JavaScriptCore/runtime/Structure.h index 230f59d65..74336a288 100644 --- a/Source/JavaScriptCore/runtime/Structure.h +++ b/Source/JavaScriptCore/runtime/Structure.h @@ -317,7 +317,7 @@ namespace JSC { if (!m_propertyTable) return notFound; - PropertyMapEntry* entry = m_propertyTable->find(propertyName.impl()).first; + PropertyMapEntry* entry = m_propertyTable->find(propertyName.uid()).first; return entry ? entry->offset : notFound; } diff --git a/Source/JavaScriptCore/runtime/WeakGCMap.h b/Source/JavaScriptCore/runtime/WeakGCMap.h index ec010fb4b..98483c312 100644 --- a/Source/JavaScriptCore/runtime/WeakGCMap.h +++ b/Source/JavaScriptCore/runtime/WeakGCMap.h @@ -53,80 +53,25 @@ class WeakGCMap : private WeakHandleOwner { typedef HashMap<KeyType, WeakImpl*, HashArg, KeyTraitsArg> MapType; typedef typename HandleTypes<MappedType>::ExternalType ExternalType; - typedef typename MapType::iterator map_iterator; public: - - struct iterator { - friend class WeakGCMap; - iterator(map_iterator iter) - : m_iterator(iter) - { - } - - std::pair<KeyType, ExternalType> get() const { return std::make_pair(m_iterator->first, HandleTypes<MappedType>::getFromSlot(const_cast<JSValue*>(&m_iterator->second->jsValue()))); } - - iterator& operator++() { ++m_iterator; return *this; } - - // postfix ++ intentionally omitted - - // Comparison. - bool operator==(const iterator& other) const { return m_iterator == other.m_iterator; } - bool operator!=(const iterator& other) const { return m_iterator != other.m_iterator; } - - private: - map_iterator m_iterator; - }; - - typedef WTF::HashTableAddResult<iterator> AddResult; - WeakGCMap() { } - bool isEmpty() { return m_map.isEmpty(); } void clear() { - map_iterator end = m_map.end(); - for (map_iterator ptr = m_map.begin(); ptr != end; ++ptr) + typename MapType::iterator end = m_map.end(); + for (typename MapType::iterator ptr = m_map.begin(); ptr != end; ++ptr) WeakSet::deallocate(ptr->second); m_map.clear(); } - bool contains(const KeyType& key) const - { - return m_map.contains(key); - } - - iterator find(const KeyType& key) - { - return m_map.find(key); - } - - void remove(iterator iter) - { - ASSERT(iter.m_iterator != m_map.end()); - WeakImpl* impl = iter.m_iterator->second; - ASSERT(impl); - WeakSet::deallocate(impl); - m_map.remove(iter.m_iterator); - } - ExternalType get(const KeyType& key) const { return HandleTypes<MappedType>::getFromSlot(const_cast<JSValue*>(&m_map.get(key)->jsValue())); } - AddResult add(JSGlobalData&, const KeyType& key, ExternalType value) - { - typename MapType::AddResult result = m_map.add(key, 0); - if (result.isNewEntry) - result.iterator->second = WeakSet::allocate(value, this, FinalizerCallback::finalizerContextFor(key)); - - // WeakGCMap exposes a different iterator, so we need to wrap it and create our own AddResult. - return AddResult(iterator(result.iterator), result.isNewEntry); - } - void set(JSGlobalData&, const KeyType& key, ExternalType value) { typename MapType::AddResult result = m_map.add(key, 0); @@ -135,21 +80,14 @@ public: result.iterator->second = WeakSet::allocate(value, this, FinalizerCallback::finalizerContextFor(key)); } - ExternalType take(const KeyType& key) + void remove(const KeyType& key) { WeakImpl* impl = m_map.take(key); if (!impl) - return HashTraits<ExternalType>::emptyValue(); - ExternalType result = HandleTypes<MappedType>::getFromSlot(const_cast<JSValue*>(&impl->jsValue())); + return; WeakSet::deallocate(impl); - return result; } - size_t size() { return m_map.size(); } - - iterator begin() { return iterator(m_map.begin()); } - iterator end() { return iterator(m_map.end()); } - ~WeakGCMap() { clear(); |