Title: [118555] trunk/Source/_javascript_Core
Revision
118555
Author
[email protected]
Date
2012-05-25 13:19:55 -0700 (Fri, 25 May 2012)

Log Message

DFG ConvertThis should just be a CheckStructure if the structure is known
https://bugs.webkit.org/show_bug.cgi?id=87057

Reviewed by Gavin Barraclough.
        
Merged r118021 from dfgopt.
        
This gives ValueProfile the ability to track singleton values - i.e. profiling
sites that always see the same value.
        
That is then used to profile the structure in op_convert_this.
        
This is then used to optimize op_convert_this into a CheckStructure if the
structure is always the same.
        
That then results in better CSE in inlined code that uses 'this', since
previously we couldn't CSE accesses on 'this' from different inline call frames.
        
Also fixed a bug where we were unnecessarily flushing 'this'.

* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dump):
(JSC::CodeBlock::stronglyVisitStrongReferences):
* bytecode/LazyOperandValueProfile.cpp:
(JSC::CompressedLazyOperandValueProfileHolder::computeUpdatedPredictions):
* bytecode/LazyOperandValueProfile.h:
(CompressedLazyOperandValueProfileHolder):
* bytecode/Opcode.h:
(JSC):
(JSC::padOpcodeName):
* bytecode/ValueProfile.h:
(JSC::ValueProfileBase::ValueProfileBase):
(JSC::ValueProfileBase::dump):
(JSC::ValueProfileBase::computeUpdatedPrediction):
(ValueProfileBase):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::BytecodeGenerator):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::setArgument):
(JSC::DFG::ByteCodeParser::parseBlock):
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_convert_this):
(JSC::JIT::emitSlow_op_convert_this):
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emit_op_convert_this):
(JSC::JIT::emitSlow_op_convert_this):
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
* runtime/JSValue.h:
(JSValue):
* runtime/Structure.h:
(JSC::JSValue::structureOrUndefined):
(JSC):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (118554 => 118555)


--- trunk/Source/_javascript_Core/ChangeLog	2012-05-25 20:11:42 UTC (rev 118554)
+++ trunk/Source/_javascript_Core/ChangeLog	2012-05-25 20:19:55 UTC (rev 118555)
@@ -1,3 +1,61 @@
+2012-05-21  Filip Pizlo  <[email protected]>
+
+        DFG ConvertThis should just be a CheckStructure if the structure is known
+        https://bugs.webkit.org/show_bug.cgi?id=87057
+
+        Reviewed by Gavin Barraclough.
+        
+        Merged r118021 from dfgopt.
+        
+        This gives ValueProfile the ability to track singleton values - i.e. profiling
+        sites that always see the same value.
+        
+        That is then used to profile the structure in op_convert_this.
+        
+        This is then used to optimize op_convert_this into a CheckStructure if the
+        structure is always the same.
+        
+        That then results in better CSE in inlined code that uses 'this', since
+        previously we couldn't CSE accesses on 'this' from different inline call frames.
+        
+        Also fixed a bug where we were unnecessarily flushing 'this'.
+
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::dump):
+        (JSC::CodeBlock::stronglyVisitStrongReferences):
+        * bytecode/LazyOperandValueProfile.cpp:
+        (JSC::CompressedLazyOperandValueProfileHolder::computeUpdatedPredictions):
+        * bytecode/LazyOperandValueProfile.h:
+        (CompressedLazyOperandValueProfileHolder):
+        * bytecode/Opcode.h:
+        (JSC):
+        (JSC::padOpcodeName):
+        * bytecode/ValueProfile.h:
+        (JSC::ValueProfileBase::ValueProfileBase):
+        (JSC::ValueProfileBase::dump):
+        (JSC::ValueProfileBase::computeUpdatedPrediction):
+        (ValueProfileBase):
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::BytecodeGenerator):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::setArgument):
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_convert_this):
+        (JSC::JIT::emitSlow_op_convert_this):
+        * jit/JITOpcodes32_64.cpp:
+        (JSC::JIT::emit_op_convert_this):
+        (JSC::JIT::emitSlow_op_convert_this):
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+        * llint/LowLevelInterpreter32_64.asm:
+        * llint/LowLevelInterpreter64.asm:
+        * runtime/JSValue.h:
+        (JSValue):
+        * runtime/Structure.h:
+        (JSC::JSValue::structureOrUndefined):
+        (JSC):
+
 2012-05-24  Tim Horton  <[email protected]>
 
         Add feature defines for web-facing parts of CSS Regions and Exclusions

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (118554 => 118555)


