Commit 7bbcaab7 authored by fpizlo@apple.com's avatar fpizlo@apple.com

JSC should be a triple-tier VM

https://bugs.webkit.org/show_bug.cgi?id=75812
<rdar://problem/10079694>

Source/JavaScriptCore: 

Reviewed by Gavin Barraclough.
        
Implemented an interpreter that uses the JIT's calling convention. This
interpreter is called LLInt, or the Low Level Interpreter. JSC will now
will start by executing code in LLInt and will only tier up to the old
JIT after the code is proven hot.
        
LLInt is written in a modified form of our macro assembly. This new macro
assembly is compiled by an offline assembler (see offlineasm), which
implements many modern conveniences such as a Turing-complete CPS-based
macro language and direct access to relevant C++ type information
(basically offsets of fields and sizes of structs/classes).
        
Code executing in LLInt appears to the rest of the JSC world "as if" it
were executing in the old JIT. Hence, things like exception handling and
cross-execution-engine calls just work and require pretty much no
additional overhead.
        
This interpreter is 2-2.5x faster than our old interpreter on SunSpider,
V8, and Kraken. With triple-tiering turned on, we're neutral on SunSpider,
V8, and Kraken, but appear to get a double-digit improvement on real-world
websites due to a huge reduction in the amount of JIT'ing.
        
