Title: [139145] trunk/Source/_javascript_Core
Revision
139145
Author
oli...@apple.com
Date
2013-01-08 18:37:29 -0800 (Tue, 08 Jan 2013)

Log Message

Support op_typeof in the DFG
https://bugs.webkit.org/show_bug.cgi?id=98898

Reviewed by Filip Pizlo.

Adds a TypeOf node to the DFG to support op_typeof.

To avoid adding too much GC horror, this also makes the
common strings portion of the SmallString cache strongly
referenced.

* dfg/DFGAbstractState.cpp:
(JSC::DFG::AbstractState::execute):
  We try to determine the result early here, and substitute in a constant.
  Otherwise we leave the node intact, and set the result type to SpecString.
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
  Parse op_typeof
* dfg/DFGCSEPhase.cpp:
(JSC::DFG::CSEPhase::performNodeCSE):
  TypeOf nodes can be subjected to pure CSE
* dfg/DFGCapabilities.h:
(JSC::DFG::canCompileOpcode):
  We can handle typeof.
* dfg/DFGNodeType.h:
(DFG):
  Define the node.
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
  Add operationTypeOf to support the non-trivial cases.
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
  Actual codegen
* runtime/Operations.cpp:
(JSC::jsTypeStringForValue):
(JSC):
* runtime/Operations.h:
(JSC):
  Some refactoring to allow us to get the type string for an
  object without needing a callframe.

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (139144 => 139145)


--- trunk/Source/_javascript_Core/ChangeLog	2013-01-09 02:30:03 UTC (rev 139144)
+++ trunk/Source/_javascript_Core/ChangeLog	2013-01-09 02:37:29 UTC (rev 139145)
@@ -1,3 +1,51 @@
+2013-01-08  Oliver Hunt  <oli...@apple.com>
+
+        Support op_typeof in the DFG
+        https://bugs.webkit.org/show_bug.cgi?id=98898
+
+        Reviewed by Filip Pizlo.
+
+        Adds a TypeOf node to the DFG to support op_typeof.
+
+        To avoid adding too much GC horror, this also makes the
+        common strings portion of the SmallString cache strongly
+        referenced.
+
+        * dfg/DFGAbstractState.cpp:
+        (JSC::DFG::AbstractState::execute):
+          We try to determine the result early here, and substitute in a constant.
+          Otherwise we leave the node intact, and set the result type to SpecString.
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+          Parse op_typeof
+        * dfg/DFGCSEPhase.cpp:
+        (JSC::DFG::CSEPhase::performNodeCSE):
+          TypeOf nodes can be subjected to pure CSE
+        * dfg/DFGCapabilities.h:
+        (JSC::DFG::canCompileOpcode):
+          We can handle typeof.
+        * dfg/DFGNodeType.h:
+        (DFG):
+          Define the node.
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGOperations.h:
+          Add operationTypeOf to support the non-trivial cases.
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        (JSC::DFG::PredictionPropagationPhase::propagate):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+          Actual codegen
+        * runtime/Operations.cpp:
+        (JSC::jsTypeStringForValue):
+        (JSC):
+        * runtime/Operations.h:
+        (JSC):
+          Some refactoring to allow us to get the type string for an
+          object without needing a callframe.
+
+
 2013-01-08  Filip Pizlo  <fpi...@apple.com>
 
         DFG shouldn't treat the 'this' argument as being captured if a code block uses arguments

Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractState.cpp (139144 => 139145)


--- trunk/Source/_javascript_Core/dfg/DFGAbstractState.cpp	2013-01-09 02:30:03 UTC (rev 139144)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractState.cpp	2013-01-09 02:37:29 UTC (rev 139145)
@@ -31,6 +31,7 @@
 #include "CodeBlock.h"
 #include "DFGBasicBlock.h"
 #include "GetByIdStatus.h"
+#include "Operations.h"
 #include "PutByIdStatus.h"
 
 namespace JSC { namespace DFG {
@@ -707,6 +708,11 @@
             case IsString:
                 constantWasSet = trySetConstant(nodeIndex, jsBoolean(isJSString(child)));
                 break;
+            case IsObject:
+                if (child.isNull() || !child.isObject()) {
+                    constantWasSet = trySetConstant(nodeIndex, jsBoolean(child.isNull()));
+                    break;
+                }
             default:
                 constantWasSet = false;
                 break;
@@ -716,9 +722,64 @@
                 break;
             }
         }