--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2012-05-25 20:11:42 UTC (rev 118554)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2012-05-25 20:19:55 UTC (rev 118555)
@@ -670,6 +670,7 @@
         case op_convert_this: {
             int r0 = (++it)->u.operand;
             dataLog("[%4d] convert_this\t %s\n", location, registerName(exec, r0).data());
+            ++it; // Skip value profile.
             break;
         }
         case op_new_object: {
@@ -2085,14 +2086,14 @@
         }
     }
     
-    m_lazyOperandValueProfiles.computeUpdatedPredictions();
+    m_lazyOperandValueProfiles.computeUpdatedPredictions(Collection);
 #endif
 
 #if ENABLE(VALUE_PROFILER)
     for (unsigned profileIndex = 0; profileIndex < numberOfArgumentValueProfiles(); ++profileIndex)
-        valueProfileForArgument(profileIndex)->computeUpdatedPrediction();
+        valueProfileForArgument(profileIndex)->computeUpdatedPrediction(Collection);
     for (unsigned profileIndex = 0; profileIndex < numberOfValueProfiles(); ++profileIndex)
-        valueProfile(profileIndex)->computeUpdatedPrediction();
+        valueProfile(profileIndex)->computeUpdatedPrediction(Collection);
 #endif
 }
 

Modified: trunk/Source/_javascript_Core/bytecode/LazyOperandValueProfile.cpp (118554 => 118555)


--- trunk/Source/_javascript_Core/bytecode/LazyOperandValueProfile.cpp	2012-05-25 20:11:42 UTC (rev 118554)
+++ trunk/Source/_javascript_Core/bytecode/LazyOperandValueProfile.cpp	2012-05-25 20:19:55 UTC (rev 118555)
@@ -33,13 +33,13 @@
 CompressedLazyOperandValueProfileHolder::CompressedLazyOperandValueProfileHolder() { }
 CompressedLazyOperandValueProfileHolder::~CompressedLazyOperandValueProfileHolder() { }
 
