diff options
Diffstat (limited to 'Source/JavaScriptCore/bytecode/ValueProfile.h')
-rw-r--r-- | Source/JavaScriptCore/bytecode/ValueProfile.h | 107 |
1 files changed, 66 insertions, 41 deletions
diff --git a/Source/JavaScriptCore/bytecode/ValueProfile.h b/Source/JavaScriptCore/bytecode/ValueProfile.h index 028c1f696..48b47da7c 100644 --- a/Source/JavaScriptCore/bytecode/ValueProfile.h +++ b/Source/JavaScriptCore/bytecode/ValueProfile.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2011, 2012, 2013 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,7 +10,7 @@ * 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. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * 3. Neither the name of Apple Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * @@ -29,10 +29,7 @@ #ifndef ValueProfile_h #define ValueProfile_h -#include <wtf/Platform.h> - -#if ENABLE(VALUE_PROFILER) - +#include "ConcurrentJITLock.h" #include "Heap.h" #include "JSArray.h" #include "SpeculatedType.h" @@ -54,7 +51,6 @@ struct ValueProfileBase { : m_bytecodeOffset(-1) , m_prediction(SpecNone) , m_numberOfSamplesInPrediction(0) - , m_singletonValueIsTop(false) { for (unsigned i = 0; i < totalNumberOfBuckets; ++i) m_buckets[i] = JSValue::encode(JSValue()); @@ -64,7 +60,6 @@ struct ValueProfileBase { : m_bytecodeOffset(bytecodeOffset) , m_prediction(SpecNone) , m_numberOfSamplesInPrediction(0) - , m_singletonValueIsTop(false) { for (unsigned i = 0; i < totalNumberOfBuckets; ++i) m_buckets[i] = JSValue::encode(JSValue()); @@ -111,28 +106,18 @@ struct ValueProfileBase { return false; } - CString briefDescription() + CString briefDescription(const ConcurrentJITLocker& locker) { - computeUpdatedPrediction(); + computeUpdatedPrediction(locker); StringPrintStream out; - - if (m_singletonValueIsTop) - out.print("predicting ", SpeculationDump(m_prediction)); - else if (m_singletonValue) - out.print("predicting ", m_singletonValue); - + out.print("predicting ", SpeculationDump(m_prediction)); return out.toCString(); } void dump(PrintStream& out) { out.print("samples = ", totalNumberOfSamples(), " prediction = ", SpeculationDump(m_prediction)); - out.printf(", value = "); - if (m_singletonValueIsTop) - out.printf("TOP"); - else - out.print(m_singletonValue); bool first = true; for (unsigned i = 0; i < totalNumberOfBuckets; ++i) { JSValue value = JSValue::decode(m_buckets[i]); @@ -147,8 +132,9 @@ struct ValueProfileBase { } } - // Updates the prediction and returns the new one. - SpeculatedType computeUpdatedPrediction(OperationInProgress operation = NoOperation) + // Updates the prediction and returns the new one. Never call this from any thread + // that isn't executing the code. + SpeculatedType computeUpdatedPrediction(const ConcurrentJITLocker&) { for (unsigned i = 0; i < totalNumberOfBuckets; ++i) { JSValue value = JSValue::decode(m_buckets[i]); @@ -158,23 +144,9 @@ struct ValueProfileBase { m_numberOfSamplesInPrediction++; mergeSpeculation(m_prediction, speculationFromValue(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; } @@ -183,9 +155,6 @@ struct ValueProfileBase { SpeculatedType m_prediction; unsigned m_numberOfSamplesInPrediction; - bool m_singletonValueIsTop; - JSValue m_singletonValue; - EncodedJSValue m_buckets[totalNumberOfBuckets]; }; @@ -237,9 +206,65 @@ inline int getRareCaseProfileBytecodeOffset(RareCaseProfile* rareCaseProfile) return rareCaseProfile->m_bytecodeOffset; } +struct ResultProfile { +private: + static const int numberOfFlagBits = 5; + +public: + ResultProfile(int bytecodeOffset) + : m_bytecodeOffsetAndFlags(bytecodeOffset << numberOfFlagBits) + { + ASSERT(((bytecodeOffset << numberOfFlagBits) >> numberOfFlagBits) == bytecodeOffset); + } + + enum ObservedResults { + NonNegZeroDouble = 1 << 0, + NegZeroDouble = 1 << 1, + NonNumber = 1 << 2, + Int32Overflow = 1 << 3, + Int52Overflow = 1 << 4, + }; + + int bytecodeOffset() const { return m_bytecodeOffsetAndFlags >> numberOfFlagBits; } + unsigned specialFastPathCount() const { return m_specialFastPathCount; } + + bool didObserveNonInt32() const { return hasBits(NonNegZeroDouble | NegZeroDouble | NonNumber); } + bool didObserveDouble() const { return hasBits(NonNegZeroDouble | NegZeroDouble); } + bool didObserveNonNegZeroDouble() const { return hasBits(NonNegZeroDouble); } + bool didObserveNegZeroDouble() const { return hasBits(NegZeroDouble); } + bool didObserveNonNumber() const { return hasBits(NonNumber); } + bool didObserveInt32Overflow() const { return hasBits(Int32Overflow); } + bool didObserveInt52Overflow() const { return hasBits(Int52Overflow); } + + void setObservedNonNegZeroDouble() { setBit(NonNegZeroDouble); } + void setObservedNegZeroDouble() { setBit(NegZeroDouble); } + void setObservedNonNumber() { setBit(NonNumber); } + void setObservedInt32Overflow() { setBit(Int32Overflow); } + void setObservedInt52Overflow() { setBit(Int52Overflow); } + + void* addressOfFlags() { return &m_bytecodeOffsetAndFlags; } + void* addressOfSpecialFastPathCount() { return &m_specialFastPathCount; } + +private: + bool hasBits(int mask) const { return m_bytecodeOffsetAndFlags & mask; } + void setBit(int mask) { m_bytecodeOffsetAndFlags |= mask; } + + int m_bytecodeOffsetAndFlags; + unsigned m_specialFastPathCount { 0 }; +}; + +inline int getResultProfileBytecodeOffset(ResultProfile* profile) +{ + return profile->bytecodeOffset(); +} + } // namespace JSC -#endif // ENABLE(VALUE_PROFILER) +namespace WTF { + +void printInternal(PrintStream&, const JSC::ResultProfile&); + +} // namespace WTF #endif // ValueProfile_h |