+
         forNode(nodeIndex).set(SpecBoolean);
         break;
     }
+
+    case TypeOf: {
+        JSGlobalData* globalData = m_codeBlock->globalData();
+        JSValue child = forNode(node.child1()).value();
+        AbstractValue& abstractChild = forNode(node.child1());
+        if (child) {
+            JSValue typeString = jsTypeStringForValue(*globalData, m_codeBlock->globalObjectFor(node.codeOrigin), child);
+            if (trySetConstant(nodeIndex, typeString)) {
+                m_foundConstants = true;
+                break;
+            }
+        } else if (isNumberSpeculation(abstractChild.m_type)) {
+            if (trySetConstant(nodeIndex, globalData->smallStrings.numberString())) {
+                forNode(node.child1()).filter(SpecNumber);
+                m_foundConstants = true;
+                break;
+            }
+        } else if (isStringSpeculation(abstractChild.m_type)) {
+            if (trySetConstant(nodeIndex, globalData->smallStrings.stringString())) {
+                forNode(node.child1()).filter(SpecString);
+                m_foundConstants = true;
+                break;
+            }
+        } else if (isFinalObjectSpeculation(abstractChild.m_type) || isArraySpeculation(abstractChild.m_type) || isArgumentsSpeculation(abstractChild.m_type)) {
+            if (trySetConstant(nodeIndex, globalData->smallStrings.objectString())) {
+                forNode(node.child1()).filter(SpecFinalObject | SpecArray | SpecArguments);
+                m_foundConstants = true;
+                break;
+            }
+        } else if (isFunctionSpeculation(abstractChild.m_type)) {
+            if (trySetConstant(nodeIndex, globalData->smallStrings.functionString())) {
+                forNode(node.child1()).filter(SpecFunction);
+                m_foundConstants = true;
+                break;
+            }
+        } else if (isBooleanSpeculation(abstractChild.m_type)) {
+            if (trySetConstant(nodeIndex, globalData->smallStrings.booleanString())) {
+                forNode(node.child1()).filter(SpecBoolean);
+                m_foundConstants = true;
+                break;
+            }
+        } else {
+            Node& childNode = m_graph[node.child1()];
+            if (isCellSpeculation(childNode.prediction())) {
+                if (isStringSpeculation(childNode.prediction()))
+                    forNode(node.child1()).filter(SpecString);
+                else
+                    forNode(node.child1()).filter(SpecCell);
+                node.setCanExit(true);
+            }
+        }
+        forNode(nodeIndex).set(SpecString);
+        break;
+    }
             
     case CompareLess:
     case CompareLessEq:

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (139144 => 139145)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2013-01-09 02:30:03 UTC (rev 139144)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2013-01-09 02:37:29 UTC (rev 139145)
@@ -3223,6 +3223,12 @@
             NEXT_OPCODE(op_new_func_exp);
         }
 
+        case op_typeof: {
+            set(currentInstruction[1].u.operand,
+                addToGraph(TypeOf, get(currentInstruction[2].u.operand)));
+            NEXT_OPCODE(op_typeof);
+        }
+
         default:
             // Parse failed! This should not happen because the capabilities checker
             // should have caught it.

Modified: trunk/Source/_javascript_Core/dfg/DFGCSEPhase.cpp (139144 => 139145)


--- trunk/Source/_javascript_Core/dfg/DFGCSEPhase.cpp	2013-01-09 02:30:03 UTC (rev 139144)
+++ trunk/Source/_javascript_Core/dfg/DFGCSEPhase.cpp	2013-01-09 02:37:29 UTC (rev 139145)
@@ -597,6 +597,7 @@
             case CreateThis:
             case AllocatePropertyStorage:
             case ReallocatePropertyStorage:
+            case TypeOf:
                 return NoNode;
                 
             case GetIndexedPropertyStorage:
@@ -1166,6 +1167,7 @@
         case SkipScope:
         case GetScopeRegisters:
         case GetScope:
+        case TypeOf:
             setReplacement(pureCSE(node));
             break;
             

Modified: trunk/Source/_javascript_Core/dfg/DFGCapabilities.h (139144 => 139145)