-void CompressedLazyOperandValueProfileHolder::computeUpdatedPredictions()
+void CompressedLazyOperandValueProfileHolder::computeUpdatedPredictions(OperationInProgress operation)
 {
     if (!m_data)
         return;
     
     for (unsigned i = 0; i < m_data->size(); ++i)
-        m_data->at(i).computeUpdatedPrediction();
+        m_data->at(i).computeUpdatedPrediction(operation);
 }
 
 LazyOperandValueProfile* CompressedLazyOperandValueProfileHolder::add(

Modified: trunk/Source/_javascript_Core/bytecode/LazyOperandValueProfile.h (118554 => 118555)


--- trunk/Source/_javascript_Core/bytecode/LazyOperandValueProfile.h	2012-05-25 20:11:42 UTC (rev 118554)
+++ trunk/Source/_javascript_Core/bytecode/LazyOperandValueProfile.h	2012-05-25 20:19:55 UTC (rev 118555)
@@ -155,7 +155,7 @@
     CompressedLazyOperandValueProfileHolder();
     ~CompressedLazyOperandValueProfileHolder();
     
-    void computeUpdatedPredictions();
+    void computeUpdatedPredictions(OperationInProgress);
     
     LazyOperandValueProfile* add(const LazyOperandValueProfileKey& key);
     

Modified: trunk/Source/_javascript_Core/bytecode/Opcode.h (118554 => 118555)


--- trunk/Source/_javascript_Core/bytecode/Opcode.h	2012-05-25 20:11:42 UTC (rev 118554)
+++ trunk/Source/_javascript_Core/bytecode/Opcode.h	2012-05-25 20:19:55 UTC (rev 118555)
@@ -43,7 +43,7 @@
         macro(op_init_lazy_reg, 2) \
         macro(op_create_arguments, 2) \
         macro(op_create_this, 2) \
-        macro(op_convert_this, 2) \
+        macro(op_convert_this, 3) \
         \
         macro(op_new_object, 2) \
         macro(op_new_array, 4) \

Modified: trunk/Source/_javascript_Core/bytecode/ValueProfile.h (118554 => 118555)


--- trunk/Source/_javascript_Core/bytecode/ValueProfile.h	2012-05-25 20:11:42 UTC (rev 118554)
+++ trunk/Source/_javascript_Core/bytecode/ValueProfile.h	2012-05-25 20:19:55 UTC (rev 118555)
@@ -33,6 +33,7 @@
 
 #if ENABLE(VALUE_PROFILER)
 
+#include "Heap.h"
 #include "JSArray.h"
 #include "PredictedType.h"
 #include "Structure.h"
@@ -51,6 +52,7 @@
         : m_bytecodeOffset(-1)
         , m_prediction(PredictNone)
         , m_numberOfSamplesInPrediction(0)
+        , m_singletonValueIsTop(false)
     {
         for (unsigned i = 0; i < totalNumberOfBuckets; ++i)
             m_buckets[i] = JSValue::encode(JSValue());
@@ -60,6 +62,7 @@
         : m_bytecodeOffset(bytecodeOffset)
         , m_prediction(PredictNone)
         , m_numberOfSamplesInPrediction(0)
+        , m_singletonValueIsTop(false)
     {
         for (unsigned i = 0; i < totalNumberOfBuckets; ++i)
             m_buckets[i] = JSValue::encode(JSValue());
@@ -112,6 +115,11 @@
                 "samples = %u, prediction = %s",
                 totalNumberOfSamples(),
                 predictionToString(m_prediction));
+        fprintf(out, ", value = ");
+        if (m_singletonValueIsTop)
+            fprintf(out, "TOP");
+        else
+            fprintf(out, "%s", m_singletonValue.description());
         bool first = true;
         for (unsigned i = 0; i < totalNumberOfBuckets; ++i) {
             JSValue value = JSValue::decode(m_buckets[i]);
@@ -127,7 +135,7 @@
     }
     
     // Updates the prediction and returns the new one.
-    PredictedType computeUpdatedPrediction()
+    PredictedType computeUpdatedPrediction(OperationInProgress operation = NoOperation)
     {
         for (unsigned i = 0; i < totalNumberOfBuckets; ++i) {
             JSValue value = JSValue::decode(m_buckets[i]);
@@ -137,9 +145,23 @@
             m_numberOfSamplesInPrediction++;
             mergePrediction(m_prediction, predictionFromValue(value));
             
+            if (!m_singletonValueIsTop && !!value) {
+                if (!m_singletonValue)
+                    m_singletonValue = value;
+                else if (m_singletonValue != value)
+                    m_singletonValueIsTop = true;
+            }
+            
             m_buckets[i] = JSValue::encode(JSValue());
         }
         
+        if (operation == Collection
+            && !m_singletonValueIsTop
+            && !!m_singletonValue
+            && m_singletonValue.isCell()
+            && !Heap::isMarked(m_singletonValue.asCell()))
+            m_singletonValueIsTop = true;
+            
         return m_prediction;
     }
     
@@ -148,6 +170,9 @@
     PredictedType m_prediction;
     unsigned m_numberOfSamplesInPrediction;
     
+    bool m_singletonValueIsTop;
+    JSValue m_singletonValue;
+
     EncodedJSValue m_buckets[totalNumberOfBuckets];
 };
 

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (118554 => 118555)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2012-05-25 20:11:42 UTC (rev 118554)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2012-05-25 20:19:55 UTC (rev 118555)
@@ -445,8 +445,9 @@
         emitOpcode(op_create_this);
         instructions().append(m_thisRegister.index());
     } else if (!codeBlock->isStrictMode() && (functionBody->usesThis() || codeBlock->usesEval() || m_shouldEmitDebugHooks)) {
-        emitOpcode(op_convert_this);
+        ValueProfile* profile = ""
         instructions().append(m_thisRegister.index());
+        instructions().append(profile);
     }
 }
 

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (118554 => 118555)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2012-05-25 20:11:42 UTC (rev 118554)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2012-05-25 20:19:55 UTC (rev 118555)
@@ -350,8 +350,9 @@
         stack->m_argumentPositions[argument]->addVariable(variableAccessData);
         NodeIndex nodeIndex = addToGraph(SetLocal, OpInfo(variableAccessData), value);
         m_currentBlock->variablesAtTail.argument(argument) = nodeIndex;
-        // Always flush arguments.
-        addToGraph(Flush, OpInfo(variableAccessData), nodeIndex);
+        // Always flush arguments, except for 'this'.
+        if (argument)
+            addToGraph(Flush, OpInfo(variableAccessData), nodeIndex);
     }
     
     VariableAccessData* flushArgument(int operand)