* CMakeLists.txt:
* GNUmakefile.am:
* GNUmakefile.list.am:
* JavaScriptCore.pri:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops:
* JavaScriptCore.vcproj/JavaScriptCore/copy-files.cmd:
* JavaScriptCore.xcodeproj/project.pbxproj:
* Target.pri:
* assembler/LinkBuffer.h:
* assembler/MacroAssemblerCodeRef.h:
(MacroAssemblerCodePtr):
(JSC::MacroAssemblerCodePtr::createFromExecutableAddress):
* bytecode/BytecodeConventions.h: Added.
* bytecode/CallLinkStatus.cpp:
(JSC::CallLinkStatus::computeFromLLInt):
(JSC):
(JSC::CallLinkStatus::computeFor):
* bytecode/CallLinkStatus.h:
(JSC::CallLinkStatus::isSet):
(JSC::CallLinkStatus::operator!):
(CallLinkStatus):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dump):
(JSC::CodeBlock::CodeBlock):
(JSC::CodeBlock::~CodeBlock):
(JSC::CodeBlock::finalizeUnconditionally):
(JSC::CodeBlock::stronglyVisitStrongReferences):
(JSC):
(JSC::CodeBlock::unlinkCalls):
(JSC::CodeBlock::unlinkIncomingCalls):
(JSC::CodeBlock::bytecodeOffset):
(JSC::ProgramCodeBlock::jettison):
(JSC::EvalCodeBlock::jettison):
(JSC::FunctionCodeBlock::jettison):
(JSC::ProgramCodeBlock::jitCompileImpl):
(JSC::EvalCodeBlock::jitCompileImpl):
(JSC::FunctionCodeBlock::jitCompileImpl):
* bytecode/CodeBlock.h:
(JSC):
(CodeBlock):
(JSC::CodeBlock::baselineVersion):
(JSC::CodeBlock::linkIncomingCall):
(JSC::CodeBlock::bytecodeOffset):
(JSC::CodeBlock::jitCompile):
(JSC::CodeBlock::hasOptimizedReplacement):
(JSC::CodeBlock::addPropertyAccessInstruction):
(JSC::CodeBlock::addGlobalResolveInstruction):
(JSC::CodeBlock::addLLIntCallLinkInfo):
(JSC::CodeBlock::addGlobalResolveInfo):
(JSC::CodeBlock::numberOfMethodCallLinkInfos):
(JSC::CodeBlock::valueProfilePredictionForBytecodeOffset):
(JSC::CodeBlock::likelyToTakeSlowCase):
(JSC::CodeBlock::couldTakeSlowCase):
(JSC::CodeBlock::likelyToTakeSpecialFastCase):
(JSC::CodeBlock::likelyToTakeDeepestSlowCase):
(JSC::CodeBlock::likelyToTakeAnySlowCase):
(JSC::CodeBlock::addFrequentExitSite):
(JSC::CodeBlock::dontJITAnytimeSoon):
(JSC::CodeBlock::jitAfterWarmUp):
(JSC::CodeBlock::jitSoon):
(JSC::CodeBlock::llintExecuteCounter):
(ProgramCodeBlock):
(EvalCodeBlock):
(FunctionCodeBlock):
* bytecode/GetByIdStatus.cpp:
(JSC::GetByIdStatus::computeFromLLInt):
(JSC):
(JSC::GetByIdStatus::computeFor):
* bytecode/GetByIdStatus.h:
(JSC::GetByIdStatus::GetByIdStatus):
(JSC::GetByIdStatus::wasSeenInJIT):
(GetByIdStatus):
* bytecode/Instruction.h:
(JSC):
(JSC::Instruction::Instruction):
(Instruction):
* bytecode/LLIntCallLinkInfo.h: Added.
(JSC):
(JSC::LLIntCallLinkInfo::LLIntCallLinkInfo):
(LLIntCallLinkInfo):
(JSC::LLIntCallLinkInfo::~LLIntCallLinkInfo):
(JSC::LLIntCallLinkInfo::isLinked):
(JSC::LLIntCallLinkInfo::unlink):
* bytecode/MethodCallLinkStatus.cpp:
(JSC::MethodCallLinkStatus::computeFor):
* bytecode/Opcode.cpp:
(JSC):
* bytecode/Opcode.h:
(JSC):
(JSC::padOpcodeName):
* bytecode/PutByIdStatus.cpp:
(JSC::PutByIdStatus::computeFromLLInt):
(JSC):
(JSC::PutByIdStatus::computeFor):
* bytecode/PutByIdStatus.h:
(PutByIdStatus):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitResolve):
(JSC::BytecodeGenerator::emitResolveWithBase):
(JSC::BytecodeGenerator::emitGetById):
(JSC::BytecodeGenerator::emitPutById):
(JSC::BytecodeGenerator::emitDirectPutById):
(JSC::BytecodeGenerator::emitCall):
(JSC::BytecodeGenerator::emitConstruct):
(JSC::BytecodeGenerator::emitCatch):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::getPredictionWithoutOSRExit):
(JSC::DFG::ByteCodeParser::handleInlining):
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCapabilities.h:
(JSC::DFG::canCompileOpcode):
* dfg/DFGOSRExitCompiler.cpp:
* dfg/DFGOperations.cpp:
* heap/Heap.h:
(JSC):
(JSC::Heap::firstAllocatorWithoutDestructors):
(Heap):
* heap/MarkStack.cpp:
(JSC::visitChildren):
* heap/MarkedAllocator.h:
(JSC):
(MarkedAllocator):
* heap/MarkedSpace.h:
(JSC):
(MarkedSpace):
(JSC::MarkedSpace::firstAllocator):
* interpreter/CallFrame.cpp:
(JSC):
(JSC::CallFrame::bytecodeOffsetForNonDFGCode):
(JSC::CallFrame::setBytecodeOffsetForNonDFGCode):
(JSC::CallFrame::currentVPC):
(JSC::CallFrame::setCurrentVPC):
(JSC::CallFrame::trueCallerFrame):
* interpreter/CallFrame.h:
(JSC::ExecState::hasReturnPC):
(JSC::ExecState::clearReturnPC):
(ExecState):
(JSC::ExecState::bytecodeOffsetForNonDFGCode):
(JSC::ExecState::currentVPC):
(JSC::ExecState::setCurrentVPC):
* interpreter/Interpreter.cpp:
(JSC::Interpreter::Interpreter):
(JSC::Interpreter::~Interpreter):
(JSC):
(JSC::Interpreter::initialize):
(JSC::Interpreter::isOpcode):
(JSC::Interpreter::unwindCallFrame):
(JSC::getCallerInfo):
(JSC::Interpreter::privateExecute):
(JSC::Interpreter::retrieveLastCaller):
* interpreter/Interpreter.h:
(JSC):
(Interpreter):
(JSC::Interpreter::getOpcode):
(JSC::Interpreter::getOpcodeID):
(JSC::Interpreter::classicEnabled):
* interpreter/RegisterFile.h:
(JSC):
(RegisterFile):
* jit/ExecutableAllocator.h:
(JSC):
* jit/HostCallReturnValue.cpp: Added.
(JSC):
(JSC::getHostCallReturnValueWithExecState):
* jit/HostCallReturnValue.h: Added.
(JSC):
(JSC::initializeHostCallReturnValue):
* jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
(JSC::JIT::privateCompileSlowCases):
(JSC::JIT::privateCompile):
* jit/JITCode.h:
(JSC::JITCode::isOptimizingJIT):
(JITCode):
(JSC::JITCode::isBaselineCode):
(JSC::JITCode::JITCode):
* jit/JITDriver.h:
(JSC::jitCompileIfAppropriate):
(JSC::jitCompileFunctionIfAppropriate):
* jit/JITExceptions.cpp:
(JSC::jitThrow):
* jit/JITInlineMethods.h:
(JSC::JIT::updateTopCallFrame):
* jit/JITStubs.cpp:
(JSC::DEFINE_STUB_FUNCTION):
(JSC):
* jit/JITStubs.h:
(JSC):
* jit/JSInterfaceJIT.h:
* llint: Added.
* llint/LLIntCommon.h: Added.
* llint/LLIntData.cpp: Added.
(LLInt):
(JSC::LLInt::Data::Data):
(JSC::LLInt::Data::performAssertions):
(JSC::LLInt::Data::~Data):
* llint/LLIntData.h: Added.
(JSC):
(LLInt):
(Data):
(JSC::LLInt::Data::exceptionInstructions):
(JSC::LLInt::Data::opcodeMap):
(JSC::LLInt::Data::performAssertions):
* llint/LLIntEntrypoints.cpp: Added.
(LLInt):
(JSC::LLInt::getFunctionEntrypoint):
(JSC::LLInt::getEvalEntrypoint):
(JSC::LLInt::getProgramEntrypoint):
* llint/LLIntEntrypoints.h: Added.
(JSC):
(LLInt):
(JSC::LLInt::getEntrypoint):
* llint/LLIntExceptions.cpp: Added.
(LLInt):
(JSC::LLInt::interpreterThrowInCaller):
(JSC::LLInt::returnToThrowForThrownException):
(JSC::LLInt::returnToThrow):
(JSC::LLInt::callToThrow):
* llint/LLIntExceptions.h: Added.
(JSC):
(LLInt):
* llint/LLIntOfflineAsmConfig.h: Added.
* llint/LLIntOffsetsExtractor.cpp: Added.
(JSC):
(LLIntOffsetsExtractor):
(JSC::LLIntOffsetsExtractor::dummy):
(main):
* llint/LLIntSlowPaths.cpp: Added.
(LLInt):
(JSC::LLInt::llint_trace_operand):
(JSC::LLInt::llint_trace_value):
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
(JSC::LLInt::traceFunctionPrologue):
(JSC::LLInt::shouldJIT):
(JSC::LLInt::entryOSR):
(JSC::LLInt::resolveGlobal):
(JSC::LLInt::getByVal):
(JSC::LLInt::handleHostCall):
(JSC::LLInt::setUpCall):
(JSC::LLInt::genericCall):
* llint/LLIntSlowPaths.h: Added.
(JSC):
(LLInt):
* llint/LLIntThunks.cpp: Added.
(LLInt):
(JSC::LLInt::generateThunkWithJumpTo):
(JSC::LLInt::functionForCallEntryThunkGenerator):
(JSC::LLInt::functionForConstructEntryThunkGenerator):
(JSC::LLInt::functionForCallArityCheckThunkGenerator):
(JSC::LLInt::functionForConstructArityCheckThunkGenerator):
(JSC::LLInt::evalEntryThunkGenerator):
(JSC::LLInt::programEntryThunkGenerator):
* llint/LLIntThunks.h: Added.
(JSC):
(LLInt):
* llint/LowLevelInterpreter.asm: Added.
* llint/LowLevelInterpreter.cpp: Added.
* llint/LowLevelInterpreter.h: Added.
* offlineasm: Added.
* offlineasm/armv7.rb: Added.
* offlineasm/asm.rb: Added.
* offlineasm/ast.rb: Added.
* offlineasm/backends.rb: Added.
* offlineasm/generate_offset_extractor.rb: Added.
* offlineasm/instructions.rb: Added.
* offlineasm/offset_extractor_constants.rb: Added.
* offlineasm/offsets.rb: Added.
* offlineasm/opt.rb: Added.
* offlineasm/parser.rb: Added.
* offlineasm/registers.rb: Added.
* offlineasm/self_hash.rb: Added.
* offlineasm/settings.rb: Added.
* offlineasm/transform.rb: Added.
* offlineasm/x86.rb: Added.
* runtime/CodeSpecializationKind.h: Added.
(JSC):
* runtime/CommonSlowPaths.h:
(JSC::CommonSlowPaths::arityCheckFor):
(CommonSlowPaths):
* runtime/Executable.cpp:
(JSC::jettisonCodeBlock):
(JSC):
(JSC::EvalExecutable::jitCompile):
(JSC::samplingDescription):
(JSC::EvalExecutable::compileInternal):
(JSC::ProgramExecutable::jitCompile):
(JSC::ProgramExecutable::compileInternal):
(JSC::FunctionExecutable::baselineCodeBlockFor):
(JSC::FunctionExecutable::jitCompileForCall):
(JSC::FunctionExecutable::jitCompileForConstruct):
(JSC::FunctionExecutable::compileForCallInternal):
(JSC::FunctionExecutable::compileForConstructInternal):
* runtime/Executable.h:
(JSC):
(EvalExecutable):
(ProgramExecutable):
(FunctionExecutable):
(JSC::FunctionExecutable::jitCompileFor):
* runtime/ExecutionHarness.h: Added.
(JSC):
(JSC::prepareForExecution):
(JSC::prepareFunctionForExecution):
* runtime/JSArray.h:
(JSC):
(JSArray):
* runtime/JSCell.h:
(JSC):
(JSCell):
* runtime/JSFunction.h:
(JSC):
(JSFunction):
* runtime/JSGlobalData.cpp:
(JSC::JSGlobalData::JSGlobalData):
* runtime/JSGlobalData.h:
(JSC):
(JSGlobalData):
* runtime/JSGlobalObject.h:
(JSC):
(JSGlobalObject):
* runtime/JSObject.h:
(JSC):
(JSObject):
(JSFinalObject):
* runtime/JSPropertyNameIterator.h:
(JSC):
(JSPropertyNameIterator):
* runtime/JSString.h:
(JSC):
(JSString):
* runtime/JSTypeInfo.h:
(JSC):
(TypeInfo):
* runtime/JSValue.cpp:
(JSC::JSValue::description):
* runtime/JSValue.h:
(LLInt):
(JSValue):
* runtime/JSVariableObject.h:
(JSC):
(JSVariableObject):
* runtime/Options.cpp:
(Options):
(JSC::Options::initializeOptions):
* runtime/Options.h:
(Options):
* runtime/ScopeChain.h:
(JSC):
(ScopeChainNode):
* runtime/Structure.cpp:
(JSC::Structure::addPropertyTransition):
* runtime/Structure.h:
(JSC):
(Structure):
* runtime/StructureChain.h:
(JSC):
(StructureChain):
* wtf/InlineASM.h:
* wtf/Platform.h:
* wtf/SentinelLinkedList.h:
(SentinelLinkedList):
(WTF::SentinelLinkedList::isEmpty):
* wtf/text/StringImpl.h:
(JSC):
(StringImpl):