--- trunk/Source/_javascript_Core/dfg/DFGCapabilities.h	2013-01-09 02:30:03 UTC (rev 139144)
+++ trunk/Source/_javascript_Core/dfg/DFGCapabilities.h	2013-01-09 02:37:29 UTC (rev 139145)
@@ -198,6 +198,7 @@
     case op_jneq_ptr:
     case op_put_to_base_variable:
     case op_put_to_base:
+    case op_typeof:
         return CanCompile;
         
     case op_call_varargs:

Modified: trunk/Source/_javascript_Core/dfg/DFGNodeType.h (139144 => 139145)


--- trunk/Source/_javascript_Core/dfg/DFGNodeType.h	2013-01-09 02:30:03 UTC (rev 139144)
+++ trunk/Source/_javascript_Core/dfg/DFGNodeType.h	2013-01-09 02:37:29 UTC (rev 139145)
@@ -214,6 +214,7 @@
     macro(IsString, NodeResultBoolean) \
     macro(IsObject, NodeResultBoolean) \
     macro(IsFunction, NodeResultBoolean) \
+    macro(TypeOf, NodeResultJS) \
     macro(LogicalNot, NodeResultBoolean) \
     macro(ToPrimitive, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
     macro(StrCat, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (139144 => 139145)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2013-01-09 02:30:03 UTC (rev 139144)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2013-01-09 02:37:29 UTC (rev 139145)
@@ -1428,6 +1428,11 @@
     return jsIsFunctionType(JSValue::decode(value));
 }
 
+JSCell* DFG_OPERATION operationTypeOf(ExecState* exec, JSCell* value)
+{
+    return jsTypeStringForValue(exec, JSValue(value)).asCell();
+}
+
 void DFG_OPERATION operationReallocateStorageAndFinishPut(ExecState* exec, JSObject* base, Structure* structure, PropertyOffset offset, EncodedJSValue value)
 {
     JSGlobalData& globalData = exec->globalData();

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.h (139144 => 139145)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.h	2013-01-09 02:30:03 UTC (rev 139144)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.h	2013-01-09 02:37:29 UTC (rev 139145)
@@ -199,6 +199,7 @@
 double DFG_OPERATION operationFModOnInts(int32_t, int32_t) WTF_INTERNAL;
 size_t DFG_OPERATION operationIsObject(ExecState*, EncodedJSValue) WTF_INTERNAL;
 size_t DFG_OPERATION operationIsFunction(EncodedJSValue) WTF_INTERNAL;
+JSCell* DFG_OPERATION operationTypeOf(ExecState*, JSCell*) WTF_INTERNAL;
 void DFG_OPERATION operationReallocateStorageAndFinishPut(ExecState*, JSObject*, Structure*, PropertyOffset, EncodedJSValue) WTF_INTERNAL;
 char* DFG_OPERATION operationAllocatePropertyStorageWithInitialCapacity(ExecState*) WTF_INTERNAL;
 char* DFG_OPERATION operationAllocatePropertyStorage(ExecState*, size_t newSize) WTF_INTERNAL;

Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (139144 => 139145)


--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2013-01-09 02:30:03 UTC (rev 139144)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2013-01-09 02:37:29 UTC (rev 139145)
@@ -518,7 +518,13 @@
             changed |= mergeDefaultFlags(node);
             break;
         }
-            
+
+        case TypeOf: {
+            changed |= setPrediction(SpecString);
+            changed |= mergeDefaultFlags(node);
+            break;
+        }
+
         case GetById: {
             changed |= mergePrediction(node.getHeapPrediction());
             changed |= mergeDefaultFlags(node);

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (139144 => 139145)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2013-01-09 02:30:03 UTC (rev 139144)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2013-01-09 02:37:29 UTC (rev 139145)
@@ -4584,7 +4584,67 @@
         booleanResult(result.gpr(), m_compileIndex);
         break;
     }
+    case TypeOf: {
+        JSValueOperand value(this, node.child1());
+        GPRReg tagGPR = value.tagGPR();
+        GPRReg payloadGPR = value.payloadGPR();
+        GPRTemporary temp(this);
+        GPRReg tempGPR = temp.gpr();
+        GPRResult result(this);
+        GPRReg resultGPR = result.gpr();
+        JITCompiler::JumpList doneJumps;
 
+        flushRegisters();
+
+        JITCompiler::Jump isNotCell = m_jit.branch32(JITCompiler::NotEqual, tagGPR, JITCompiler::TrustedImm32(JSValue::CellTag));
+        Node& child = m_jit.graph()[node.child1()];
+        if (child.shouldSpeculateCell())
+            speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), node.child1(), isNotCell);
+
+        if (!child.shouldSpeculateNonStringCell()) {
+            m_jit.loadPtr(JITCompiler::Address(payloadGPR, JSCell::structureOffset()), tempGPR);
+            JITCompiler::Jump notString = m_jit.branch8(JITCompiler::NotEqual, JITCompiler::Address(tempGPR, Structure::typeInfoTypeOffset()), TrustedImm32(StringType));
+            if (child.shouldSpeculateString())
+                speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), node.child1(), notString);
+            m_jit.move(TrustedImmPtr(m_jit.globalData()->smallStrings.stringString()), resultGPR);
+            doneJumps.append(m_jit.jump());
+            if (!child.shouldSpeculateString()) {
+                notString.link(&m_jit);
+                callOperation(operationTypeOf, resultGPR, payloadGPR);
+                doneJumps.append(m_jit.jump());
+            }
+        } else {
+            callOperation(operationTypeOf, resultGPR, payloadGPR);
+            doneJumps.append(m_jit.jump());
+        }
+
+        if (!child.shouldSpeculateCell()) {
+            isNotCell.link(&m_jit);
+
+            m_jit.add32(TrustedImm32(1), tagGPR, tempGPR);
+            JITCompiler::Jump notNumber = m_jit.branch32(JITCompiler::AboveOrEqual, tempGPR, JITCompiler::TrustedImm32(JSValue::LowestTag + 1));
+            m_jit.move(TrustedImmPtr(m_jit.globalData()->smallStrings.numberString()), resultGPR);
+            doneJumps.append(m_jit.jump());
+            notNumber.link(&m_jit);
+
+            JITCompiler::Jump notUndefined = m_jit.branch32(JITCompiler::NotEqual, tagGPR, TrustedImm32(JSValue::UndefinedTag));
+            m_jit.move(TrustedImmPtr(m_jit.globalData()->smallStrings.undefinedString()), resultGPR);
+            doneJumps.append(m_jit.jump());
+            notUndefined.link(&m_jit);
+
+            JITCompiler::Jump notNull = m_jit.branch32(JITCompiler::NotEqual, tagGPR, TrustedImm32(JSValue::NullTag));
+            m_jit.move(TrustedImmPtr(m_jit.globalData()->smallStrings.objectString()), resultGPR);
+            doneJumps.append(m_jit.jump());
+            notNull.link(&m_jit);
+
+            // Only boolean left
+            m_jit.move(TrustedImmPtr(m_jit.globalData()->smallStrings.booleanString()), resultGPR);
+        }
+        doneJumps.link(&m_jit);
+        cellResult(resultGPR, m_compileIndex);
+        break;
+    }
+
     case Phi:
     case Flush:
         break;

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (139144 => 139145)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2013-01-09 02:30:03 UTC (rev 139144)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2013-01-09 02:37:29 UTC (rev 139145)
@@ -4088,7 +4088,7 @@
         cachedGetById(node.codeOrigin, baseGPR, resultGPR, node.identifierNumber(), notCell, DontSpill);
         
         jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