@@ -1582,10 +1583,27 @@
 
         case op_convert_this: {
             NodeIndex op1 = getThis();
-            if (m_graph[op1].op() == ConvertThis)
-                setThis(op1);
-            else
-                setThis(addToGraph(ConvertThis, op1));
+            if (m_graph[op1].op() != ConvertThis) {
+                ValueProfile* profile =
+                    m_inlineStackTop->m_profiledBlock->valueProfileForBytecodeOffset(m_currentProfilingIndex);
+                profile->computeUpdatedPrediction();
+#if DFG_ENABLE(DEBUG_VERBOSE)
+                dataLog("[@%lu bc#%u]: profile %p: ", m_graph.size(), m_currentProfilingIndex, profile);
+                profile->dump(WTF::dataFile());
+                dataLog("\n");
+#endif
+                if (profile->m_singletonValueIsTop
+                    || !profile->m_singletonValue
+                    || !profile->m_singletonValue.isCell()
+                    || profile->m_singletonValue.asCell()->classInfo() != &Structure::s_info)
+                    setThis(addToGraph(ConvertThis, op1));
+                else {
+                    addToGraph(
+                        CheckStructure,
+                        OpInfo(m_graph.addStructureSet(jsCast<Structure*>(profile->m_singletonValue.asCell()))),
+                        op1);
+                }
+            }
             NEXT_OPCODE(op_convert_this);
         }
 

Modified: trunk/Source/_javascript_Core/jit/JITOpcodes.cpp (118554 => 118555)


--- trunk/Source/_javascript_Core/jit/JITOpcodes.cpp	2012-05-25 20:11:42 UTC (rev 118554)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes.cpp	2012-05-25 20:19:55 UTC (rev 118555)
@@ -1257,10 +1257,14 @@
 
 void JIT::emit_op_convert_this(Instruction* currentInstruction)
 {
-    emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);
+    emitGetVirtualRegister(currentInstruction[1].u.operand, regT1);
 
-    emitJumpSlowCaseIfNotJSCell(regT0);
-    addSlowCase(branchPtr(Equal, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)));
+    emitJumpSlowCaseIfNotJSCell(regT1);
+    if (shouldEmitProfiling()) {
+        loadPtr(Address(regT1, JSCell::structureOffset()), regT0);
+        emitValueProfilingSite();
+    }
+    addSlowCase(branchPtr(Equal, Address(regT1, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)));
 }
 
 void JIT::emit_op_create_this(Instruction* currentInstruction)
@@ -1315,15 +1319,21 @@
     void* globalThis = m_codeBlock->globalObject()->globalScopeChain()->globalThis.get();
 
     linkSlowCase(iter);
-    Jump isNotUndefined = branchPtr(NotEqual, regT0, TrustedImmPtr(JSValue::encode(jsUndefined())));
+    if (shouldEmitProfiling())
+        move(TrustedImmPtr(bitwise_cast<void*>(JSValue::encode(jsUndefined()))), regT0);
+    Jump isNotUndefined = branchPtr(NotEqual, regT1, TrustedImmPtr(JSValue::encode(jsUndefined())));
+    emitValueProfilingSite();
     move(TrustedImmPtr(globalThis), regT0);
     emitPutVirtualRegister(currentInstruction[1].u.operand, regT0);
     emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_convert_this));
 
+    linkSlowCase(iter);
+    if (shouldEmitProfiling())
+        move(TrustedImmPtr(bitwise_cast<void*>(JSValue::encode(m_globalData->stringStructure.get()))), regT0);
     isNotUndefined.link(this);
-    linkSlowCase(iter);
+    emitValueProfilingSite();
     JITStubCall stubCall(this, cti_op_convert_this);
-    stubCall.addArgument(regT0);
+    stubCall.addArgument(regT1);
     stubCall.call(currentInstruction[1].u.operand);
 }
 

Modified: trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp (118554 => 118555)


--- trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp	2012-05-25 20:11:42 UTC (rev 118554)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp	2012-05-25 20:19:55 UTC (rev 118555)
@@ -1548,12 +1548,15 @@
 {
     unsigned thisRegister = currentInstruction[1].u.operand;
 
-    emitLoad(thisRegister, regT1, regT0);
+    emitLoad(thisRegister, regT3, regT2);
 
-    addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
-    addSlowCase(branchPtr(Equal, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)));
-
-    map(m_bytecodeOffset + OPCODE_LENGTH(op_convert_this), thisRegister, regT1, regT0);
+    addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::CellTag)));
+    if (shouldEmitProfiling()) {
+        loadPtr(Address(regT2, JSCell::structureOffset()), regT0);
+        move(regT3, regT1);
+        emitValueProfilingSite();
+    }
+    addSlowCase(branchPtr(Equal, Address(regT2, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)));
 }
 
 void JIT::emitSlow_op_convert_this(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
@@ -1562,16 +1565,26 @@
     unsigned thisRegister = currentInstruction[1].u.operand;
 
     linkSlowCase(iter);
-    Jump isNotUndefined = branch32(NotEqual, regT1, TrustedImm32(JSValue::UndefinedTag));
+    if (shouldEmitProfiling()) {
+        move(TrustedImm32(JSValue::UndefinedTag), regT1);
+        move(TrustedImm32(0), regT0);
+    }
+    Jump isNotUndefined = branch32(NotEqual, regT3, TrustedImm32(JSValue::UndefinedTag));
+    emitValueProfilingSite();
     move(TrustedImmPtr(globalThis), regT0);
     move(TrustedImm32(JSValue::CellTag), regT1);
     emitStore(thisRegister, regT1, regT0);
     emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_convert_this));
 
