diff options
Diffstat (limited to 'JavaScriptCore/interpreter')
| -rw-r--r-- | JavaScriptCore/interpreter/CallFrame.h | 1 | ||||
| -rw-r--r-- | JavaScriptCore/interpreter/Interpreter.cpp | 419 | ||||
| -rw-r--r-- | JavaScriptCore/interpreter/Interpreter.h | 235 | ||||
| -rw-r--r-- | JavaScriptCore/interpreter/Register.h | 3 | ||||
| -rw-r--r-- | JavaScriptCore/interpreter/RegisterFile.h | 139 |
5 files changed, 111 insertions, 686 deletions
diff --git a/JavaScriptCore/interpreter/CallFrame.h b/JavaScriptCore/interpreter/CallFrame.h index d6b9b79..10d0b99 100644 --- a/JavaScriptCore/interpreter/CallFrame.h +++ b/JavaScriptCore/interpreter/CallFrame.h @@ -97,6 +97,7 @@ namespace JSC { friend class JSActivation; friend class JSGlobalObject; friend class Interpreter; + friend class JITStubs; static CallFrame* create(Register* callFrameBase) { return static_cast<CallFrame*>(callFrameBase); } Register* registers() { return this; } diff --git a/JavaScriptCore/interpreter/Interpreter.cpp b/JavaScriptCore/interpreter/Interpreter.cpp index 135c42f..8178d15 100644 --- a/JavaScriptCore/interpreter/Interpreter.cpp +++ b/JavaScriptCore/interpreter/Interpreter.cpp @@ -66,29 +66,10 @@ #include "AssemblerBuffer.h" #endif -#if PLATFORM(DARWIN) -#include <mach/mach.h> -#endif - -#if HAVE(SYS_TIME_H) -#include <sys/time.h> -#endif - -#if PLATFORM(WIN_OS) -#include <windows.h> -#endif - -#if PLATFORM(QT) -#include <QDateTime> -#endif - using namespace std; namespace JSC { -// Preferred number of milliseconds between each timeout check -static const int preferredScriptCheckTimeInterval = 1000; - static ALWAYS_INLINE unsigned bytecodeOffsetForPC(CallFrame* callFrame, CodeBlock* codeBlock, void* pc) { #if ENABLE(JIT) @@ -107,162 +88,6 @@ static int depth(CodeBlock* codeBlock, ScopeChain& sc) return sc.localDepth(); } -static inline bool jsLess(CallFrame* callFrame, JSValuePtr v1, JSValuePtr v2) -{ - if (JSValuePtr::areBothInt32Fast(v1, v2)) - return v1.getInt32Fast() < v2.getInt32Fast(); - - double n1; - double n2; - if (v1.getNumber(n1) && v2.getNumber(n2)) - return n1 < n2; - - Interpreter* interpreter = callFrame->interpreter(); - if (interpreter->isJSString(v1) && interpreter->isJSString(v2)) - return asString(v1)->value() < asString(v2)->value(); - - JSValuePtr p1; - JSValuePtr p2; - bool wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1); - bool wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2); - - if (wasNotString1 | wasNotString2) - return n1 < n2; - - return asString(p1)->value() < asString(p2)->value(); -} - -static inline bool jsLessEq(CallFrame* callFrame, JSValuePtr v1, JSValuePtr v2) -{ - if (JSValuePtr::areBothInt32Fast(v1, v2)) - return v1.getInt32Fast() <= v2.getInt32Fast(); - - double n1; - double n2; - if (v1.getNumber(n1) && v2.getNumber(n2)) - return n1 <= n2; - - Interpreter* interpreter = callFrame->interpreter(); - if (interpreter->isJSString(v1) && interpreter->isJSString(v2)) - return !(asString(v2)->value() < asString(v1)->value()); - - JSValuePtr p1; - JSValuePtr p2; - bool wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1); - bool wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2); - - if (wasNotString1 | wasNotString2) - return n1 <= n2; - - return !(asString(p2)->value() < asString(p1)->value()); -} - -static NEVER_INLINE JSValuePtr jsAddSlowCase(CallFrame* callFrame, JSValuePtr v1, JSValuePtr v2) -{ - // exception for the Date exception in defaultValue() - JSValuePtr p1 = v1.toPrimitive(callFrame); - JSValuePtr p2 = v2.toPrimitive(callFrame); - - if (p1.isString() || p2.isString()) { - RefPtr<UString::Rep> value = concatenate(p1.toString(callFrame).rep(), p2.toString(callFrame).rep()); - if (!value) - return throwOutOfMemoryError(callFrame); - return jsString(callFrame, value.release()); - } - - return jsNumber(callFrame, p1.toNumber(callFrame) + p2.toNumber(callFrame)); -} - -// Fast-path choices here are based on frequency data from SunSpider: -// <times> Add case: <t1> <t2> -// --------------------------- -// 5626160 Add case: 3 3 (of these, 3637690 are for immediate values) -// 247412 Add case: 5 5 -// 20900 Add case: 5 6 -// 13962 Add case: 5 3 -// 4000 Add case: 3 5 - -static ALWAYS_INLINE JSValuePtr jsAdd(CallFrame* callFrame, JSValuePtr v1, JSValuePtr v2) -{ - double left; - double right = 0.0; - - bool rightIsNumber = v2.getNumber(right); - if (rightIsNumber && v1.getNumber(left)) - return jsNumber(callFrame, left + right); - - bool leftIsString = v1.isString(); - if (leftIsString && v2.isString()) { - RefPtr<UString::Rep> value = concatenate(asString(v1)->value().rep(), asString(v2)->value().rep()); - if (!value) - return throwOutOfMemoryError(callFrame); - return jsString(callFrame, value.release()); - } - - if (rightIsNumber & leftIsString) { - RefPtr<UString::Rep> value = v2.isInt32Fast() ? - concatenate(asString(v1)->value().rep(), v2.getInt32Fast()) : - concatenate(asString(v1)->value().rep(), right); - - if (!value) - return throwOutOfMemoryError(callFrame); - return jsString(callFrame, value.release()); - } - - // All other cases are pretty uncommon - return jsAddSlowCase(callFrame, v1, v2); -} - -static JSValuePtr jsTypeStringForValue(CallFrame* callFrame, JSValuePtr v) -{ - if (v.isUndefined()) - return jsNontrivialString(callFrame, "undefined"); - if (v.isBoolean()) - return jsNontrivialString(callFrame, "boolean"); - if (v.isNumber()) - return jsNontrivialString(callFrame, "number"); - if (v.isString()) - return jsNontrivialString(callFrame, "string"); - if (v.isObject()) { - // Return "undefined" for objects that should be treated - // as null when doing comparisons. - if (asObject(v)->structure()->typeInfo().masqueradesAsUndefined()) - return jsNontrivialString(callFrame, "undefined"); - CallData callData; - if (asObject(v)->getCallData(callData) != CallTypeNone) - return jsNontrivialString(callFrame, "function"); - } - return jsNontrivialString(callFrame, "object"); -} - -static bool jsIsObjectType(JSValuePtr v) -{ - if (!v.isCell()) - return v.isNull(); - - JSType type = asCell(v)->structure()->typeInfo().type(); - if (type == NumberType || type == StringType) - return false; - if (type == ObjectType) { - if (asObject(v)->structure()->typeInfo().masqueradesAsUndefined()) - return false; - CallData callData; - if (asObject(v)->getCallData(callData) != CallTypeNone) - return false; - } - return true; -} - -static bool jsIsFunctionType(JSValuePtr v) -{ - if (v.isObject()) { - CallData callData; - if (asObject(v)->getCallData(callData) != CallTypeNone) - return true; - } - return false; -} - NEVER_INLINE bool Interpreter::resolve(CallFrame* callFrame, Instruction* vPC, JSValuePtr& exceptionValue) { int dst = (vPC + 1)->u.operand; @@ -364,34 +189,11 @@ NEVER_INLINE bool Interpreter::resolveGlobal(CallFrame* callFrame, Instruction* return false; } -static ALWAYS_INLINE JSValuePtr inlineResolveBase(CallFrame* callFrame, Identifier& property, ScopeChainNode* scopeChain) -{ - ScopeChainIterator iter = scopeChain->begin(); - ScopeChainIterator next = iter; - ++next; - ScopeChainIterator end = scopeChain->end(); - ASSERT(iter != end); - - PropertySlot slot; - JSObject* base; - while (true) { - base = *iter; - if (next == end || base->getPropertySlot(callFrame, property, slot)) - return base; - - iter = next; - ++next; - } - - ASSERT_NOT_REACHED(); - return noValue(); -} - NEVER_INLINE void Interpreter::resolveBase(CallFrame* callFrame, Instruction* vPC) { int dst = (vPC + 1)->u.operand; int property = (vPC + 2)->u.operand; - callFrame[dst] = JSValuePtr(inlineResolveBase(callFrame, callFrame->codeBlock()->identifier(property), callFrame->scopeChain())); + callFrame[dst] = JSValuePtr(JSC::resolveBase(callFrame, callFrame->codeBlock()->identifier(property), callFrame->scopeChain())); } NEVER_INLINE bool Interpreter::resolveBaseAndProperty(CallFrame* callFrame, Instruction* vPC, JSValuePtr& exceptionValue) @@ -545,56 +347,9 @@ NEVER_INLINE JSValuePtr Interpreter::callEval(CallFrame* callFrame, RegisterFile Interpreter::Interpreter() : m_sampler(0) -#if ENABLE(JIT) - , m_ctiArrayLengthTrampoline(0) - , m_ctiStringLengthTrampoline(0) - , m_ctiVirtualCallPreLink(0) - , m_ctiVirtualCallLink(0) - , m_ctiVirtualCall(0) -#endif , m_reentryDepth(0) - , m_timeoutTime(0) - , m_timeAtLastCheckTimeout(0) - , m_timeExecuting(0) - , m_timeoutCheckCount(0) - , m_ticksUntilNextTimeoutCheck(initialTickCountThreshold) { - initTimeout(); privateExecute(InitializeAndReturn, 0, 0, 0); - - // Bizarrely, calling fastMalloc here is faster than allocating space on the stack. - void* storage = fastMalloc(sizeof(CollectorBlock)); - - JSCell* jsArray = new (storage) JSArray(JSArray::createStructure(jsNull())); - m_jsArrayVptr = jsArray->vptr(); - jsArray->~JSCell(); - - JSCell* jsByteArray = new (storage) JSByteArray(JSByteArray::VPtrStealingHack); - m_jsByteArrayVptr = jsByteArray->vptr(); - jsByteArray->~JSCell(); - - JSCell* jsString = new (storage) JSString(JSString::VPtrStealingHack); - m_jsStringVptr = jsString->vptr(); - jsString->~JSCell(); - - JSCell* jsFunction = new (storage) JSFunction(JSFunction::createStructure(jsNull())); - m_jsFunctionVptr = jsFunction->vptr(); - jsFunction->~JSCell(); - - fastFree(storage); -} - -void Interpreter::initialize(JSGlobalData* globalData) -{ -#if ENABLE(JIT) - JIT::compileCTIMachineTrampolines(globalData); -#else - UNUSED_PARAM(globalData); -#endif -} - -Interpreter::~Interpreter() -{ } #ifndef NDEBUG @@ -865,7 +620,7 @@ JSValuePtr Interpreter::execute(ProgramNode* programNode, CallFrame* callFrame, #if ENABLE(JIT) if (!codeBlock->jitCode()) JIT::compile(scopeChain->globalData, codeBlock); - result = JIT::execute(codeBlock->jitCode(), &m_registerFile, newCallFrame, scopeChain->globalData, exception); + result = codeBlock->jitCode().execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception); #else result = privateExecute(Normal, &m_registerFile, newCallFrame, exception); #endif @@ -931,7 +686,7 @@ JSValuePtr Interpreter::execute(FunctionBodyNode* functionBodyNode, CallFrame* c #if ENABLE(JIT) if (!codeBlock->jitCode()) JIT::compile(scopeChain->globalData, codeBlock); - result = JIT::execute(codeBlock->jitCode(), &m_registerFile, newCallFrame, scopeChain->globalData, exception); + result = codeBlock->jitCode().execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception); #else result = privateExecute(Normal, &m_registerFile, newCallFrame, exception); #endif @@ -1023,7 +778,7 @@ JSValuePtr Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObje #if ENABLE(JIT) if (!codeBlock->jitCode()) JIT::compile(scopeChain->globalData, codeBlock); - result = JIT::execute(codeBlock->jitCode(), &m_registerFile, newCallFrame, scopeChain->globalData, exception); + result = codeBlock->jitCode().execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception); #else result = privateExecute(Normal, &m_registerFile, newCallFrame, exception); #endif @@ -1065,93 +820,6 @@ NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHook } } -void Interpreter::resetTimeoutCheck() -{ - m_ticksUntilNextTimeoutCheck = initialTickCountThreshold; - m_timeAtLastCheckTimeout = 0; - m_timeExecuting = 0; -} - -// Returns the time the current thread has spent executing, in milliseconds. -static inline unsigned getCPUTime() -{ -#if PLATFORM(DARWIN) - mach_msg_type_number_t infoCount = THREAD_BASIC_INFO_COUNT; - thread_basic_info_data_t info; - - // Get thread information - mach_port_t threadPort = mach_thread_self(); - thread_info(threadPort, THREAD_BASIC_INFO, reinterpret_cast<thread_info_t>(&info), &infoCount); - mach_port_deallocate(mach_task_self(), threadPort); - - unsigned time = info.user_time.seconds * 1000 + info.user_time.microseconds / 1000; - time += info.system_time.seconds * 1000 + info.system_time.microseconds / 1000; - - return time; -#elif HAVE(SYS_TIME_H) - // FIXME: This should probably use getrusage with the RUSAGE_THREAD flag. - struct timeval tv; - gettimeofday(&tv, 0); - return tv.tv_sec * 1000 + tv.tv_usec / 1000; -#elif PLATFORM(QT) - QDateTime t = QDateTime::currentDateTime(); - return t.toTime_t() * 1000 + t.time().msec(); -#elif PLATFORM(WIN_OS) - union { - FILETIME fileTime; - unsigned long long fileTimeAsLong; - } userTime, kernelTime; - - // GetThreadTimes won't accept NULL arguments so we pass these even though - // they're not used. - FILETIME creationTime, exitTime; - - GetThreadTimes(GetCurrentThread(), &creationTime, &exitTime, &kernelTime.fileTime, &userTime.fileTime); - - return userTime.fileTimeAsLong / 10000 + kernelTime.fileTimeAsLong / 10000; -#else -#error Platform does not have getCurrentTime function -#endif -} - -// We have to return a JSValue here, gcc seems to produce worse code if -// we attempt to return a bool -ALWAYS_INLINE bool Interpreter::checkTimeout(JSGlobalObject* globalObject) -{ - unsigned currentTime = getCPUTime(); - - if (!m_timeAtLastCheckTimeout) { - // Suspicious amount of looping in a script -- start timing it - m_timeAtLastCheckTimeout = currentTime; - return false; - } - - unsigned timeDiff = currentTime - m_timeAtLastCheckTimeout; - - if (timeDiff == 0) - timeDiff = 1; - - m_timeExecuting += timeDiff; - m_timeAtLastCheckTimeout = currentTime; - - // Adjust the tick threshold so we get the next checkTimeout call in the interval specified in - // preferredScriptCheckTimeInterval - m_ticksUntilNextTimeoutCheck = static_cast<unsigned>((static_cast<float>(preferredScriptCheckTimeInterval) / timeDiff) * m_ticksUntilNextTimeoutCheck); - // If the new threshold is 0 reset it to the default threshold. This can happen if the timeDiff is higher than the - // preferred script check time interval. - if (m_ticksUntilNextTimeoutCheck == 0) - m_ticksUntilNextTimeoutCheck = initialTickCountThreshold; - - if (m_timeoutTime && m_timeExecuting > m_timeoutTime) { - if (globalObject->shouldInterruptScript()) - return true; - - resetTimeoutCheck(); - } - - return false; -} - NEVER_INLINE ScopeChainNode* Interpreter::createExceptionScope(CallFrame* callFrame, const Instruction* vPC) { int dst = (++vPC)->u.operand; @@ -1251,37 +919,6 @@ NEVER_INLINE void Interpreter::uncachePutByID(CodeBlock* codeBlock, Instruction* vPC[4] = 0; } -static size_t countPrototypeChainEntriesAndCheckForProxies(CallFrame* callFrame, JSValuePtr baseValue, const PropertySlot& slot) -{ - JSCell* cell = asCell(baseValue); - size_t count = 0; - - while (slot.slotBase() != cell) { - JSValuePtr v = cell->structure()->prototypeForLookup(callFrame); - - // If we didn't find slotBase in baseValue's prototype chain, then baseValue - // must be a proxy for another object. - - if (v.isNull()) - return 0; - - cell = asCell(v); - - // Since we're accessing a prototype in a loop, it's a good bet that it - // should not be treated as a dictionary. - if (cell->structure()->isDictionary()) { - RefPtr<Structure> transition = Structure::fromDictionaryTransition(cell->structure()); - asObject(cell)->setStructure(transition.release()); - cell->structure()->setCachedPrototypeChain(0); - } - - ++count; - } - - ASSERT(count); - return count; -} - NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* vPC, JSValuePtr baseValue, const Identifier& propertyName, const PropertySlot& slot) { // Recursive invocation may already have specialized this instruction. @@ -1294,12 +931,13 @@ NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock* return; } - if (isJSArray(baseValue) && propertyName == callFrame->propertyNames().length) { + JSGlobalData* globalData = &callFrame->globalData(); + if (isJSArray(globalData, baseValue) && propertyName == callFrame->propertyNames().length) { vPC[0] = getOpcode(op_get_array_length); return; } - if (isJSString(baseValue) && propertyName == callFrame->propertyNames().length) { + if (isJSString(globalData, baseValue) && propertyName == callFrame->propertyNames().length) { vPC[0] = getOpcode(op_get_string_length); return; } @@ -1417,7 +1055,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe Instruction* vPC = callFrame->codeBlock()->instructions().begin(); Profiler** enabledProfilerReference = Profiler::enabledProfilerReference(); - unsigned tickCount = m_ticksUntilNextTimeoutCheck + 1; + unsigned tickCount = globalData->timeoutChecker.ticksUntilNextCheck(); #define CHECK_FOR_EXCEPTION() \ do { \ @@ -1433,19 +1071,17 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe #define CHECK_FOR_TIMEOUT() \ if (!--tickCount) { \ - if (checkTimeout(callFrame->dynamicGlobalObject())) { \ + if (globalData->timeoutChecker.didTimeOut(callFrame)) { \ exceptionValue = jsNull(); \ goto vm_throw; \ } \ - tickCount = m_ticksUntilNextTimeoutCheck; \ + tickCount = globalData->timeoutChecker.ticksUntilNextCheck(); \ } #if ENABLE(OPCODE_SAMPLING) #define SAMPLE(codeBlock, vPC) m_sampler->sample(codeBlock, vPC) - #define CTI_SAMPLER ARG_globalData->interpreter->sampler() #else #define SAMPLE(codeBlock, vPC) - #define CTI_SAMPLER 0 #endif #if HAVE(COMPUTED_GOTO) @@ -2123,7 +1759,12 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe goto vm_throw; JSObject* baseObj = asObject(baseVal); - callFrame[dst] = jsBoolean(baseObj->structure()->typeInfo().implementsHasInstance() ? baseObj->hasInstance(callFrame, callFrame[value].jsValue(callFrame), callFrame[baseProto].jsValue(callFrame)) : false); + if (baseObj->structure()->typeInfo().implementsHasInstance()) { + bool result = baseObj->hasInstance(callFrame, callFrame[value].jsValue(callFrame), callFrame[baseProto].jsValue(callFrame)); + CHECK_FOR_EXCEPTION(); + callFrame[dst] = jsBoolean(result); + } else + callFrame[dst] = jsBoolean(false); vPC += 5; NEXT_INSTRUCTION(); @@ -2607,7 +2248,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe int base = vPC[2].u.operand; JSValuePtr baseValue = callFrame[base].jsValue(callFrame); - if (LIKELY(isJSArray(baseValue))) { + if (LIKELY(isJSArray(globalData, baseValue))) { int dst = vPC[1].u.operand; callFrame[dst] = JSValuePtr(jsNumber(callFrame, asArray(baseValue)->length())); vPC += 8; @@ -2627,7 +2268,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe int base = vPC[2].u.operand; JSValuePtr baseValue = callFrame[base].jsValue(callFrame); - if (LIKELY(isJSString(baseValue))) { + if (LIKELY(isJSString(globalData, baseValue))) { int dst = vPC[1].u.operand; callFrame[dst] = JSValuePtr(jsNumber(callFrame, asString(baseValue)->value().size())); vPC += 8; @@ -2809,15 +2450,15 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe if (LIKELY(subscript.isUInt32Fast())) { uint32_t i = subscript.getUInt32Fast(); - if (isJSArray(baseValue)) { + if (isJSArray(globalData, baseValue)) { JSArray* jsArray = asArray(baseValue); if (jsArray->canGetIndex(i)) result = jsArray->getIndex(i); else result = jsArray->JSArray::get(callFrame, i); - } else if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i)) + } else if (isJSString(globalData, baseValue) && asString(baseValue)->canGetIndex(i)) result = asString(baseValue)->getIndex(&callFrame->globalData(), i); - else if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) + else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) result = asByteArray(baseValue)->getIndex(callFrame, i); else result = baseValue.get(callFrame, i); @@ -2851,13 +2492,13 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe if (LIKELY(subscript.isUInt32Fast())) { uint32_t i = subscript.getUInt32Fast(); - if (isJSArray(baseValue)) { + if (isJSArray(globalData, baseValue)) { JSArray* jsArray = asArray(baseValue); if (jsArray->canSetIndex(i)) jsArray->setIndex(i, callFrame[value].jsValue(callFrame)); else jsArray->JSArray::put(callFrame, i, callFrame[value].jsValue(callFrame)); - } else if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) { + } else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) { JSByteArray* jsByteArray = asByteArray(baseValue); double dValue = 0; JSValuePtr jsValue = callFrame[value].jsValue(callFrame); @@ -3144,9 +2785,10 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe if (scrutinee.isInt32Fast()) vPC += callFrame->codeBlock()->immediateSwitchJumpTable(tableIndex).offsetForValue(scrutinee.getInt32Fast(), defaultOffset); else { - int32_t value; - if (scrutinee.numberToInt32(value)) - vPC += callFrame->codeBlock()->immediateSwitchJumpTable(tableIndex).offsetForValue(value, defaultOffset); + double value; + int32_t intValue; + if (scrutinee.getNumber(value) && ((intValue = static_cast<int32_t>(value)) == value)) + vPC += callFrame->codeBlock()->immediateSwitchJumpTable(tableIndex).offsetForValue(intValue, defaultOffset); else vPC += defaultOffset; } @@ -3591,7 +3233,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe the object in register override to register dst. */ - int dst = vPC[1].u.operand;; + int dst = vPC[1].u.operand; if (LIKELY(callFrame[dst].jsValue(callFrame).isObject())) { vPC += 3; NEXT_INSTRUCTION(); @@ -3711,7 +3353,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe DEFINE_OPCODE(op_catch) { /* catch ex(r) - Retrieves the VMs current exception and puts it in register + Retrieves the VM's current exception and puts it in register ex. This is only valid after an exception has been raised, and usually forms the beginning of an exception handler. */ @@ -4004,6 +3646,7 @@ CallFrame* Interpreter::findFunctionCallFrame(CallFrame* callFrame, InternalFunc return 0; } +#ifdef MANUAL_MERGE_REQUIRED #if ENABLE(JIT) #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) @@ -6137,4 +5780,6 @@ JSValueEncodedAsPointer* Interpreter::cti_vm_throw(STUB_ARGS) #endif // ENABLE(JIT) +#else // MANUAL_MERGE_REQUIRED +#endif // MANUAL_MERGE_REQUIRED } // namespace JSC diff --git a/JavaScriptCore/interpreter/Interpreter.h b/JavaScriptCore/interpreter/Interpreter.h index 18c2185..7d97962 100644 --- a/JavaScriptCore/interpreter/Interpreter.h +++ b/JavaScriptCore/interpreter/Interpreter.h @@ -32,6 +32,7 @@ #include "ArgList.h" #include "JSCell.h" #include "JSValue.h" +#include "JSObject.h" #include "Opcode.h" #include "RegisterFile.h" #include <wtf/HashMap.h> @@ -56,52 +57,6 @@ namespace JSC { class SamplingTool; struct HandlerInfo; -#if ENABLE(JIT) - -#if USE(JIT_STUB_ARGUMENT_VA_LIST) - #define STUB_ARGS void* args, ... - #define ARGS (reinterpret_cast<void**>(vl_args) - 1) -#else // JIT_STUB_ARGUMENT_REGISTER or JIT_STUB_ARGUMENT_STACK - #define STUB_ARGS void** args - #define ARGS (args) -#endif - -#if USE(JIT_STUB_ARGUMENT_REGISTER) - #if PLATFORM(X86_64) - #define JIT_STUB - #elif COMPILER(MSVC) - #define JIT_STUB __fastcall - #elif COMPILER(GCC) - #define JIT_STUB __attribute__ ((fastcall)) - #else - #error Need to support register calling convention in this compiler - #endif -#else // JIT_STUB_ARGUMENT_VA_LIST or JIT_STUB_ARGUMENT_STACK - #if COMPILER(MSVC) - #define JIT_STUB __cdecl - #else - #define JIT_STUB - #endif -#endif - -// The Mac compilers are fine with this, -#if PLATFORM(MAC) - struct VoidPtrPair { - void* first; - void* second; - }; -#define RETURN_PAIR(a,b) VoidPtrPair pair = { a, b }; return pair -#else - typedef uint64_t VoidPtrPair; - union VoidPtrPairValue { - struct { void* first; void* second; } s; - VoidPtrPair i; - }; -#define RETURN_PAIR(a,b) VoidPtrPairValue pair = {{ a, b }}; return pair.i -#endif - -#endif // ENABLE(JIT) - enum DebugHookID { WillExecuteProgram, DidExecuteProgram, @@ -111,16 +66,15 @@ namespace JSC { WillExecuteStatement }; - enum { MaxReentryDepth = 128 }; + enum { MaxReentryDepth = 64 }; class Interpreter { friend class JIT; + friend class JITStubs; + public: Interpreter(); - ~Interpreter(); - void initialize(JSGlobalData*); - RegisterFile& registerFile() { return m_registerFile; } Opcode getOpcode(OpcodeID id) @@ -153,161 +107,9 @@ namespace JSC { void retrieveLastCaller(CallFrame*, int& lineNumber, intptr_t& sourceID, UString& sourceURL, JSValuePtr& function) const; void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc); - void setTimeoutTime(unsigned timeoutTime) { m_timeoutTime = timeoutTime; } - - void startTimeoutCheck() - { - if (!m_timeoutCheckCount) - resetTimeoutCheck(); -#ifdef ANDROID_INSTRUMENT - if (!m_timeoutCheckCount) - android::TimeCounter::start(android::TimeCounter::JavaScriptTimeCounter); -#endif - - ++m_timeoutCheckCount; - } - - void stopTimeoutCheck() - { - ASSERT(m_timeoutCheckCount); - --m_timeoutCheckCount; -#ifdef ANDROID_INSTRUMENT - if (!m_timeoutCheckCount) - android::TimeCounter::record(android::TimeCounter::JavaScriptTimeCounter, __FUNCTION__); -#endif - } - - inline void initTimeout() - { - ASSERT(!m_timeoutCheckCount); - resetTimeoutCheck(); - m_timeoutTime = 0; - m_timeoutCheckCount = 0; - } - void setSampler(SamplingTool* sampler) { m_sampler = sampler; } SamplingTool* sampler() { return m_sampler; } -#if ENABLE(JIT) - - static int JIT_STUB cti_timeout_check(STUB_ARGS); - static void JIT_STUB cti_register_file_check(STUB_ARGS); - - static JSObject* JIT_STUB cti_op_convert_this(STUB_ARGS); - static void JIT_STUB cti_op_end(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_add(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_pre_inc(STUB_ARGS); - static int JIT_STUB cti_op_loop_if_less(STUB_ARGS); - static int JIT_STUB cti_op_loop_if_lesseq(STUB_ARGS); - static JSObject* JIT_STUB cti_op_new_object(STUB_ARGS); - static void JIT_STUB cti_op_put_by_id(STUB_ARGS); - static void JIT_STUB cti_op_put_by_id_second(STUB_ARGS); - static void JIT_STUB cti_op_put_by_id_generic(STUB_ARGS); - static void JIT_STUB cti_op_put_by_id_fail(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_get_by_id(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_get_by_id_second(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_get_by_id_generic(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_get_by_id_self_fail(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_get_by_id_proto_list(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_get_by_id_proto_list_full(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_get_by_id_proto_fail(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_get_by_id_array_fail(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_get_by_id_string_fail(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_del_by_id(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_instanceof(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_mul(STUB_ARGS); - static JSObject* JIT_STUB cti_op_new_func(STUB_ARGS); - static void* JIT_STUB cti_op_call_JSFunction(STUB_ARGS); - static VoidPtrPair JIT_STUB cti_op_call_arityCheck(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_call_NotJSFunction(STUB_ARGS); - static void JIT_STUB cti_op_create_arguments(STUB_ARGS); - static void JIT_STUB cti_op_create_arguments_no_params(STUB_ARGS); - static void JIT_STUB cti_op_tear_off_activation(STUB_ARGS); - static void JIT_STUB cti_op_tear_off_arguments(STUB_ARGS); - static void JIT_STUB cti_op_profile_will_call(STUB_ARGS); - static void JIT_STUB cti_op_profile_did_call(STUB_ARGS); - static void JIT_STUB cti_op_ret_scopeChain(STUB_ARGS); - static JSObject* JIT_STUB cti_op_new_array(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_resolve(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_resolve_global(STUB_ARGS); - static JSObject* JIT_STUB cti_op_construct_JSConstruct(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_construct_NotJSConstruct(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_get_by_val(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_get_by_val_byte_array(STUB_ARGS); - static VoidPtrPair JIT_STUB cti_op_resolve_func(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_sub(STUB_ARGS); - static void JIT_STUB cti_op_put_by_val(STUB_ARGS); - static void JIT_STUB cti_op_put_by_val_array(STUB_ARGS); - static void JIT_STUB cti_op_put_by_val_byte_array(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_lesseq(STUB_ARGS); - static int JIT_STUB cti_op_loop_if_true(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_resolve_base(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_negate(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_resolve_skip(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_div(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_pre_dec(STUB_ARGS); - static int JIT_STUB cti_op_jless(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_not(STUB_ARGS); - static int JIT_STUB cti_op_jtrue(STUB_ARGS); - static VoidPtrPair JIT_STUB cti_op_post_inc(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_eq(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_lshift(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_bitand(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_rshift(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_bitnot(STUB_ARGS); - static VoidPtrPair JIT_STUB cti_op_resolve_with_base(STUB_ARGS); - static JSObject* JIT_STUB cti_op_new_func_exp(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_mod(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_less(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_neq(STUB_ARGS); - static VoidPtrPair JIT_STUB cti_op_post_dec(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_urshift(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_bitxor(STUB_ARGS); - static JSObject* JIT_STUB cti_op_new_regexp(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_bitor(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_call_eval(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_throw(STUB_ARGS); - static JSPropertyNameIterator* JIT_STUB cti_op_get_pnames(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_next_pname(STUB_ARGS); - static JSObject* JIT_STUB cti_op_push_scope(STUB_ARGS); - static void JIT_STUB cti_op_pop_scope(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_typeof(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_is_undefined(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_is_boolean(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_is_number(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_is_string(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_is_object(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_is_function(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_stricteq(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_nstricteq(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_to_jsnumber(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_in(STUB_ARGS); - static JSObject* JIT_STUB cti_op_push_new_scope(STUB_ARGS); - static void JIT_STUB cti_op_jmp_scopes(STUB_ARGS); - static void JIT_STUB cti_op_put_by_index(STUB_ARGS); - static void* JIT_STUB cti_op_switch_imm(STUB_ARGS); - static void* JIT_STUB cti_op_switch_char(STUB_ARGS); - static void* JIT_STUB cti_op_switch_string(STUB_ARGS); - static JSValueEncodedAsPointer* JIT_STUB cti_op_del_by_val(STUB_ARGS); - static void JIT_STUB cti_op_put_getter(STUB_ARGS); - static void JIT_STUB cti_op_put_setter(STUB_ARGS); - static JSObject* JIT_STUB cti_op_new_error(STUB_ARGS); - static void JIT_STUB cti_op_debug(STUB_ARGS); - - static JSValueEncodedAsPointer* JIT_STUB cti_vm_throw(STUB_ARGS); - static void* JIT_STUB cti_vm_dontLazyLinkCall(STUB_ARGS); - static void* JIT_STUB cti_vm_lazyLinkCall(STUB_ARGS); - static JSObject* JIT_STUB cti_op_push_activation(STUB_ARGS); - -#endif // ENABLE(JIT) - - // Default number of ticks before a timeout check should be done. - static const int initialTickCountThreshold = 1024; - - bool isJSArray(JSValuePtr v) { return v.isCell() && v.asCell()->vptr() == m_jsArrayVptr; } - bool isJSString(JSValuePtr v) { return v.isCell() && v.asCell()->vptr() == m_jsStringVptr; } - bool isJSByteArray(JSValuePtr v) { return v.isCell() && v.asCell()->vptr() == m_jsByteArrayVptr; } - private: enum ExecutionFlag { Normal, InitializeAndReturn }; @@ -336,9 +138,6 @@ namespace JSC { void dumpCallFrame(CallFrame*); void dumpRegisters(CallFrame*); - bool checkTimeout(JSGlobalObject*); - void resetTimeoutCheck(); - void tryCacheGetByID(CallFrame*, CodeBlock*, Instruction*, JSValuePtr baseValue, const Identifier& propertyName, const PropertySlot&); void uncacheGetByID(CodeBlock*, Instruction* vPC); void tryCachePutByID(CallFrame*, CodeBlock*, Instruction*, JSValuePtr baseValue, const PutPropertySlot&); @@ -346,38 +145,12 @@ namespace JSC { bool isCallBytecode(Opcode opcode) { return opcode == getOpcode(op_call) || opcode == getOpcode(op_construct) || opcode == getOpcode(op_call_eval); } -#if ENABLE(JIT) - static void throwStackOverflowPreviousFrame(CallFrame**, JSGlobalData*, void*& returnAddress); - - void tryCTICacheGetByID(CallFrame*, CodeBlock*, void* returnAddress, JSValuePtr baseValue, const Identifier& propertyName, const PropertySlot&); - void tryCTICachePutByID(CallFrame*, CodeBlock*, void* returnAddress, JSValuePtr baseValue, const PutPropertySlot&); -#endif - SamplingTool* m_sampler; -#if ENABLE(JIT) - RefPtr<ExecutablePool> m_executablePool; - void* m_ctiArrayLengthTrampoline; - void* m_ctiStringLengthTrampoline; - void* m_ctiVirtualCallPreLink; - void* m_ctiVirtualCallLink; - void* m_ctiVirtualCall; -#endif - int m_reentryDepth; - unsigned m_timeoutTime; - unsigned m_timeAtLastCheckTimeout; - unsigned m_timeExecuting; - unsigned m_timeoutCheckCount; - unsigned m_ticksUntilNextTimeoutCheck; RegisterFile m_registerFile; - void* m_jsArrayVptr; - void* m_jsByteArrayVptr; - void* m_jsStringVptr; - void* m_jsFunctionVptr; - #if HAVE(COMPUTED_GOTO) Opcode m_opcodeTable[numOpcodeIDs]; // Maps OpcodeID => Opcode for compiling HashMap<Opcode, OpcodeID> m_opcodeIDTable; // Maps Opcode => OpcodeID for decompiling diff --git a/JavaScriptCore/interpreter/Register.h b/JavaScriptCore/interpreter/Register.h index ff36bbc..5277a0f 100644 --- a/JavaScriptCore/interpreter/Register.h +++ b/JavaScriptCore/interpreter/Register.h @@ -60,8 +60,9 @@ namespace JSC { private: friend class ExecState; friend class Interpreter; + friend class JITStubs; - // Only CallFrame and Interpreter should use these functions. + // Only CallFrame, Interpreter, and JITStubs should use these functions. Register(intptr_t); diff --git a/JavaScriptCore/interpreter/RegisterFile.h b/JavaScriptCore/interpreter/RegisterFile.h index ec190d6..c320f04 100644 --- a/JavaScriptCore/interpreter/RegisterFile.h +++ b/JavaScriptCore/interpreter/RegisterFile.h @@ -29,6 +29,7 @@ #ifndef RegisterFile_h #define RegisterFile_h +#include "ExecutableAllocator.h" #include "Register.h" #include "Collector.h" #include <wtf/Noncopyable.h> @@ -111,48 +112,9 @@ namespace JSC { static const size_t defaultCapacity = 524288; static const size_t defaultMaxGlobals = 8192; - static const size_t allocationSize = 1 << 14; - static const size_t allocationSizeMask = allocationSize - 1; - - RegisterFile(size_t capacity = defaultCapacity, size_t maxGlobals = defaultMaxGlobals) - : m_numGlobals(0) - , m_maxGlobals(maxGlobals) - , m_start(0) - , m_end(0) - , m_max(0) - , m_buffer(0) - , m_globalObject(0) - { - size_t bufferLength = (capacity + maxGlobals) * sizeof(Register); -#if HAVE(MMAP) - m_buffer = static_cast<Register*>(mmap(0, bufferLength, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0)); - if (m_buffer == MAP_FAILED) { - fprintf(stderr, "Could not allocate register file: %d\n", errno); - CRASH(); - } -#elif HAVE(VIRTUALALLOC) - // Ensure bufferLength is a multiple of allocation size - bufferLength = (bufferLength + allocationSizeMask) & ~allocationSizeMask; - m_buffer = static_cast<Register*>(VirtualAlloc(0, bufferLength, MEM_RESERVE, PAGE_READWRITE)); - if (!m_buffer) { - fprintf(stderr, "Could not allocate register file: %d\n", errno); - CRASH(); - } - int initialAllocation = (maxGlobals * sizeof(Register) + allocationSizeMask) & ~allocationSizeMask; - void* commitCheck = VirtualAlloc(m_buffer, initialAllocation, MEM_COMMIT, PAGE_READWRITE); - if (commitCheck != m_buffer) { - fprintf(stderr, "Could not allocate register file: %d\n", errno); - CRASH(); - } - m_maxCommitted = reinterpret_cast<Register*>(reinterpret_cast<char*>(m_buffer) + initialAllocation); -#else - #error "Don't know how to reserve virtual memory on this platform." -#endif - m_start = m_buffer + maxGlobals; - m_end = m_start; - m_max = m_start + capacity; - } + static const size_t commitSize = 1 << 14; + RegisterFile(size_t capacity = defaultCapacity, size_t maxGlobals = defaultMaxGlobals); ~RegisterFile(); Register* start() const { return m_start; } @@ -162,31 +124,8 @@ namespace JSC { void setGlobalObject(JSGlobalObject* globalObject) { m_globalObject = globalObject; } JSGlobalObject* globalObject() { return m_globalObject; } - void shrink(Register* newEnd) - { - if (newEnd < m_end) - m_end = newEnd; - } - - bool grow(Register* newEnd) - { - if (newEnd > m_end) { - if (newEnd > m_max) - return false; -#if !HAVE(MMAP) && HAVE(VIRTUALALLOC) - if (newEnd > m_maxCommitted) { - ptrdiff_t additionalAllocation = ((reinterpret_cast<char*>(newEnd) - reinterpret_cast<char*>(m_maxCommitted)) + allocationSizeMask) & ~allocationSizeMask; - if (!VirtualAlloc(m_maxCommitted, additionalAllocation, MEM_COMMIT, PAGE_READWRITE)) { - fprintf(stderr, "Could not allocate register file: %d\n", errno); - CRASH(); - } - m_maxCommitted = reinterpret_cast<Register*>(reinterpret_cast<char*>(m_maxCommitted) + additionalAllocation); - } -#endif - m_end = newEnd; - } - return true; - } + bool grow(Register* newEnd); + void shrink(Register* newEnd); void setNumGlobals(size_t numGlobals) { m_numGlobals = numGlobals; } int numGlobals() const { return m_numGlobals; } @@ -205,12 +144,78 @@ namespace JSC { Register* m_max; Register* m_buffer; #if HAVE(VIRTUALALLOC) - Register* m_maxCommitted; + Register* m_commitEnd; #endif JSGlobalObject* m_globalObject; // The global object whose vars are currently stored in the register file. }; + inline RegisterFile::RegisterFile(size_t capacity, size_t maxGlobals) + : m_numGlobals(0) + , m_maxGlobals(maxGlobals) + , m_start(0) + , m_end(0) + , m_max(0) + , m_buffer(0) + , m_globalObject(0) + { + size_t bufferLength = (capacity + maxGlobals) * sizeof(Register); + #if HAVE(MMAP) + m_buffer = static_cast<Register*>(mmap(0, bufferLength, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0)); + if (m_buffer == MAP_FAILED) { + fprintf(stderr, "Could not allocate register file: %d\n", errno); + CRASH(); + } + #elif HAVE(VIRTUALALLOC) + m_buffer = static_cast<Register*>(VirtualAlloc(0, roundUpAllocationSize(bufferLength, commitSize), MEM_RESERVE, PAGE_READWRITE)); + if (!m_buffer) { + fprintf(stderr, "Could not allocate register file: %d\n", errno); + CRASH(); + } + size_t committedSize = roundUpAllocationSize(maxGlobals * sizeof(Register), commitSize); + void* commitCheck = VirtualAlloc(m_buffer, committedSize, MEM_COMMIT, PAGE_READWRITE); + if (commitCheck != m_buffer) { + fprintf(stderr, "Could not allocate register file: %d\n", errno); + CRASH(); + } + m_commitEnd = reinterpret_cast<Register*>(reinterpret_cast<char*>(m_buffer) + committedSize); + #else + #error "Don't know how to reserve virtual memory on this platform." + #endif + m_start = m_buffer + maxGlobals; + m_end = m_start; + m_max = m_start + capacity; + } + + inline void RegisterFile::shrink(Register* newEnd) + { + if (newEnd < m_end) + m_end = newEnd; + } + + inline bool RegisterFile::grow(Register* newEnd) + { + if (newEnd < m_end) + return true; + + if (newEnd > m_max) + return false; + +#if !HAVE(MMAP) && HAVE(VIRTUALALLOC) + if (newEnd > m_commitEnd) { + size_t size = roundUpAllocationSize(reinterpret_cast<char*>(newEnd) - reinterpret_cast<char*>(m_commitEnd), commitSize); + if (!VirtualAlloc(m_commitEnd, size, MEM_COMMIT, PAGE_READWRITE)) { + fprintf(stderr, "Could not allocate register file: %d\n", errno); + CRASH(); + } + m_commitEnd = reinterpret_cast<Register*>(reinterpret_cast<char*>(m_commitEnd) + size); + } +#endif + + m_end = newEnd; + return true; + } + } // namespace JSC #endif // RegisterFile_h |