-        
+
         break;
     }
 
@@ -4511,6 +4511,64 @@
         break;
     }
 
+    case TypeOf: {
+        JSValueOperand value(this, node.child1());
+        GPRReg valueGPR = value.gpr();
+        GPRTemporary temp(this);
+        GPRReg tempGPR = temp.gpr();
+        GPRResult result(this);
+        GPRReg resultGPR = result.gpr();
+        JITCompiler::JumpList doneJumps;
+
+        flushRegisters();
+
+        JITCompiler::Jump isNotCell = m_jit.branchTest64(JITCompiler::NonZero, valueGPR, GPRInfo::tagMaskRegister);
+        Node& child = m_jit.graph()[node.child1()];
+        if (child.shouldSpeculateCell())
+            speculationCheck(BadType, JSValueSource(valueGPR), node.child1(), isNotCell);
+
+        if (!child.shouldSpeculateNonStringCell()) {
+            m_jit.loadPtr(JITCompiler::Address(valueGPR, JSCell::structureOffset()), tempGPR);
+            JITCompiler::Jump notString = m_jit.branch8(JITCompiler::NotEqual, JITCompiler::Address(tempGPR, Structure::typeInfoTypeOffset()), TrustedImm32(StringType));
+            if (child.shouldSpeculateString())
+                speculationCheck(BadType, JSValueSource(valueGPR), node.child1(), notString);
+            m_jit.move(TrustedImmPtr(m_jit.globalData()->smallStrings.stringString()), resultGPR);
+            doneJumps.append(m_jit.jump());
+            if (!child.shouldSpeculateString()) {
+                notString.link(&m_jit);
+                callOperation(operationTypeOf, resultGPR, valueGPR);
+                doneJumps.append(m_jit.jump());
+            }
+        } else {
+            callOperation(operationTypeOf, resultGPR, valueGPR);
+            doneJumps.append(m_jit.jump());
+        }
+
+        if (!child.shouldSpeculateCell()) {
+            isNotCell.link(&m_jit);
+            JITCompiler::Jump notNumber = m_jit.branchTest64(JITCompiler::Zero, valueGPR, GPRInfo::tagTypeNumberRegister);
+            m_jit.move(TrustedImmPtr(m_jit.globalData()->smallStrings.numberString()), resultGPR);
+            doneJumps.append(m_jit.jump());
+            notNumber.link(&m_jit);
+
+            JITCompiler::Jump notUndefined = m_jit.branch64(JITCompiler::NotEqual, valueGPR, JITCompiler::TrustedImm64(ValueUndefined));
+            m_jit.move(TrustedImmPtr(m_jit.globalData()->smallStrings.undefinedString()), resultGPR);
+            doneJumps.append(m_jit.jump());
+            notUndefined.link(&m_jit);
+
+            JITCompiler::Jump notNull = m_jit.branch64(JITCompiler::NotEqual, valueGPR, JITCompiler::TrustedImm64(ValueNull));
+            m_jit.move(TrustedImmPtr(m_jit.globalData()->smallStrings.objectString()), resultGPR);
+            doneJumps.append(m_jit.jump());
+            notNull.link(&m_jit);
+
+            // Only boolean left
+            m_jit.move(TrustedImmPtr(m_jit.globalData()->smallStrings.booleanString()), resultGPR);
+        }
+        doneJumps.link(&m_jit);
+        cellResult(resultGPR, m_compileIndex);
+        break;
+    }
+
     case Flush:
     case Phi:
         break;