+    linkSlowCase(iter);
+    if (shouldEmitProfiling()) {
+        move(TrustedImm32(JSValue::CellTag), regT1);
+        move(TrustedImmPtr(m_globalData->stringStructure.get()), regT0);
+    }
     isNotUndefined.link(this);
-    linkSlowCase(iter);
+    emitValueProfilingSite();
     JITStubCall stubCall(this, cti_op_convert_this);
-    stubCall.addArgument(regT1, regT0);
+    stubCall.addArgument(regT3, regT2);
     stubCall.call(thisRegister);
 }
 

Modified: trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp (118554 => 118555)


--- trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2012-05-25 20:11:42 UTC (rev 118554)
+++ trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2012-05-25 20:19:55 UTC (rev 118555)
@@ -467,6 +467,8 @@
     LLINT_BEGIN();
     JSValue v1 = LLINT_OP(1).jsValue();
     ASSERT(v1.isPrimitive());
+    pc[OPCODE_LENGTH(op_convert_this) - 1].u.profile->m_buckets[0] =
+        JSValue::encode(v1.structureOrUndefined());
     LLINT_RETURN(v1.toThisObject(exec));
 }
 

Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm (118554 => 118555)


--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm	2012-05-25 20:11:42 UTC (rev 118554)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm	2012-05-25 20:19:55 UTC (rev 118555)
@@ -364,11 +364,13 @@
     loadi PayloadOffset[cfr, t0, 8], t0
     loadp JSCell::m_structure[t0], t0
     bbb Structure::m_typeInfo + TypeInfo::m_type[t0], ObjectType, .opConvertThisSlow
-    dispatch(2)
+    loadi 8[PC], t1
+    valueProfile(CellTag, t0, t1)
+    dispatch(3)
 
 .opConvertThisSlow:
     callSlowPath(_llint_slow_path_convert_this)
-    dispatch(2)
+    dispatch(3)
 
 
 _llint_op_new_object:

Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm (118554 => 118555)


--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2012-05-25 20:11:42 UTC (rev 118554)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2012-05-25 20:19:55 UTC (rev 118555)
@@ -241,11 +241,13 @@
     btpnz t0, tagMask, .opConvertThisSlow
     loadp JSCell::m_structure[t0], t0
     bbb Structure::m_typeInfo + TypeInfo::m_type[t0], ObjectType, .opConvertThisSlow
-    dispatch(2)
+    loadp 16[PB, PC, 8], t1
+    valueProfile(t0, t1)
+    dispatch(3)
 
 .opConvertThisSlow:
     callSlowPath(_llint_slow_path_convert_this)
-    dispatch(2)
+    dispatch(3)
 
 
 _llint_op_new_object:

Modified: trunk/Source/_javascript_Core/runtime/JSValue.h (118554 => 118555)


--- trunk/Source/_javascript_Core/runtime/JSValue.h	2012-05-25 20:11:42 UTC (rev 118554)
+++ trunk/Source/_javascript_Core/runtime/JSValue.h	2012-05-25 20:19:55 UTC (rev 118555)
@@ -239,6 +239,8 @@
         bool isCell() const;
         JSCell* asCell() const;
         JS_EXPORT_PRIVATE bool isValidCallee();
+        
+        JSValue structureOrUndefined() const;
 
         char* description() const;
 

Modified: trunk/Source/_javascript_Core/runtime/Structure.h (118554 => 118555)


--- trunk/Source/_javascript_Core/runtime/Structure.h	2012-05-25 20:11:42 UTC (rev 118554)
+++ trunk/Source/_javascript_Core/runtime/Structure.h	2012-05-25 20:19:55 UTC (rev 118555)
@@ -332,6 +332,13 @@
         return entry ? entry->offset : notFound;
     }
     
+    inline JSValue JSValue::structureOrUndefined() const
+    {
+        if (isCell())
+            return JSValue(asCell()->structure());
+        return jsUndefined();
+    }
+
     inline bool JSCell::isObject() const
     {
         return m_structure->isObject();
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to