Source/WebCore: 

Reviewed by Gavin Barraclough.
        
No new tests, because there is no change in behavior.

* CMakeLists.txt:

Source/WebKit: 

Reviewed by Gavin Barraclough.

Changed EFL's build system to include a new directory in JavaScriptCore.
        
* CMakeLists.txt:

Tools: 

Reviewed by Gavin Barraclough.

Changed EFL's build system to include a new directory in JavaScriptCore.

* DumpRenderTree/efl/CMakeLists.txt:



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@108444 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent d14f2e83
......@@ -11,6 +11,7 @@ SET(JavaScriptCore_INCLUDE_DIRECTORIES
"${JAVASCRIPTCORE_DIR}/debugger"
"${JAVASCRIPTCORE_DIR}/interpreter"
"${JAVASCRIPTCORE_DIR}/jit"
"${JAVASCRIPTCORE_DIR}/llint"
"${JAVASCRIPTCORE_DIR}/parser"
"${JAVASCRIPTCORE_DIR}/profiler"
"${JAVASCRIPTCORE_DIR}/runtime"
......@@ -102,6 +103,7 @@ SET(JavaScriptCore_SOURCES
interpreter/RegisterFile.cpp
jit/ExecutableAllocator.cpp
jit/HostCallReturnValue.cpp
jit/JITArithmetic32_64.cpp
jit/JITArithmetic.cpp
jit/JITCall32_64.cpp
......
This diff is collapsed.
......@@ -57,6 +57,7 @@ javascriptcore_cppflags += \
-I$(srcdir)/Source/JavaScriptCore/interpreter \
-I$(srcdir)/Source/JavaScriptCore/jit \
-I$(srcdir)/Source/JavaScriptCore/jit \
-I$(srcdir)/Source/JavaScriptCore/llint \
-I$(srcdir)/Source/JavaScriptCore/parser \
-I$(srcdir)/Source/JavaScriptCore/profiler \
-I$(srcdir)/Source/JavaScriptCore/runtime \
......
......@@ -81,6 +81,7 @@ javascriptcore_sources += \
Source/JavaScriptCore/assembler/RepatchBuffer.h \
Source/JavaScriptCore/assembler/SH4Assembler.h \
Source/JavaScriptCore/assembler/X86Assembler.h \
Source/JavaScriptCore/bytecode/BytecodeConventions.h \
Source/JavaScriptCore/bytecode/CallLinkInfo.cpp \
Source/JavaScriptCore/bytecode/CallLinkInfo.h \
Source/JavaScriptCore/bytecode/CallLinkStatus.cpp \
......@@ -102,6 +103,7 @@ javascriptcore_sources += \
Source/JavaScriptCore/bytecode/Instruction.h \
Source/JavaScriptCore/bytecode/JumpTable.cpp \
Source/JavaScriptCore/bytecode/JumpTable.h \
Source/JavaScriptCore/bytecode/LLIntCallLinkInfo.h \
Source/JavaScriptCore/bytecode/LineInfo.h \
Source/JavaScriptCore/bytecode/MethodCallLinkInfo.cpp \
Source/JavaScriptCore/bytecode/MethodCallLinkInfo.h \
......@@ -297,6 +299,8 @@ javascriptcore_sources += \
Source/JavaScriptCore/jit/CompactJITCodeMap.h \
Source/JavaScriptCore/jit/ExecutableAllocator.cpp \
Source/JavaScriptCore/jit/ExecutableAllocator.h \
Source/JavaScriptCore/jit/HostCallReturnValue.cpp \
Source/JavaScriptCore/jit/HostCallReturnValue.h \
Source/JavaScriptCore/jit/JITArithmetic32_64.cpp \
Source/JavaScriptCore/jit/JITArithmetic.cpp \
Source/JavaScriptCore/jit/JITCall32_64.cpp \
......@@ -320,6 +324,7 @@ javascriptcore_sources += \
Source/JavaScriptCore/jit/SpecializedThunkJIT.h \
Source/JavaScriptCore/jit/ThunkGenerators.cpp \
Source/JavaScriptCore/jit/ThunkGenerators.h \
Source/JavaScriptCore/llint/LLIntData.h \
Source/JavaScriptCore/os-win32/stdbool.h \
Source/JavaScriptCore/os-win32/stdint.h \
Source/JavaScriptCore/parser/ASTBuilder.h \
......@@ -370,6 +375,7 @@ javascriptcore_sources += \
Source/JavaScriptCore/runtime/CallData.cpp \
Source/JavaScriptCore/runtime/CallData.h \
Source/JavaScriptCore/runtime/ClassInfo.h \
Source/JavaScriptCore/runtime/CodeSpecializationKind.h \
Source/JavaScriptCore/runtime/CommonIdentifiers.cpp \
Source/JavaScriptCore/runtime/CommonIdentifiers.h \
Source/JavaScriptCore/runtime/CommonSlowPaths.h \
......@@ -398,6 +404,7 @@ javascriptcore_sources += \
Source/JavaScriptCore/runtime/ExceptionHelpers.h \
Source/JavaScriptCore/runtime/Executable.cpp \
Source/JavaScriptCore/runtime/Executable.h \
Source/JavaScriptCore/runtime/ExecutionHarness.h \
Source/JavaScriptCore/runtime/FunctionConstructor.cpp \
Source/JavaScriptCore/runtime/FunctionConstructor.h \
Source/JavaScriptCore/runtime/FunctionPrototype.cpp \
......
......@@ -20,6 +20,7 @@ INCLUDEPATH += \
$$SOURCE_DIR/debugger \
$$SOURCE_DIR/interpreter \
$$SOURCE_DIR/jit \
$$SOURCE_DIR/llint \
$$SOURCE_DIR/parser \
$$SOURCE_DIR/profiler \
$$SOURCE_DIR/runtime \
......
......@@ -1761,6 +1761,10 @@
RelativePath="..\..\jit\ExecutableAllocator.h"
>
</File>
<File
RelativePath="..\..\jit\HostCallReturnValue.cpp"
>
</File>
<File
RelativePath="..\..\jit\JIT.cpp"
>
......@@ -1846,6 +1850,14 @@
>
</File>
</Filter>
<Filter
Name="llint"
>
<File
RelativePath="..\..\llint\LLIntData.h"
>
</File>
</Filter>
<Filter
Name="interpreter"
>
......
......@@ -6,7 +6,7 @@
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="&quot;$(ConfigurationBuildDir)\obj\JavaScriptCore\DerivedSources\&quot;;../../;../../API/;../../parser/;../../bytecompiler/;../../dfg/;../../jit/;../../runtime/;../../tools/;../../bytecode/;../../interpreter/;../../wtf/;../../profiler;../../assembler/;../../debugger/;../../heap/;&quot;$(WebKitLibrariesDir)\include&quot;;&quot;$(WebKitLibrariesDir)\include\private&quot;;&quot;$(ConfigurationBuildDir)\include&quot;;&quot;$(ConfigurationBuildDir)\include\JavaScriptCore&quot;;&quot;$(ConfigurationBuildDir)\include\private&quot;;&quot;$(WebKitLibrariesDir)\include\pthreads&quot;"
AdditionalIncludeDirectories="&quot;$(ConfigurationBuildDir)\obj\JavaScriptCore\DerivedSources\&quot;;../../;../../API/;../../parser/;../../bytecompiler/;../../dfg/;../../jit/;../../llint/;../../runtime/;../../tools/;../../bytecode/;../../interpreter/;../../wtf/;../../profiler;../../assembler/;../../debugger/;../../heap/;&quot;$(WebKitLibrariesDir)\include&quot;;&quot;$(WebKitLibrariesDir)\include\private&quot;;&quot;$(ConfigurationBuildDir)\include&quot;;&quot;$(ConfigurationBuildDir)\include\JavaScriptCore&quot;;&quot;$(ConfigurationBuildDir)\include\private&quot;;&quot;$(WebKitLibrariesDir)\include\pthreads&quot;"
PreprocessorDefinitions="__STD_C"
ForcedIncludeFiles="ICUVersion.h"
/>
......
......@@ -43,6 +43,7 @@ for %%d in (
debugger
interpreter
jit
llint
parser
profiler
runtime
......
......@@ -113,6 +113,7 @@ SOURCES += \
interpreter/RegisterFile.cpp \
jit/ExecutableAllocatorFixedVMPool.cpp \
jit/ExecutableAllocator.cpp \
jit/HostCallReturnValue.cpp \
jit/JITArithmetic.cpp \
jit/JITArithmetic32_64.cpp \
jit/JITCall.cpp \
......
......@@ -34,7 +34,7 @@
#define GLOBAL_THUNK_ID reinterpret_cast<void*>(static_cast<intptr_t>(-1))
#define REGEXP_CODE_ID reinterpret_cast<void*>(static_cast<intptr_t>(-2))
#include <MacroAssembler.h>
#include "MacroAssembler.h"
#include <wtf/DataLog.h>
#include <wtf/Noncopyable.h>
......
......@@ -31,8 +31,6 @@
#include "RefPtr.h"
#include "UnusedParam.h"
#if ENABLE(ASSEMBLER)
// ASSERT_VALID_CODE_POINTER checks that ptr is a non-null pointer, and that it is a valid
// instruction address on the platform (for example, check any alignment requirements).
#if CPU(ARM_THUMB2)
......@@ -273,6 +271,14 @@ public:
{
ASSERT_VALID_CODE_POINTER(m_value);
}
static MacroAssemblerCodePtr createFromExecutableAddress(void* value)
{
ASSERT_VALID_CODE_POINTER(value);
MacroAssemblerCodePtr result;
result.m_value = value;
return result;
}
explicit MacroAssemblerCodePtr(ReturnAddressPtr ra)
: m_value(ra.value())
......@@ -360,6 +366,4 @@ private:
} // namespace JSC
#endif // ENABLE(ASSEMBLER)
#endif // MacroAssemblerCodeRef_h
/*
* Copyright (C) 2012 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef BytecodeConventions_h
#define BytecodeConventions_h
// Register numbers used in bytecode operations have different meaning according to their ranges:
// 0x80000000-0xFFFFFFFF Negative indices from the CallFrame pointer are entries in the call frame, see RegisterFile.h.
// 0x00000000-0x3FFFFFFF Forwards indices from the CallFrame pointer are local vars and temporaries with the function's callframe.
// 0x40000000-0x7FFFFFFF Positive indices from 0x40000000 specify entries in the constant pool on the CodeBlock.
static const int FirstConstantRegisterIndex = 0x40000000;
#endif // BytecodeConventions_h
......@@ -27,17 +27,40 @@
#include "CallLinkStatus.h"
#include "CodeBlock.h"
#include "LLIntCallLinkInfo.h"
namespace JSC {
CallLinkStatus CallLinkStatus::computeFromLLInt(CodeBlock* profiledBlock, unsigned bytecodeIndex)
{
UNUSED_PARAM(profiledBlock);
UNUSED_PARAM(bytecodeIndex);
#if ENABLE(LLINT)
Instruction* instruction = profiledBlock->instructions().begin() + bytecodeIndex;
LLIntCallLinkInfo* callLinkInfo = instruction[4].u.callLinkInfo;
return CallLinkStatus(callLinkInfo->lastSeenCallee.get(), false);
#else
return CallLinkStatus(0, false);
#endif
}
CallLinkStatus CallLinkStatus::computeFor(CodeBlock* profiledBlock, unsigned bytecodeIndex)
{
UNUSED_PARAM(profiledBlock);
UNUSED_PARAM(bytecodeIndex);
#if ENABLE(JIT) && ENABLE(VALUE_PROFILER)
return CallLinkStatus(
profiledBlock->getCallLinkInfo(bytecodeIndex).lastSeenCallee.get(),
profiledBlock->couldTakeSlowCase(bytecodeIndex));
if (!profiledBlock->numberOfCallLinkInfos())
return computeFromLLInt(profiledBlock, bytecodeIndex);
if (profiledBlock->couldTakeSlowCase(bytecodeIndex))
return CallLinkStatus(0, true);
JSFunction* target = profiledBlock->getCallLinkInfo(bytecodeIndex).lastSeenCallee.get();
if (!target)
return computeFromLLInt(profiledBlock, bytecodeIndex);
return CallLinkStatus(target, false);
#else
return CallLinkStatus(0, false);
#endif
......
......@@ -47,15 +47,17 @@ public:
static CallLinkStatus computeFor(CodeBlock*, unsigned bytecodeIndex);
bool isSet() const { return !!m_callTarget; }
bool isSet() const { return !!m_callTarget || m_couldTakeSlowPath; }
bool operator!() const { return !m_callTarget; }
bool operator!() const { return !isSet(); }
bool couldTakeSlowPath() const { return m_couldTakeSlowPath; }
JSFunction* callTarget() const { return m_callTarget; }
private:
static CallLinkStatus computeFromLLInt(CodeBlock*, unsigned bytecodeIndex);
JSFunction* m_callTarget;
bool m_couldTakeSlowPath;
};
......
This diff is collapsed.
......@@ -27,20 +27,49 @@
#include "GetByIdStatus.h"
#include "CodeBlock.h"
#include "LowLevelInterpreter.h"
namespace JSC {
GetByIdStatus GetByIdStatus::computeFromLLInt(CodeBlock* profiledBlock, unsigned bytecodeIndex, Identifier& ident)
{
UNUSED_PARAM(profiledBlock);
UNUSED_PARAM(bytecodeIndex);
UNUSED_PARAM(ident);
#if ENABLE(LLINT)
Instruction* instruction = profiledBlock->instructions().begin() + bytecodeIndex;
if (instruction[0].u.opcode == llint_op_method_check)
instruction++;
Structure* structure = instruction[4].u.structure.get();
if (!structure)
return GetByIdStatus(NoInformation, StructureSet(), notFound, false);
size_t offset = structure->get(*profiledBlock->globalData(), ident);
if (offset == notFound)
return GetByIdStatus(NoInformation, StructureSet(), notFound, false);
return GetByIdStatus(SimpleDirect, StructureSet(structure), offset, false);
#else
return GetByIdStatus(NoInformation, StructureSet(), notFound, false);
#endif
}
GetByIdStatus GetByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytecodeIndex, Identifier& ident)
{
UNUSED_PARAM(profiledBlock);
UNUSED_PARAM(bytecodeIndex);
UNUSED_PARAM(ident);
#if ENABLE(JIT) && ENABLE(VALUE_PROFILER)
if (!profiledBlock->numberOfStructureStubInfos())
return computeFromLLInt(profiledBlock, bytecodeIndex, ident);
// First check if it makes either calls, in which case we want to be super careful, or
// if it's not set at all, in which case we punt.
StructureStubInfo& stubInfo = profiledBlock->getStubInfo(bytecodeIndex);
if (!stubInfo.seen)
return GetByIdStatus(NoInformation, StructureSet(), notFound);
return computeFromLLInt(profiledBlock, bytecodeIndex, ident);
PolymorphicAccessStructureList* list;
int listSize;
......@@ -60,18 +89,19 @@ GetByIdStatus GetByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytec
}
for (int i = 0; i < listSize; ++i) {
if (!list->list[i].isDirect)
return GetByIdStatus(MakesCalls, StructureSet(), notFound);
return GetByIdStatus(MakesCalls, StructureSet(), notFound, true);
}
// Next check if it takes slow case, in which case we want to be kind of careful.
if (profiledBlock->likelyToTakeSlowCase(bytecodeIndex))
return GetByIdStatus(TakesSlowPath, StructureSet(), notFound);
return GetByIdStatus(TakesSlowPath, StructureSet(), notFound, true);
// Finally figure out if we can derive an access strategy.
GetByIdStatus result;
result.m_wasSeenInJIT = true;
switch (stubInfo.accessType) {
case access_unset:
return GetByIdStatus(NoInformation, StructureSet(), notFound);
return computeFromLLInt(profiledBlock, bytecodeIndex, ident);
case access_get_by_id_self: {
Structure* structure = stubInfo.u.getByIdSelf.baseObjectStructure.get();
......@@ -130,7 +160,7 @@ GetByIdStatus GetByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytec
return result;
#else // ENABLE(JIT)
return GetByIdStatus(NoInformation, StructureSet(), notFound);
return GetByIdStatus(NoInformation, StructureSet(), notFound, false);
#endif // ENABLE(JIT)
}
......
......@@ -49,10 +49,11 @@ public:
{
}
GetByIdStatus(State state, const StructureSet& structureSet, size_t offset)
GetByIdStatus(State state, const StructureSet& structureSet, size_t offset, bool wasSeenInJIT)
: m_state(state)
, m_structureSet(structureSet)
, m_offset(offset)
, m_wasSeenInJIT(wasSeenInJIT)
{
ASSERT((state == SimpleDirect) == (offset != notFound));
}
......@@ -70,10 +71,15 @@ public:
const StructureSet& structureSet() const { return m_structureSet; }
size_t offset() const { return m_offset; }
bool wasSeenInJIT() const { return m_wasSeenInJIT; }
private:
static GetByIdStatus computeFromLLInt(CodeBlock*, unsigned bytecodeIndex, Identifier&);
State m_state;
StructureSet m_structureSet;
size_t m_offset;
bool m_wasSeenInJIT;
};
} // namespace JSC
......
......@@ -48,6 +48,7 @@ namespace JSC {
class JSCell;
class Structure;
class StructureChain;
struct LLIntCallLinkInfo;
struct ValueProfile;
#if ENABLE(JIT)
......@@ -146,6 +147,11 @@ namespace JSC {
#endif
struct Instruction {
Instruction()
{
u.jsCell.clear();
}
Instruction(Opcode opcode)
{
#if !ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
......@@ -182,6 +188,8 @@ namespace JSC {
Instruction(PropertySlot::GetValueFunc getterFunc) { u.getterFunc = getterFunc; }
Instruction(LLIntCallLinkInfo* callLinkInfo) { u.callLinkInfo = callLinkInfo; }
Instruction(ValueProfile* profile) { u.profile = profile; }
union {
......@@ -191,7 +199,9 @@ namespace JSC {
WriteBarrierBase<StructureChain> structureChain;
WriteBarrierBase<JSCell> jsCell;
PropertySlot::GetValueFunc getterFunc;
LLIntCallLinkInfo* callLinkInfo;
ValueProfile* profile;
void* pointer;
} u;
private:
......
/*
* Copyright (C) 2012 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef LLIntCallLinkInfo_h
#define LLIntCallLinkInfo_h
#include "JSFunction.h"
#include "MacroAssemblerCodeRef.h"
#include <wtf/SentinelLinkedList.h>
namespace JSC {
struct Instruction;
struct LLIntCallLinkInfo : public BasicRawSentinelNode<LLIntCallLinkInfo> {
LLIntCallLinkInfo()
{
}
~LLIntCallLinkInfo()
{
if (isOnList())
remove();
}
bool isLinked() { return callee; }
void unlink()
{
callee.clear();
machineCodeTarget = MacroAssemblerCodePtr();
if (isOnList())
remove();
}
WriteBarrier<JSFunction> callee;
WriteBarrier<JSFunction> lastSeenCallee;
MacroAssemblerCodePtr machineCodeTarget;
};
} // namespace JSC
#endif // LLIntCallLinkInfo_h
......@@ -35,6 +35,11 @@ MethodCallLinkStatus MethodCallLinkStatus::computeFor(CodeBlock* profiledBlock,
UNUSED_PARAM(profiledBlock);
UNUSED_PARAM(bytecodeIndex);
#if ENABLE(JIT) && ENABLE(VALUE_PROFILER)
// NOTE: This does not have an LLInt fall-back because LLInt does not do any method
// call link caching.
if (!profiledBlock->numberOfMethodCallLinkInfos())
return MethodCallLinkStatus();
MethodCallLinkInfo& methodCall = profiledBlock->getMethodCallLinkInfo(bytecodeIndex);
if (!methodCall.seen || !methodCall.cachedStructure)
......
......@@ -39,16 +39,12 @@ using namespace std;
namespace JSC {
#if !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING) || ENABLE(CODEBLOCK_SAMPLING) || ENABLE(OPCODE_STATS)
const char* const opcodeNames[] = {
#define OPCODE_NAME_ENTRY(opcode, size) #opcode,
FOR_EACH_OPCODE_ID(OPCODE_NAME_ENTRY)
#undef OPCODE_NAME_ENTRY
};
#endif
#if ENABLE(OPCODE_STATS)
long long OpcodeStats::opcodeCounts[numOpcodeIDs];
......
......@@ -123,6 +123,8 @@ namespace JSC {
macro(op_get_arguments_length, 4) \
macro(op_put_by_id, 9) \
macro(op_put_by_id_transition, 9) \
macro(op_put_by_id_transition_direct, 9) \
macro(op_put_by_id_transition_normal, 9) \
macro(op_put_by_id_replace, 9) \
macro(op_put_by_id_generic, 9) \
macro(op_del_by_id, 4) \
......@@ -201,6 +203,7 @@ namespace JSC {
typedef enum { FOR_EACH_OPCODE_ID(OPCODE_ID_ENUM) } OpcodeID;
#undef OPCODE_ID_ENUM
const int maxOpcodeLength = 9;
const int numOpcodeIDs = op_end + 1;
#define OPCODE_ID_LENGTHS(id, length) const int id##_length = length;
......@@ -217,7 +220,7 @@ namespace JSC {
FOR_EACH_OPCODE_ID(VERIFY_OPCODE_ID);
#undef VERIFY_OPCODE_ID
#if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
#if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) || ENABLE(LLINT)
#if COMPILER(RVCT) || COMPILER(INTEL)
typedef void* Opcode;
#else
......@@ -227,8 +230,6 @@ namespace JSC {
typedef OpcodeID Opcode;
#endif
#if !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING) || ENABLE(CODEBLOCK_SAMPLING) || ENABLE(OPCODE_STATS)
#define PADDING_STRING " "
#define PADDING_STRING_LENGTH static_cast<unsigned>(strlen(PADDING_STRING))
......@@ -244,8 +245,6 @@ namespace JSC {
#undef PADDING_STRING_LENGTH
#undef PADDING_STRING
#endif
#if ENABLE(OPCODE_STATS)
struct OpcodeStats {
......
......@@ -27,27 +27,69 @@
#include "PutByIdStatus.h"
#include "CodeBlock.h"
#include "LowLevelInterpreter.h"
#include "Structure.h"
#include "StructureChain.h"
namespace JSC {
PutByIdStatus PutByIdStatus::computeFromLLInt(CodeBlock* profiledBlock, unsigned bytecodeIndex, Identifier& ident)
{
UNUSED_PARAM(profiledBlock);
UNUSED_PARAM(bytecodeIndex);
UNUSED_PARAM(ident);
#if ENABLE(LLINT)
Instruction* instruction = profiledBlock->instructions().begin() + bytecodeIndex;
Structure* structure = instruction[4].u.structure.get();
if (!structure)
return PutByIdStatus(NoInformation, 0, 0, 0, notFound);
if (instruction[0].u.opcode == llint_op_put_by_id) {
size_t offset = structure->get(*profiledBlock->globalData(), ident);
if (offset == notFound)
return PutByIdStatus(NoInformation, 0, 0, 0, notFound);
return PutByIdStatus(SimpleReplace, structure, 0, 0, offset);
}
ASSERT(instruction[0].u.opcode == llint_op_put_by_id_transition_direct
|| instruction[0].u.opcode == llint_op_put_by_id_transition_normal);
Structure* newStructure = instruction[6].u.structure.get();
StructureChain* chain = instruction[7].u.structureChain.get();
ASSERT(newStructure);
ASSERT(chain);
size_t offset = newStructure->get(*profiledBlock->globalData(), ident);
if (offset == notFound)
return PutByIdStatus(NoInformation, 0, 0, 0, notFound);
return PutByIdStatus(SimpleTransition, structure, newStructure, chain, offset);
#else
return PutByIdStatus(NoInformation, 0, 0, 0, notFound);
#endif
}
PutByIdStatus PutByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytecodeIndex, Identifier& ident)
{
UNUSED_PARAM(profiledBlock);
UNUSED_PARAM(bytecodeIndex);
UNUSED_PARAM(ident);
#if ENABLE(JIT) && ENABLE(VALUE_PROFILER)
if (!profiledBlock->numberOfStructureStubInfos())
return computeFromLLInt(profiledBlock, bytecodeIndex, ident);
if (profiledBlock->likelyToTakeSlowCase(bytecodeIndex))
return PutByIdStatus(TakesSlowPath, 0, 0, 0, notFound);
StructureStubInfo& stubInfo = profiledBlock->getStubInfo(bytecodeIndex);
if (!stubInfo.seen)
return PutByIdStatus(NoInformation, 0, 0, 0, notFound);
return computeFromLLInt(profiledBlock, bytecodeIndex, ident);
switch (stubInfo.accessType) {
case access_unset:
return PutByIdStatus(NoInformation, 0, 0, 0, notFound);
return computeFromLLInt(profiledBlock, bytecodeIndex, ident);
case access_put_by_id_replace: {
size_t offset = stubInfo.u.putByIdReplace.baseObjectStructure->get(
......
......@@ -93,6 +93,8 @@ public:
size_t offset() const { return