Modified: trunk/Source/_javascript_Core/heap/Heap.cpp (139144 => 139145)


--- trunk/Source/_javascript_Core/heap/Heap.cpp	2013-01-09 02:30:03 UTC (rev 139144)
+++ trunk/Source/_javascript_Core/heap/Heap.cpp	2013-01-09 02:37:29 UTC (rev 139145)
@@ -492,6 +492,8 @@
                 m_globalData->codeBlocksBeingCompiled[i]->visitAggregate(visitor);
         }
 
+        m_globalData->smallStrings.visitStrongReferences(visitor);
+
         {
             GCPHASE(VisitMachineRoots);
             MARK_LOG_ROOT(visitor, "C++ Stack");

Modified: trunk/Source/_javascript_Core/runtime/BooleanPrototype.cpp (139144 => 139145)


--- trunk/Source/_javascript_Core/runtime/BooleanPrototype.cpp	2013-01-09 02:30:03 UTC (rev 139144)
+++ trunk/Source/_javascript_Core/runtime/BooleanPrototype.cpp	2013-01-09 02:37:29 UTC (rev 139145)
@@ -79,19 +79,19 @@
     JSGlobalData* globalData = &exec->globalData();
     JSValue thisValue = exec->hostThisValue();
     if (thisValue == jsBoolean(false))
-        return JSValue::encode(globalData->smallStrings.falseString(globalData));
+        return JSValue::encode(globalData->smallStrings.falseString());
 
     if (thisValue == jsBoolean(true))
-        return JSValue::encode(globalData->smallStrings.trueString(globalData));
+        return JSValue::encode(globalData->smallStrings.trueString());
 
     if (!thisValue.inherits(&BooleanObject::s_info))
         return throwVMTypeError(exec);
 
     if (asBooleanObject(thisValue)->internalValue() == jsBoolean(false))
-        return JSValue::encode(globalData->smallStrings.falseString(globalData));
+        return JSValue::encode(globalData->smallStrings.falseString());
 
     ASSERT(asBooleanObject(thisValue)->internalValue() == jsBoolean(true));
-    return JSValue::encode(globalData->smallStrings.trueString(globalData));
+    return JSValue::encode(globalData->smallStrings.trueString());
 }
 
 EncodedJSValue JSC_HOST_CALL booleanProtoFuncValueOf(ExecState* exec)

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalData.cpp (139144 => 139145)


--- trunk/Source/_javascript_Core/runtime/JSGlobalData.cpp	2013-01-09 02:30:03 UTC (rev 139144)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalData.cpp	2013-01-09 02:37:29 UTC (rev 139145)
@@ -230,6 +230,7 @@
     unlinkedProgramCodeBlockStructure.set(*this, UnlinkedProgramCodeBlock::createStructure(*this, 0, jsNull()));
     unlinkedEvalCodeBlockStructure.set(*this, UnlinkedEvalCodeBlock::createStructure(*this, 0, jsNull()));
     unlinkedFunctionCodeBlockStructure.set(*this, UnlinkedFunctionCodeBlock::createStructure(*this, 0, jsNull()));
+    smallStrings.initializeCommonStrings(*this);
 
     wtfThreadData().setCurrentIdentifierTable(existingEntryIdentifierTable);
 
@@ -245,7 +246,7 @@
 #endif
 
     heap.notifyIsSafeToCollect();
-    
+
     LLInt::Data::performAssertions(*this);
     
     if (Options::enableProfiler())

Modified: trunk/Source/_javascript_Core/runtime/JSString.h (139144 => 139145)


--- trunk/Source/_javascript_Core/runtime/JSString.h	2013-01-09 02:30:03 UTC (rev 139144)
+++ trunk/Source/_javascript_Core/runtime/JSString.h	2013-01-09 02:37:29 UTC (rev 139145)
@@ -333,7 +333,7 @@
 
     inline JSString* jsEmptyString(JSGlobalData* globalData)
     {
-        return globalData->smallStrings.emptyString(globalData);
+        return globalData->smallStrings.emptyString();
     }
 
     ALWAYS_INLINE JSString* jsSingleCharacterString(JSGlobalData* globalData, UChar c)
@@ -386,7 +386,7 @@
     {
         int size = s.length();
         if (!size)
-            return globalData->smallStrings.emptyString(globalData);
+            return globalData->smallStrings.emptyString();
         if (size == 1) {
             UChar c = s.characterAt(0);
             if (c <= maxSingleCharacterString)
@@ -402,7 +402,7 @@
         ASSERT(offset + length <= static_cast<unsigned>(s->length()));
         JSGlobalData* globalData = &exec->globalData();
         if (!length)
-            return globalData->smallStrings.emptyString(globalData);
+            return globalData->smallStrings.emptyString();
         return jsSubstring(globalData, s->value(exec), offset, length);
     }
 
@@ -412,7 +412,7 @@
         ASSERT(length <= static_cast<unsigned>(s.length()));
         ASSERT(offset + length <= static_cast<unsigned>(s.length()));
         if (!length)
-            return globalData->smallStrings.emptyString(globalData);
+            return globalData->smallStrings.emptyString();
         if (length == 1) {
             UChar c = s.characterAt(offset);
             if (c <= maxSingleCharacterString)
@@ -427,7 +427,7 @@
         ASSERT(length <= static_cast<unsigned>(s.length()));
         ASSERT(offset + length <= static_cast<unsigned>(s.length()));
         if (!length)
-            return globalData->smallStrings.emptyString(globalData);
+            return globalData->smallStrings.emptyString();
         if (length == 1) {
             UChar c = s.characterAt(offset);
             if (c <= maxSingleCharacterString)
@@ -440,7 +440,7 @@
     {
         int size = s.length();
         if (!size)
-            return globalData->smallStrings.emptyString(globalData);
+            return globalData->smallStrings.emptyString();
         if (size == 1) {
             UChar c = s.characterAt(0);
             if (c <= maxSingleCharacterString)

Modified: trunk/Source/_javascript_Core/runtime/JSValue.cpp (139144 => 139145)


--- trunk/Source/_javascript_Core/runtime/JSValue.cpp	2013-01-09 02:30:03 UTC (rev 139144)
+++ trunk/Source/_javascript_Core/runtime/JSValue.cpp	2013-01-09 02:37:29 UTC (rev 139145)
@@ -295,13 +295,13 @@
     if (isDouble())
         return jsString(&globalData, globalData.numericStrings.add(asDouble()));
     if (isTrue())
-        return globalData.smallStrings.trueString(&globalData);
+        return globalData.smallStrings.trueString();
     if (isFalse())
-        return globalData.smallStrings.falseString(&globalData);
+        return globalData.smallStrings.falseString();
     if (isNull())
-        return globalData.smallStrings.nullString(&globalData);
+        return globalData.smallStrings.nullString();
     if (isUndefined())
-        return globalData.smallStrings.undefinedString(&globalData);
+        return globalData.smallStrings.undefinedString();
 
     ASSERT(isCell());
     JSValue value = asCell()->toPrimitive(exec, PreferString);

Modified: trunk/Source/_javascript_Core/runtime/Operations.cpp (139144 => 139145)


--- trunk/Source/_javascript_Core/runtime/Operations.cpp	2013-01-09 02:30:03 UTC (rev 139144)
+++ trunk/Source/_javascript_Core/runtime/Operations.cpp	2013-01-09 02:37:29 UTC (rev 139145)
@@ -56,30 +56,34 @@
     return jsNumber(p1.toNumber(callFrame) + p2.toNumber(callFrame));
 }
 
-JSValue jsTypeStringForValue(CallFrame* callFrame, JSValue v)
+JSValue jsTypeStringForValue(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue v)
 {
-    JSGlobalData& globalData = callFrame->globalData();
     if (v.isUndefined())
-        return globalData.smallStrings.undefinedString(&globalData);
+        return globalData.smallStrings.undefinedString();
     if (v.isBoolean())
-        return globalData.smallStrings.booleanString(&globalData);
+        return globalData.smallStrings.booleanString();
     if (v.isNumber())
-        return globalData.smallStrings.numberString(&globalData);
+        return globalData.smallStrings.numberString();
     if (v.isString())
-        return globalData.smallStrings.stringString(&globalData);
+        return globalData.smallStrings.stringString();
     if (v.isObject()) {
         // Return "undefined" for objects that should be treated
         // as null when doing comparisons.
-        if (asObject(v)->structure()->masqueradesAsUndefined(callFrame->lexicalGlobalObject()))
-            return globalData.smallStrings.undefinedString(&globalData);
+        if (asObject(v)->structure()->masqueradesAsUndefined(globalObject))
+            return globalData.smallStrings.undefinedString();
         CallData callData;
         JSObject* object = asObject(v);
         if (object->methodTable()->getCallData(object, callData) != CallTypeNone)
-            return globalData.smallStrings.functionString(&globalData);
+            return globalData.smallStrings.functionString();
     }
-    return globalData.smallStrings.objectString(&globalData);
+    return globalData.smallStrings.objectString();
 }
 
+JSValue jsTypeStringForValue(CallFrame* callFrame, JSValue v)
+{
+    return jsTypeStringForValue(callFrame->globalData(), callFrame->lexicalGlobalObject(), v);
+}
+
 bool jsIsObjectType(CallFrame* callFrame, JSValue v)
 {
     if (!v.isCell())

Modified: trunk/Source/_javascript_Core/runtime/Operations.h (139144 => 139145)


--- trunk/Source/_javascript_Core/runtime/Operations.h	2013-01-09 02:30:03 UTC (rev 139144)
+++ trunk/Source/_javascript_Core/runtime/Operations.h	2013-01-09 02:37:29 UTC (rev 139145)
@@ -32,6 +32,7 @@
 
     NEVER_INLINE JSValue jsAddSlowCase(CallFrame*, JSValue, JSValue);
     JSValue jsTypeStringForValue(CallFrame*, JSValue);
+    JSValue jsTypeStringForValue(JSGlobalData&, JSGlobalObject*, JSValue);
     bool jsIsObjectType(CallFrame*, JSValue);
     bool jsIsFunctionType(JSValue);
 

Modified: trunk/Source/_javascript_Core/runtime/SmallStrings.cpp (139144 => 139145)


--- trunk/Source/_javascript_Core/runtime/SmallStrings.cpp	2013-01-09 02:30:03 UTC (rev 139144)
+++ trunk/Source/_javascript_Core/runtime/SmallStrings.cpp	2013-01-09 02:37:29 UTC (rev 139145)
@@ -80,6 +80,22 @@
         m_singleCharacterStrings[i] = 0;
 }
 
+void SmallStrings::initializeCommonStrings(JSGlobalData& globalData)
+{
+    createEmptyString(&globalData);
+#define JSC_COMMON_STRINGS_ATTRIBUTE_INITIALIZE(name) initialize(&globalData, m_##name, #name);
+    JSC_COMMON_STRINGS_EACH_NAME(JSC_COMMON_STRINGS_ATTRIBUTE_INITIALIZE)
+#undef JSC_COMMON_STRINGS_ATTRIBUTE_INITIALIZE
+}
+
+void SmallStrings::visitStrongReferences(SlotVisitor& visitor)
+{
+    visitor.appendUnbarrieredPointer(&m_emptyString);
+#define JSC_COMMON_STRINGS_ATTRIBUTE_VISIT(name) visitor.appendUnbarrieredPointer(&m_##name);
+    JSC_COMMON_STRINGS_EACH_NAME(JSC_COMMON_STRINGS_ATTRIBUTE_VISIT)
+#undef JSC_COMMON_STRINGS_ATTRIBUTE_VISIT
+}
+
 SmallStrings::~SmallStrings()
 {
 }
@@ -89,9 +105,6 @@
     finalize(m_emptyString);
     for (unsigned i = 0; i < singleCharacterStringCount; ++i)
         finalize(m_singleCharacterStrings[i]);
-#define JSC_COMMON_STRINGS_ATTRIBUTE_FINALIZE(name) finalize(m_##name);
-    JSC_COMMON_STRINGS_EACH_NAME(JSC_COMMON_STRINGS_ATTRIBUTE_FINALIZE)
-#undef JSC_COMMON_STRINGS_ATTRIBUTE_FINALIZE
 }
 
 void SmallStrings::createEmptyString(JSGlobalData* globalData)

Modified: trunk/Source/_javascript_Core/runtime/SmallStrings.h (139144 => 139145)


--- trunk/Source/_javascript_Core/runtime/SmallStrings.h	2013-01-09 02:30:03 UTC (rev 139144)
+++ trunk/Source/_javascript_Core/runtime/SmallStrings.h	2013-01-09 02:37:29 UTC (rev 139145)
@@ -26,6 +26,8 @@
 #ifndef SmallStrings_h
 #define SmallStrings_h
 
+#include "WriteBarrier.h"
+
 #include <wtf/FixedArray.h>
 #include <wtf/Noncopyable.h>
 #include <wtf/OwnPtr.h>
@@ -61,10 +63,8 @@
         SmallStrings();
         ~SmallStrings();
 
-        JSString* emptyString(JSGlobalData* globalData)
+        JSString* emptyString()
         {
-            if (!m_emptyString)
-                createEmptyString(globalData);
             return m_emptyString;
         }
 
@@ -81,11 +81,12 @@
 
         JSString** singleCharacterStrings() { return &m_singleCharacterStrings[0]; }
 
+        void initializeCommonStrings(JSGlobalData&);
+        void visitStrongReferences(SlotVisitor&);
+
 #define JSC_COMMON_STRINGS_ACCESSOR_DEFINITION(name) \
-        JSString* name##String(JSGlobalData* globalData) const \
+        JSString* name##String() const \
         { \
-            if (!m_##name) \
-                initialize(globalData, m_##name, #name); \
             return m_##name; \
         }
         JSC_COMMON_STRINGS_EACH_NAME(JSC_COMMON_STRINGS_ACCESSOR_DEFINITION)
@@ -100,7 +101,7 @@
         void initialize(JSGlobalData* globalData, JSString*& string, const char* value) const;
 
         JSString* m_emptyString;
-#define JSC_COMMON_STRINGS_ATTRIBUTE_DECLARATION(name) mutable JSString* m_##name;
+#define JSC_COMMON_STRINGS_ATTRIBUTE_DECLARATION(name) JSString* m_##name;
         JSC_COMMON_STRINGS_EACH_NAME(JSC_COMMON_STRINGS_ATTRIBUTE_DECLARATION)
 #undef JSC_COMMON_STRINGS_ATTRIBUTE_DECLARATION
         JSString* m_singleCharacterStrings[singleCharacterStringCount];
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to