Diff
Modified: trunk/LayoutTests/ChangeLog (199945 => 199946)
--- trunk/LayoutTests/ChangeLog 2016-04-23 01:14:02 UTC (rev 199945)
+++ trunk/LayoutTests/ChangeLog 2016-04-23 02:00:38 UTC (rev 199946)
@@ -1,3 +1,17 @@
+2016-04-22 Filip Pizlo <fpi...@apple.com>
+
+ Speed up bound functions a bit
+ https://bugs.webkit.org/show_bug.cgi?id=156889
+
+ Reviewed by Saam Barati.
+
+ This microbenchmark speeds up by >4x with this change.
+
+ * js/regress/bound-function-call-expected.txt: Added.
+ * js/regress/bound-function-call.html: Added.
+ * js/regress/script-tests/bound-function-call.js: Added.
+ (foo):
+
2016-04-22 Chris Dumez <cdu...@apple.com>
Cannot access the SQLTransaction.constructor.prototype
Added: trunk/LayoutTests/js/regress/bound-function-call-expected.txt (0 => 199946)
--- trunk/LayoutTests/js/regress/bound-function-call-expected.txt (rev 0)
+++ trunk/LayoutTests/js/regress/bound-function-call-expected.txt 2016-04-23 02:00:38 UTC (rev 199946)
@@ -0,0 +1,10 @@
+JSRegress/bound-function-call
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/js/regress/bound-function-call.html (0 => 199946)
--- trunk/LayoutTests/js/regress/bound-function-call.html (rev 0)
+++ trunk/LayoutTests/js/regress/bound-function-call.html 2016-04-23 02:00:38 UTC (rev 199946)
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/js/regress/script-tests/bound-function-call.js (0 => 199946)
--- trunk/LayoutTests/js/regress/script-tests/bound-function-call.js (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/bound-function-call.js 2016-04-23 02:00:38 UTC (rev 199946)
@@ -0,0 +1,16 @@
+function foo() {
+ return this.f;
+}
+
+var binding = foo.bind({f:42});
+
+(function() {
+ var n = 1000000;
+ var result = 0;
+ for (var i = 0; i < n; ++i) {
+ var myResult = binding();
+ result += myResult;
+ }
+ if (result != n * 42)
+ throw "Error: bad result: " + result;
+})();
Modified: trunk/Source/_javascript_Core/ChangeLog (199945 => 199946)
--- trunk/Source/_javascript_Core/ChangeLog 2016-04-23 01:14:02 UTC (rev 199945)
+++ trunk/Source/_javascript_Core/ChangeLog 2016-04-23 02:00:38 UTC (rev 199946)
@@ -1,3 +1,125 @@
+2016-04-22 Filip Pizlo <fpi...@apple.com>
+
+ Speed up bound functions a bit
+ https://bugs.webkit.org/show_bug.cgi?id=156889
+
+ Reviewed by Saam Barati.
+
+ Bound functions are hard to optimize because JSC doesn't have a good notion of non-JS code
+ that does JS-ey things like make JS calls. What I mean by "non-JS code" is code that did not
+ originate from JS source. A bound function does a highly polymorphic call to the target
+ stored in the JSBoundFunction. Prior to this change, we represented it as native code that
+ used the generic native->JS call API. That's not cheap.
+
+ We could model bound functions using a builtin, but it's not clear that this would be easy
+ to grok, since so much of the code would have to access special parts of the JSBoundFunction
+ type. Doing it that way might solve the performance problems but it would mean extra work to
+ arrange for the builtin to have speedy access to the call target, the bound this, and the
+ bound arguments. Also, optimizing bound functions that way would mean that bound function
+ performance would be gated on the performance of a bunch of other things in our system. For
+ example, we'd want this polymorphic call to be handled like the funnel that it is: if we're
+ compiling the bound function's outgoing call with no context then we should compile it as
+ fully polymorphic but we can let it assume basic sanity like that the callee is a real
+ function; but if we're compiling the call with any amount of calling context then we want to
+ use normal call IC's.
+
+ Since the builtin path wouldn't lead to a simpler patch and since I think that the VM will
+ benefit in the long run from using custom handling for bound functions, I kept the native
+ code and just added Intrinsic/thunk support.
+
+ This just adds an Intrinsic for bound function calls where the JSBoundFunction targets a
+ JSFunction instance and has no bound arguments (only bound this). This intrinsic is
+ currently only implemented as a thunk and not yet recognized by the DFG bytecode parser.
+
+ I needed to loosen some restrictions to do this. For one, I was really tired of our bad use
+ of ENABLE(JIT) conditionals, which made it so that any serious client of Intrinsics would
+ have to have #ifdefs. Really what should happen is that if the JIT is not enabled then we
+ just ignore intrinsics. Also, the code was previously assuming that having a native
+ constructor and knowing the Intrinsic for your native call were mutually exclusive. This
+ change makes it possible to have a native executable that has a custom function, custom
+ constructor, and an Intrinsic.
+
+ This is a >4x speed-up on bound function calls with no bound arguments.
+
+ In the future, we should teach the DFG Intrinsic handling to deal with bound functions and
+ we should teach the inliner (and ByteCodeParser::handleCall() in general) how to deal with
+ the function call inside the bound function. That would be super awesome.
+
+ * assembler/AbstractMacroAssembler.h:
+ (JSC::AbstractMacroAssembler::timesPtr):
+ (JSC::AbstractMacroAssembler::Address::withOffset):
+ (JSC::AbstractMacroAssembler::BaseIndex::BaseIndex):
+ (JSC::MacroAssemblerType>::Address::indexedBy):
+ * jit/AssemblyHelpers.h:
+ (JSC::AssemblyHelpers::storeCell):
+ (JSC::AssemblyHelpers::loadCell):
+ (JSC::AssemblyHelpers::storeValue):
+ (JSC::AssemblyHelpers::emitSaveCalleeSaves):
+ (JSC::AssemblyHelpers::emitSaveThenMaterializeTagRegisters):
+ (JSC::AssemblyHelpers::emitRestoreCalleeSaves):
+ (JSC::AssemblyHelpers::emitRestoreSavedTagRegisters):
+ (JSC::AssemblyHelpers::copyCalleeSavesToVMCalleeSavesBuffer):
+ * jit/JITThunks.cpp:
+ (JSC::JITThunks::ctiNativeTailCall):
+ (JSC::JITThunks::ctiNativeTailCallWithoutSavedTags):
+ (JSC::JITThunks::ctiStub):
+ (JSC::JITThunks::hostFunctionStub):
+ (JSC::JITThunks::clearHostFunctionStubs):
+ * jit/JITThunks.h:
+ * jit/SpecializedThunkJIT.h:
+ (JSC::SpecializedThunkJIT::callDoubleToDoublePreservingReturn):
+ (JSC::SpecializedThunkJIT::tagReturnAsInt32):
+ (JSC::SpecializedThunkJIT::emitSaveThenMaterializeTagRegisters): Deleted.
+ (JSC::SpecializedThunkJIT::emitRestoreSavedTagRegisters): Deleted.
+ * jit/ThunkGenerators.cpp:
+ (JSC::virtualThunkFor):
+ (JSC::nativeForGenerator):
+ (JSC::nativeCallGenerator):
+ (JSC::nativeTailCallGenerator):
+ (JSC::nativeTailCallWithoutSavedTagsGenerator):
+ (JSC::nativeConstructGenerator):
+ (JSC::randomThunkGenerator):
+ (JSC::boundThisNoArgsFunctionCallGenerator):
+ * jit/ThunkGenerators.h:
+ * runtime/Executable.cpp:
+ (JSC::NativeExecutable::create):
+ (JSC::NativeExecutable::destroy):
+ (JSC::NativeExecutable::createStructure):
+ (JSC::NativeExecutable::finishCreation):
+ (JSC::NativeExecutable::NativeExecutable):
+ (JSC::ScriptExecutable::ScriptExecutable):
+ * runtime/Executable.h:
+ * runtime/FunctionPrototype.cpp:
+ (JSC::functionProtoFuncBind):
+ * runtime/IntlCollatorPrototype.cpp:
+ (JSC::IntlCollatorPrototypeGetterCompare):
+ * runtime/Intrinsic.h:
+ * runtime/JSBoundFunction.cpp:
+ (JSC::boundThisNoArgsFunctionCall):
+ (JSC::boundFunctionCall):
+ (JSC::boundThisNoArgsFunctionConstruct):
+ (JSC::boundFunctionConstruct):
+ (JSC::getBoundFunctionStructure):
+ (JSC::JSBoundFunction::create):
+ (JSC::JSBoundFunction::customHasInstance):
+ (JSC::JSBoundFunction::JSBoundFunction):
+ * runtime/JSBoundFunction.h:
+ (JSC::JSBoundFunction::targetFunction):
+ (JSC::JSBoundFunction::boundThis):
+ (JSC::JSBoundFunction::boundArgs):
+ (JSC::JSBoundFunction::createStructure):
+ (JSC::JSBoundFunction::offsetOfTargetFunction):
+ (JSC::JSBoundFunction::offsetOfBoundThis):
+ * runtime/JSFunction.cpp:
+ (JSC::JSFunction::lookUpOrCreateNativeExecutable):
+ (JSC::JSFunction::create):
+ * runtime/VM.cpp:
+ (JSC::thunkGeneratorForIntrinsic):
+ (JSC::VM::getHostFunction):
+ * runtime/VM.h:
+ (JSC::VM::getCTIStub):
+ (JSC::VM::exceptionOffset):
+
2016-04-22 Joonghun Park <jh718.p...@samsung.com>
[JSC] Fix build break since r199866
Modified: trunk/Source/_javascript_Core/assembler/AbstractMacroAssembler.h (199945 => 199946)
--- trunk/Source/_javascript_Core/assembler/AbstractMacroAssembler.h 2016-04-23 01:14:02 UTC (rev 199945)
+++ trunk/Source/_javascript_Core/assembler/AbstractMacroAssembler.h 2016-04-23 02:00:38 UTC (rev 199946)
@@ -143,7 +143,9 @@
return TimesFour;
return TimesEight;
}
-
+
+ struct BaseIndex;
+
// Address:
//
// Describes a simple base-offset address.
@@ -159,6 +161,8 @@
return Address(base, offset + additionalOffset);
}
+ BaseIndex indexedBy(RegisterID index, Scale) const;
+
RegisterID base;
int32_t offset;
};
@@ -216,7 +220,7 @@
, offset(offset)
{
}
-
+
RegisterID base;
RegisterID index;
Scale scale;
@@ -1144,6 +1148,15 @@
friend class LinkBuffer;
}; // class AbstractMacroAssembler
+template <class AssemblerType, class MacroAssemblerType>
+inline typename AbstractMacroAssembler<AssemblerType, MacroAssemblerType>::BaseIndex
+AbstractMacroAssembler<AssemblerType, MacroAssemblerType>::Address::indexedBy(
+ typename AbstractMacroAssembler<AssemblerType, MacroAssemblerType>::RegisterID index,
+ typename AbstractMacroAssembler<AssemblerType, MacroAssemblerType>::Scale scale) const
+{
+ return BaseIndex(base, index, scale, offset);
+}
+
} // namespace JSC
#endif // ENABLE(ASSEMBLER)
Modified: trunk/Source/_javascript_Core/jit/AssemblyHelpers.h (199945 => 199946)
--- trunk/Source/_javascript_Core/jit/AssemblyHelpers.h 2016-04-23 01:14:02 UTC (rev 199945)
+++ trunk/Source/_javascript_Core/jit/AssemblyHelpers.h 2016-04-23 02:00:38 UTC (rev 199946)
@@ -85,6 +85,15 @@
#endif
}
+ void loadCell(Address address, GPRReg gpr)
+ {
+#if USE(JSVALUE64)
+ load64(address, gpr);
+#else
+ load32(address.withOffset(PayloadOffset), gpr);
+#endif
+ }
+
void storeValue(JSValueRegs regs, Address address)
{
#if USE(JSVALUE64)
@@ -274,11 +283,36 @@
emitSaveCalleeSavesFor(codeBlock());
}
+ void emitSaveThenMaterializeTagRegisters()
+ {
+#if USE(JSVALUE64)
+#if CPU(ARM64)
+ pushPair(GPRInfo::tagTypeNumberRegister, GPRInfo::tagMaskRegister);
+#else
+ push(GPRInfo::tagTypeNumberRegister);
+ push(GPRInfo::tagMaskRegister);
+#endif
+ emitMaterializeTagCheckRegisters();
+#endif
+ }
+
void emitRestoreCalleeSaves()
{
emitRestoreCalleeSavesFor(codeBlock());
}
+ void emitRestoreSavedTagRegisters()
+ {
+#if USE(JSVALUE64)
+#if CPU(ARM64)
+ popPair(GPRInfo::tagTypeNumberRegister, GPRInfo::tagMaskRegister);
+#else
+ pop(GPRInfo::tagMaskRegister);
+ pop(GPRInfo::tagTypeNumberRegister);
+#endif
+#endif
+ }
+
void copyCalleeSavesToVMCalleeSavesBuffer(const TempRegisterSet& usedRegisters = { RegisterSet::stubUnavailableRegisters() })
{
#if NUMBER_OF_CALLEE_SAVES_REGISTERS > 0
Modified: trunk/Source/_javascript_Core/jit/JITThunks.cpp (199945 => 199946)
--- trunk/Source/_javascript_Core/jit/JITThunks.cpp 2016-04-23 01:14:02 UTC (rev 199945)
+++ trunk/Source/_javascript_Core/jit/JITThunks.cpp 2016-04-23 02:00:38 UTC (rev 199946)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012, 2013, 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2012, 2013, 2015-2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -64,6 +64,12 @@
return ctiStub(vm, nativeTailCallGenerator).code();
}
+MacroAssemblerCodePtr JITThunks::ctiNativeTailCallWithoutSavedTags(VM* vm)
+{
+ ASSERT(vm->canUseJIT());
+ return ctiStub(vm, nativeTailCallWithoutSavedTagsGenerator).code();
+}
+
MacroAssemblerCodeRef JITThunks::ctiStub(VM* vm, ThunkGenerator generator)
{
LockHolder locker(m_lock);
@@ -84,27 +90,15 @@
NativeExecutable* JITThunks::hostFunctionStub(VM* vm, NativeFunction function, NativeFunction constructor, const String& name)
{
- ASSERT(!isCompilationThread());
-
- if (NativeExecutable* nativeExecutable = m_hostFunctionStubMap->get(std::make_tuple(function, constructor, name)))
- return nativeExecutable;
-
- NativeExecutable* nativeExecutable = NativeExecutable::create(
- *vm,
- adoptRef(new NativeJITCode(JIT::compileCTINativeCall(vm, function), JITCode::HostCallThunk)),
- function,
- adoptRef(new NativeJITCode(MacroAssemblerCodeRef::createSelfManagedCodeRef(ctiNativeConstruct(vm)), JITCode::HostCallThunk)),
- constructor, NoIntrinsic, name);
- weakAdd(*m_hostFunctionStubMap, std::make_tuple(function, constructor, name), Weak<NativeExecutable>(nativeExecutable, this));
- return nativeExecutable;
+ return hostFunctionStub(vm, function, constructor, nullptr, NoIntrinsic, name);
}
-NativeExecutable* JITThunks::hostFunctionStub(VM* vm, NativeFunction function, ThunkGenerator generator, Intrinsic intrinsic, const String& name)
+NativeExecutable* JITThunks::hostFunctionStub(VM* vm, NativeFunction function, NativeFunction constructor, ThunkGenerator generator, Intrinsic intrinsic, const String& name)
{
ASSERT(!isCompilationThread());
ASSERT(vm->canUseJIT());
- if (NativeExecutable* nativeExecutable = m_hostFunctionStubMap->get(std::make_tuple(function, &callHostFunctionAsConstructor, name)))
+ if (NativeExecutable* nativeExecutable = m_hostFunctionStubMap->get(std::make_tuple(function, constructor, name)))
return nativeExecutable;
RefPtr<JITCode> forCall;
@@ -116,11 +110,16 @@
RefPtr<JITCode> forConstruct = adoptRef(new NativeJITCode(MacroAssemblerCodeRef::createSelfManagedCodeRef(ctiNativeConstruct(vm)), JITCode::HostCallThunk));
- NativeExecutable* nativeExecutable = NativeExecutable::create(*vm, forCall, function, forConstruct, callHostFunctionAsConstructor, intrinsic, name);
- weakAdd(*m_hostFunctionStubMap, std::make_tuple(function, &callHostFunctionAsConstructor, name), Weak<NativeExecutable>(nativeExecutable, this));
+ NativeExecutable* nativeExecutable = NativeExecutable::create(*vm, forCall, function, forConstruct, constructor, intrinsic, name);
+ weakAdd(*m_hostFunctionStubMap, std::make_tuple(function, constructor, name), Weak<NativeExecutable>(nativeExecutable, this));
return nativeExecutable;
}
+NativeExecutable* JITThunks::hostFunctionStub(VM* vm, NativeFunction function, ThunkGenerator generator, Intrinsic intrinsic, const String& name)
+{
+ return hostFunctionStub(vm, function, callHostFunctionAsConstructor, generator, intrinsic, name);
+}
+
void JITThunks::clearHostFunctionStubs()
{
m_hostFunctionStubMap = nullptr;
Modified: trunk/Source/_javascript_Core/jit/JITThunks.h (199945 => 199946)
--- trunk/Source/_javascript_Core/jit/JITThunks.h 2016-04-23 01:14:02 UTC (rev 199945)
+++ trunk/Source/_javascript_Core/jit/JITThunks.h 2016-04-23 02:00:38 UTC (rev 199946)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2012, 2013, 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -55,10 +55,12 @@
MacroAssemblerCodePtr ctiNativeCall(VM*);
MacroAssemblerCodePtr ctiNativeConstruct(VM*);
MacroAssemblerCodePtr ctiNativeTailCall(VM*);
+ MacroAssemblerCodePtr ctiNativeTailCallWithoutSavedTags(VM*);
MacroAssemblerCodeRef ctiStub(VM*, ThunkGenerator);
NativeExecutable* hostFunctionStub(VM*, NativeFunction, NativeFunction constructor, const String& name);
+ NativeExecutable* hostFunctionStub(VM*, NativeFunction, NativeFunction constructor, ThunkGenerator, Intrinsic, const String& name);
NativeExecutable* hostFunctionStub(VM*, NativeFunction, ThunkGenerator, Intrinsic, const String& name);
void clearHostFunctionStubs();
Modified: trunk/Source/_javascript_Core/jit/SpecializedThunkJIT.h (199945 => 199946)
--- trunk/Source/_javascript_Core/jit/SpecializedThunkJIT.h 2016-04-23 01:14:02 UTC (rev 199945)
+++ trunk/Source/_javascript_Core/jit/SpecializedThunkJIT.h 2016-04-23 02:00:38 UTC (rev 199946)
@@ -193,31 +193,6 @@
}
private:
- void emitSaveThenMaterializeTagRegisters()
- {
-#if USE(JSVALUE64)
-#if CPU(ARM64)
- pushPair(tagTypeNumberRegister, tagMaskRegister);
-#else
- push(tagTypeNumberRegister);
- push(tagMaskRegister);
-#endif
- emitMaterializeTagCheckRegisters();
-#endif
- }
-
- void emitRestoreSavedTagRegisters()
- {
-#if USE(JSVALUE64)
-#if CPU(ARM64)
- popPair(tagTypeNumberRegister, tagMaskRegister);
-#else
- pop(tagMaskRegister);
- pop(tagTypeNumberRegister);
-#endif
-#endif
- }
-
void tagReturnAsInt32()
{
#if USE(JSVALUE64)
Modified: trunk/Source/_javascript_Core/jit/ThunkGenerators.cpp (199945 => 199946)
--- trunk/Source/_javascript_Core/jit/ThunkGenerators.cpp 2016-04-23 01:14:02 UTC (rev 199945)
+++ trunk/Source/_javascript_Core/jit/ThunkGenerators.cpp 2016-04-23 02:00:38 UTC (rev 199946)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010, 2012, 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2010, 2012, 2013, 2014, 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -31,6 +31,7 @@
#include "JITOperations.h"
#include "JSArray.h"
#include "JSArrayIterator.h"
+#include "JSBoundFunction.h"
#include "JSStack.h"
#include "MathCommon.h"
#include "MaxFrameExtentForSlowPathCall.h"
@@ -227,7 +228,7 @@
callLinkInfo.callMode() == CallMode::Regular ? "call" : callLinkInfo.callMode() == CallMode::Tail ? "tail call" : "construct"));
}
-enum ThunkEntryType { EnterViaCall, EnterViaJump };
+enum ThunkEntryType { EnterViaCall, EnterViaJumpWithSavedTags, EnterViaJumpWithoutSavedTags };
static MacroAssemblerCodeRef nativeForGenerator(VM* vm, CodeSpecializationKind kind, ThunkEntryType entryType = EnterViaCall)
{
@@ -238,10 +239,12 @@
JSInterfaceJIT jit(vm);
- if (entryType == EnterViaCall)
+ switch (entryType) {
+ case EnterViaCall:
jit.emitFunctionPrologue();
+ break;
+ case EnterViaJumpWithSavedTags:
#if USE(JSVALUE64)
- else if (entryType == EnterViaJump) {
// We're coming from a specialized thunk that has saved the prior tag registers' contents.
// Restore them now.
#if CPU(ARM64)
@@ -250,8 +253,12 @@
jit.pop(JSInterfaceJIT::tagMaskRegister);
jit.pop(JSInterfaceJIT::tagTypeNumberRegister);
#endif
+#endif
+ break;
+ case EnterViaJumpWithoutSavedTags:
+ jit.move(JSInterfaceJIT::framePointerRegister, JSInterfaceJIT::stackPointerRegister);
+ break;
}
-#endif
jit.emitPutToCallFrameHeader(0, JSStack::CodeBlock);
jit.storePtr(JSInterfaceJIT::callFrameRegister, &vm->topCallFrame);
@@ -374,7 +381,7 @@
jit.jumpToExceptionHandler();
LinkBuffer patchBuffer(*vm, jit, GLOBAL_THUNK_ID);
- return FINALIZE_CODE(patchBuffer, ("native %s%s trampoline", entryType == EnterViaJump ? "Tail " : "", toCString(kind).data()));
+ return FINALIZE_CODE(patchBuffer, ("native %s%s trampoline", entryType == EnterViaJumpWithSavedTags ? "Tail With Saved Tags " : entryType == EnterViaJumpWithoutSavedTags ? "Tail Without Saved Tags " : "", toCString(kind).data()));
}
MacroAssemblerCodeRef nativeCallGenerator(VM* vm)
@@ -384,9 +391,14 @@
MacroAssemblerCodeRef nativeTailCallGenerator(VM* vm)
{
- return nativeForGenerator(vm, CodeForCall, EnterViaJump);
+ return nativeForGenerator(vm, CodeForCall, EnterViaJumpWithSavedTags);
}
+MacroAssemblerCodeRef nativeTailCallWithoutSavedTagsGenerator(VM* vm)
+{
+ return nativeForGenerator(vm, CodeForCall, EnterViaJumpWithoutSavedTags);
+}
+
MacroAssemblerCodeRef nativeConstructGenerator(VM* vm)
{
return nativeForGenerator(vm, CodeForConstruct);
@@ -1079,6 +1091,97 @@
#endif
}
+MacroAssemblerCodeRef boundThisNoArgsFunctionCallGenerator(VM* vm)
+{
+ CCallHelpers jit(vm);
+
+ jit.emitFunctionPrologue();
+
+ // Set up our call frame.
+ jit.storePtr(CCallHelpers::TrustedImmPtr(nullptr), CCallHelpers::addressFor(JSStack::CodeBlock));
+ jit.store32(CCallHelpers::TrustedImm32(0), CCallHelpers::tagFor(JSStack::ArgumentCount));
+
+ unsigned extraStackNeeded = 0;
+ if (unsigned stackMisalignment = sizeof(CallerFrameAndPC) % stackAlignmentBytes())
+ extraStackNeeded = stackAlignmentBytes() - stackMisalignment;
+
+ // We need to forward all of the arguments that we were passed. We aren't allowed to do a tail
+ // call here as far as I can tell. At least not so long as the generic path doesn't do a tail
+ // call, since that would be way too weird.
+
+ // The formula for the number of stack bytes needed given some number of parameters (including
+ // this) is:
+ //
+ // stackAlign((numParams + CallFrameHeaderSize) * sizeof(Register) - sizeof(CallerFrameAndPC))
+ //
+ // Probably we want to write this as:
+ //
+ // stackAlign((numParams + (CallFrameHeaderSize - CallerFrameAndPCSize)) * sizeof(Register))
+ //
+ // That's really all there is to this. We have all the registers we need to do it.
+
+ jit.load32(CCallHelpers::payloadFor(JSStack::ArgumentCount), GPRInfo::regT1);
+ jit.add32(CCallHelpers::TrustedImm32(JSStack::CallFrameHeaderSize - JSStack::CallerFrameAndPCSize), GPRInfo::regT1, GPRInfo::regT2);
+ jit.lshift32(CCallHelpers::TrustedImm32(3), GPRInfo::regT2);
+ jit.add32(CCallHelpers::TrustedImm32(stackAlignmentBytes() - 1), GPRInfo::regT2);
+ jit.and32(CCallHelpers::TrustedImm32(-stackAlignmentBytes()), GPRInfo::regT2);
+
+ if (extraStackNeeded)
+ jit.add32(CCallHelpers::TrustedImm32(extraStackNeeded), GPRInfo::regT2);
+
+ // At this point regT1 has the actual argument count and regT2 has the amount of stack we will
+ // need.
+
+ jit.subPtr(GPRInfo::regT2, CCallHelpers::stackPointerRegister);
+
+ // Do basic callee frame setup, including 'this'.
+
+ jit.loadCell(CCallHelpers::addressFor(JSStack::Callee), GPRInfo::regT3);
+
+ jit.store32(GPRInfo::regT1, CCallHelpers::calleeFramePayloadSlot(JSStack::ArgumentCount));
+
+ JSValueRegs valueRegs = JSValueRegs::withTwoAvailableRegs(GPRInfo::regT0, GPRInfo::regT2);
+ jit.loadValue(CCallHelpers::Address(GPRInfo::regT3, JSBoundFunction::offsetOfBoundThis()), valueRegs);
+ jit.storeValue(valueRegs, CCallHelpers::calleeArgumentSlot(0));
+
+ jit.loadPtr(CCallHelpers::Address(GPRInfo::regT3, JSBoundFunction::offsetOfTargetFunction()), GPRInfo::regT3);
+ jit.storeCell(GPRInfo::regT3, CCallHelpers::calleeFrameSlot(JSStack::Callee));
+
+ // OK, now we can start copying. This is a simple matter of copying parameters from the caller's
+ // frame to the callee's frame. Note that we know that regT1 (the argument count) must be at
+ // least 1.
+ jit.sub32(CCallHelpers::TrustedImm32(1), GPRInfo::regT1);
+ CCallHelpers::Jump done = jit.branchTest32(CCallHelpers::Zero, GPRInfo::regT1);
+
+ CCallHelpers::Label loop = jit.label();
+ jit.sub32(CCallHelpers::TrustedImm32(1), GPRInfo::regT1);
+ jit.loadValue(CCallHelpers::addressFor(virtualRegisterForArgument(1)).indexedBy(GPRInfo::regT1, CCallHelpers::TimesEight), valueRegs);
+ jit.storeValue(valueRegs, CCallHelpers::calleeArgumentSlot(1).indexedBy(GPRInfo::regT1, CCallHelpers::TimesEight));
+ jit.branchTest32(CCallHelpers::NonZero, GPRInfo::regT1).linkTo(loop, &jit);
+
+ done.link(&jit);
+
+ jit.loadPtr(
+ CCallHelpers::Address(GPRInfo::regT3, JSFunction::offsetOfExecutable()),
+ GPRInfo::regT0);
+ jit.loadPtr(
+ CCallHelpers::Address(
+ GPRInfo::regT0, ExecutableBase::offsetOfJITCodeWithArityCheckFor(CodeForCall)),
+ GPRInfo::regT0);
+ CCallHelpers::Jump noCode = jit.branchTestPtr(CCallHelpers::Zero, GPRInfo::regT0);
+
+ emitPointerValidation(jit, GPRInfo::regT0);
+ jit.call(GPRInfo::regT0);
+
+ jit.emitFunctionEpilogue();
+ jit.ret();
+
+ LinkBuffer linkBuffer(*vm, jit, GLOBAL_THUNK_ID);
+ linkBuffer.link(noCode, CodeLocationLabel(vm->jitStubs->ctiNativeTailCallWithoutSavedTags(vm)));
+ return FINALIZE_CODE(
+ linkBuffer, ("Specialized thunk for bound function calls with no arguments"));
}
+} // namespace JSC
+
#endif // ENABLE(JIT)
Modified: trunk/Source/_javascript_Core/jit/ThunkGenerators.h (199945 => 199946)
--- trunk/Source/_javascript_Core/jit/ThunkGenerators.h 2016-04-23 01:14:02 UTC (rev 199945)
+++ trunk/Source/_javascript_Core/jit/ThunkGenerators.h 2016-04-23 02:00:38 UTC (rev 199946)
@@ -46,6 +46,7 @@
MacroAssemblerCodeRef nativeCallGenerator(VM*);
MacroAssemblerCodeRef nativeConstructGenerator(VM*);
MacroAssemblerCodeRef nativeTailCallGenerator(VM*);
+MacroAssemblerCodeRef nativeTailCallWithoutSavedTagsGenerator(VM*);
MacroAssemblerCodeRef arityFixupGenerator(VM*);
MacroAssemblerCodeRef unreachableGenerator(VM*);
@@ -65,6 +66,8 @@
MacroAssemblerCodeRef randomThunkGenerator(VM*);
MacroAssemblerCodeRef truncThunkGenerator(VM*);
+MacroAssemblerCodeRef boundThisNoArgsFunctionCallGenerator(VM* vm);
+
}
#endif // ENABLE(JIT)
Modified: trunk/Source/_javascript_Core/runtime/Executable.cpp (199945 => 199946)
--- trunk/Source/_javascript_Core/runtime/Executable.cpp 2016-04-23 01:14:02 UTC (rev 199945)
+++ trunk/Source/_javascript_Core/runtime/Executable.cpp 2016-04-23 02:00:38 UTC (rev 199946)
@@ -103,11 +103,41 @@
const ClassInfo NativeExecutable::s_info = { "NativeExecutable", &ExecutableBase::s_info, 0, CREATE_METHOD_TABLE(NativeExecutable) };
+NativeExecutable* NativeExecutable::create(VM& vm, PassRefPtr<JITCode> callThunk, NativeFunction function, PassRefPtr<JITCode> constructThunk, NativeFunction constructor, Intrinsic intrinsic, const String& name)
+{
+ NativeExecutable* executable;
+ executable = new (NotNull, allocateCell<NativeExecutable>(vm.heap)) NativeExecutable(vm, function, constructor, intrinsic);
+ executable->finishCreation(vm, callThunk, constructThunk, name);
+ return executable;
+}
+
void NativeExecutable::destroy(JSCell* cell)
{
static_cast<NativeExecutable*>(cell)->NativeExecutable::~NativeExecutable();
}
+Structure* NativeExecutable::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
+{
+ return Structure::create(vm, globalObject, proto, TypeInfo(CellType, StructureFlags), info());
+}
+
+void NativeExecutable::finishCreation(VM& vm, PassRefPtr<JITCode> callThunk, PassRefPtr<JITCode> constructThunk, const String& name)
+{
+ Base::finishCreation(vm);
+ m_jitCodeForCall = callThunk;
+ m_jitCodeForConstruct = constructThunk;
+ m_jitCodeForCallWithArityCheck = m_jitCodeForCall->addressForCall(MustCheckArity);
+ m_jitCodeForConstructWithArityCheck = m_jitCodeForConstruct->addressForCall(MustCheckArity);
+ m_name = name;
+}
+
+NativeExecutable::NativeExecutable(VM& vm, NativeFunction function, NativeFunction constructor, Intrinsic intrinsic)
+ : ExecutableBase(vm, vm.nativeExecutableStructure.get(), NUM_PARAMETERS_IS_HOST, intrinsic)
+ , m_function(function)
+ , m_constructor(constructor)
+{
+}
+
const ClassInfo ScriptExecutable::s_info = { "ScriptExecutable", &ExecutableBase::s_info, 0, CREATE_METHOD_TABLE(ScriptExecutable) };
ScriptExecutable::ScriptExecutable(Structure* structure, VM& vm, const SourceCode& source, bool isInStrictContext, DerivedContextType derivedContextType, bool isInArrowFunctionContext, EvalContextType evalContextType, Intrinsic intrinsic)
Modified: trunk/Source/_javascript_Core/runtime/Executable.h (199945 => 199946)
--- trunk/Source/_javascript_Core/runtime/Executable.h 2016-04-23 01:14:02 UTC (rev 199945)
+++ trunk/Source/_javascript_Core/runtime/Executable.h 2016-04-23 02:00:38 UTC (rev 199946)
@@ -258,13 +258,7 @@
typedef ExecutableBase Base;
static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
- static NativeExecutable* create(VM& vm, PassRefPtr<JITCode> callThunk, NativeFunction function, PassRefPtr<JITCode> constructThunk, NativeFunction constructor, Intrinsic intrinsic, const String& name)
- {
- NativeExecutable* executable;
- executable = new (NotNull, allocateCell<NativeExecutable>(vm.heap)) NativeExecutable(vm, function, constructor, intrinsic);
- executable->finishCreation(vm, callThunk, constructThunk, name);
- return executable;
- }
+ static NativeExecutable* create(VM& vm, PassRefPtr<JITCode> callThunk, NativeFunction function, PassRefPtr<JITCode> constructThunk, NativeFunction constructor, Intrinsic intrinsic, const String& name);
static void destroy(JSCell*);
@@ -289,7 +283,7 @@
return OBJECT_OFFSETOF(NativeExecutable, m_constructor);
}
- static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(CellType, StructureFlags), info()); }
+ static Structure* createStructure(VM&, JSGlobalObject*, JSValue proto);
DECLARE_INFO;
@@ -298,23 +292,12 @@
const String& name() const { return m_name; }
protected:
- void finishCreation(VM& vm, PassRefPtr<JITCode> callThunk, PassRefPtr<JITCode> constructThunk, const String& name)
- {
- Base::finishCreation(vm);
- m_jitCodeForCall = callThunk;
- m_jitCodeForConstruct = constructThunk;
- m_name = name;
- }
+ void finishCreation(VM&, PassRefPtr<JITCode> callThunk, PassRefPtr<JITCode> constructThunk, const String& name);
private:
friend class ExecutableBase;
- NativeExecutable(VM& vm, NativeFunction function, NativeFunction constructor, Intrinsic intrinsic)
- : ExecutableBase(vm, vm.nativeExecutableStructure.get(), NUM_PARAMETERS_IS_HOST, intrinsic)
- , m_function(function)
- , m_constructor(constructor)
- {
- }
+ NativeExecutable(VM&, NativeFunction function, NativeFunction constructor, Intrinsic);
NativeFunction m_function;
NativeFunction m_constructor;
Modified: trunk/Source/_javascript_Core/runtime/FunctionPrototype.cpp (199945 => 199946)
--- trunk/Source/_javascript_Core/runtime/FunctionPrototype.cpp 2016-04-23 01:14:02 UTC (rev 199945)
+++ trunk/Source/_javascript_Core/runtime/FunctionPrototype.cpp 2016-04-23 02:00:38 UTC (rev 199946)
@@ -141,13 +141,17 @@
// Let A be a new (possibly empty) internal list of all of the argument values provided after thisArg (arg1, arg2 etc), in order.
size_t numBoundArgs = exec->argumentCount() > 1 ? exec->argumentCount() - 1 : 0;
- JSArray* boundArgs = JSArray::tryCreateUninitialized(vm, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithUndecided), numBoundArgs);
- if (!boundArgs)
- return JSValue::encode(throwOutOfMemoryError(exec));
+ JSArray* boundArgs;
+ if (numBoundArgs) {
+ boundArgs = JSArray::tryCreateUninitialized(vm, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous), numBoundArgs);
+ if (!boundArgs)
+ return JSValue::encode(throwOutOfMemoryError(exec));
+
+ for (size_t i = 0; i < numBoundArgs; ++i)
+ boundArgs->initializeIndex(vm, i, exec->argument(i + 1));
+ } else
+ boundArgs = nullptr;
- for (size_t i = 0; i < numBoundArgs; ++i)
- boundArgs->initializeIndex(vm, i, exec->argument(i + 1));
-
// If the [[Class]] internal property of Target is "Function", then ...
// Else set the length own property of F to 0.
unsigned length = 0;
Modified: trunk/Source/_javascript_Core/runtime/IntlCollatorPrototype.cpp (199945 => 199946)
--- trunk/Source/_javascript_Core/runtime/IntlCollatorPrototype.cpp 2016-04-23 01:14:02 UTC (rev 199945)
+++ trunk/Source/_javascript_Core/runtime/IntlCollatorPrototype.cpp 2016-04-23 02:00:38 UTC (rev 199946)
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 Andy VanWagoner (thetalecraf...@gmail.com)
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -124,12 +125,9 @@
// a. Let F be a new built-in function object as defined in 11.3.4.
// b. The value of F’s length property is 2.
JSFunction* targetObject = JSFunction::create(vm, globalObject, 2, ASCIILiteral("compare"), IntlCollatorFuncCompare, NoIntrinsic);
- JSArray* boundArgs = JSArray::tryCreateUninitialized(vm, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithUndecided), 0);
- if (!boundArgs)
- return JSValue::encode(throwOutOfMemoryError(state));
// c. Let bc be BoundFunctionCreate(F, «this value»).
- boundCompare = JSBoundFunction::create(vm, state, globalObject, targetObject, collator, boundArgs, 2, ASCIILiteral("compare"));
+ boundCompare = JSBoundFunction::create(vm, state, globalObject, targetObject, collator, nullptr, 2, ASCIILiteral("compare"));
if (vm.exception())
return JSValue::encode(JSValue());
// d. Set collator.[[boundCompare]] to bc.
Modified: trunk/Source/_javascript_Core/runtime/Intrinsic.h (199945 => 199946)
--- trunk/Source/_javascript_Core/runtime/Intrinsic.h 2016-04-23 01:14:02 UTC (rev 199945)
+++ trunk/Source/_javascript_Core/runtime/Intrinsic.h 2016-04-23 02:00:38 UTC (rev 199946)
@@ -61,6 +61,7 @@
IsArrayConstructorIntrinsic,
IsJSArrayIntrinsic,
IsRegExpObjectIntrinsic,
+ BoundThisNoArgsFunctionCallIntrinsic,
// Getter intrinsics.
TypedArrayLengthIntrinsic,
Modified: trunk/Source/_javascript_Core/runtime/JSBoundFunction.cpp (199945 => 199946)
--- trunk/Source/_javascript_Core/runtime/JSBoundFunction.cpp 2016-04-23 01:14:02 UTC (rev 199945)
+++ trunk/Source/_javascript_Core/runtime/JSBoundFunction.cpp 2016-04-23 02:00:38 UTC (rev 199946)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -34,16 +34,37 @@
const ClassInfo JSBoundFunction::s_info = { "Function", &Base::s_info, 0, CREATE_METHOD_TABLE(JSBoundFunction) };
+EncodedJSValue JSC_HOST_CALL boundThisNoArgsFunctionCall(ExecState* exec)
+{
+ JSBoundFunction* boundFunction = jsCast<JSBoundFunction*>(exec->callee());
+
+ MarkedArgumentBuffer args;
+ for (unsigned i = 0; i < exec->argumentCount(); ++i)
+ args.append(exec->uncheckedArgument(i));
+
+ JSFunction* targetFunction = jsCast<JSFunction*>(boundFunction->targetFunction());
+ ExecutableBase* executable = targetFunction->executable();
+ if (executable->hasJITCodeForCall()) {
+ // Force the executable to cache its arity entrypoint.
+ executable->entrypointFor(CodeForCall, MustCheckArity);
+ }
+ CallData callData;
+ CallType callType = getCallData(targetFunction, callData);
+ ASSERT(callType != CallType::None);
+ return JSValue::encode(call(exec, targetFunction, callType, callData, boundFunction->boundThis(), args));
+}
+
EncodedJSValue JSC_HOST_CALL boundFunctionCall(ExecState* exec)
{
JSBoundFunction* boundFunction = jsCast<JSBoundFunction*>(exec->callee());
- ASSERT(isJSArray(boundFunction->boundArgs())); // Currently this is true!
- JSArray* boundArgs = asArray(boundFunction->boundArgs());
+ JSArray* boundArgs = boundFunction->boundArgs();
MarkedArgumentBuffer args;
- for (unsigned i = 0; i < boundArgs->length(); ++i)
- args.append(boundArgs->getIndexQuickly(i));
+ if (boundArgs) {
+ for (unsigned i = 0; i < boundArgs->length(); ++i)
+ args.append(boundArgs->getIndexQuickly(i));
+ }
for (unsigned i = 0; i < exec->argumentCount(); ++i)
args.append(exec->uncheckedArgument(i));
@@ -54,16 +75,32 @@
return JSValue::encode(call(exec, targetFunction, callType, callData, boundFunction->boundThis(), args));
}
+EncodedJSValue JSC_HOST_CALL boundThisNoArgsFunctionConstruct(ExecState* exec)
+{
+ JSBoundFunction* boundFunction = jsCast<JSBoundFunction*>(exec->callee());
+
+ MarkedArgumentBuffer args;
+ for (unsigned i = 0; i < exec->argumentCount(); ++i)
+ args.append(exec->uncheckedArgument(i));
+
+ JSFunction* targetFunction = jsCast<JSFunction*>(boundFunction->targetFunction());
+ ConstructData constructData;
+ ConstructType constructType = getConstructData(targetFunction, constructData);
+ ASSERT(constructType != ConstructType::None);
+ return JSValue::encode(construct(exec, targetFunction, constructType, constructData, args));
+}
+
EncodedJSValue JSC_HOST_CALL boundFunctionConstruct(ExecState* exec)
{
JSBoundFunction* boundFunction = jsCast<JSBoundFunction*>(exec->callee());
- ASSERT(isJSArray(boundFunction->boundArgs())); // Currently this is true!
- JSArray* boundArgs = asArray(boundFunction->boundArgs());
+ JSArray* boundArgs = boundFunction->boundArgs();
MarkedArgumentBuffer args;
- for (unsigned i = 0; i < boundArgs->length(); ++i)
- args.append(boundArgs->getIndexQuickly(i));
+ if (boundArgs) {
+ for (unsigned i = 0; i < boundArgs->length(); ++i)
+ args.append(boundArgs->getIndexQuickly(i));
+ }
for (unsigned i = 0; i < exec->argumentCount(); ++i)
args.append(exec->uncheckedArgument(i));
@@ -119,12 +156,19 @@
return result;
}
-JSBoundFunction* JSBoundFunction::create(VM& vm, ExecState* exec, JSGlobalObject* globalObject, JSObject* targetFunction, JSValue boundThis, JSValue boundArgs, int length, const String& name)
+JSBoundFunction* JSBoundFunction::create(VM& vm, ExecState* exec, JSGlobalObject* globalObject, JSObject* targetFunction, JSValue boundThis, JSArray* boundArgs, int length, const String& name)
{
ConstructData constructData;
ConstructType constructType = JSC::getConstructData(targetFunction, constructData);
bool canConstruct = constructType != ConstructType::None;
- NativeExecutable* executable = vm.getHostFunction(boundFunctionCall, canConstruct ? boundFunctionConstruct : callHostFunctionAsConstructor, name);
+
+ bool slowCase = boundArgs || !getJSFunction(targetFunction);
+
+ NativeExecutable* executable = vm.getHostFunction(
+ slowCase ? boundFunctionCall : boundThisNoArgsFunctionCall,
+ slowCase ? NoIntrinsic : BoundThisNoArgsFunctionCallIntrinsic,
+ canConstruct ? (slowCase ? boundFunctionConstruct : boundThisNoArgsFunctionConstruct) : callHostFunctionAsConstructor,
+ name);
Structure* structure = getBoundFunctionStructure(vm, exec, globalObject, targetFunction);
if (UNLIKELY(vm.exception()))
return nullptr;
@@ -139,11 +183,11 @@
return jsCast<JSBoundFunction*>(object)->m_targetFunction->hasInstance(exec, value);
}
-JSBoundFunction::JSBoundFunction(VM& vm, JSGlobalObject* globalObject, Structure* structure, JSObject* targetFunction, JSValue boundThis, JSValue boundArgs)
+JSBoundFunction::JSBoundFunction(VM& vm, JSGlobalObject* globalObject, Structure* structure, JSObject* targetFunction, JSValue boundThis, JSArray* boundArgs)
: Base(vm, globalObject, structure)
, m_targetFunction(vm, this, targetFunction)
, m_boundThis(vm, this, boundThis)
- , m_boundArgs(vm, this, boundArgs)
+ , m_boundArgs(vm, this, boundArgs, WriteBarrier<JSArray>::MayBeNull)
{
}
Modified: trunk/Source/_javascript_Core/runtime/JSBoundFunction.h (199945 => 199946)
--- trunk/Source/_javascript_Core/runtime/JSBoundFunction.h 2016-04-23 01:14:02 UTC (rev 199945)
+++ trunk/Source/_javascript_Core/runtime/JSBoundFunction.h 2016-04-23 02:00:38 UTC (rev 199946)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -30,7 +30,9 @@
namespace JSC {
+EncodedJSValue JSC_HOST_CALL boundThisNoArgsFunctionCall(ExecState*);
EncodedJSValue JSC_HOST_CALL boundFunctionCall(ExecState*);
+EncodedJSValue JSC_HOST_CALL boundThisNoArgsFunctionConstruct(ExecState*);
EncodedJSValue JSC_HOST_CALL boundFunctionConstruct(ExecState*);
EncodedJSValue JSC_HOST_CALL isBoundFunction(ExecState*);
EncodedJSValue JSC_HOST_CALL hasInstanceBoundFunction(ExecState*);
@@ -40,19 +42,22 @@
typedef JSFunction Base;
const static unsigned StructureFlags = ~ImplementsDefaultHasInstance & Base::StructureFlags;
- static JSBoundFunction* create(VM&, ExecState*, JSGlobalObject*, JSObject* targetFunction, JSValue boundThis, JSValue boundArgs, int, const String& name);
+ static JSBoundFunction* create(VM&, ExecState*, JSGlobalObject*, JSObject* targetFunction, JSValue boundThis, JSArray* boundArgs, int, const String& name);
static bool customHasInstance(JSObject*, ExecState*, JSValue);
JSObject* targetFunction() { return m_targetFunction.get(); }
JSValue boundThis() { return m_boundThis.get(); }
- JSValue boundArgs() { return m_boundArgs.get(); }
+ JSArray* boundArgs() { return m_boundArgs.get(); }
static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
{
ASSERT(globalObject);
return Structure::create(vm, globalObject, prototype, TypeInfo(JSFunctionType, StructureFlags), info());
}
+
+ static ptrdiff_t offsetOfTargetFunction() { return OBJECT_OFFSETOF(JSBoundFunction, m_targetFunction); }
+ static ptrdiff_t offsetOfBoundThis() { return OBJECT_OFFSETOF(JSBoundFunction, m_boundThis); }
DECLARE_INFO;
@@ -60,13 +65,13 @@
static void visitChildren(JSCell*, SlotVisitor&);
private:
- JSBoundFunction(VM&, JSGlobalObject*, Structure*, JSObject* targetFunction, JSValue boundThis, JSValue boundArgs);
+ JSBoundFunction(VM&, JSGlobalObject*, Structure*, JSObject* targetFunction, JSValue boundThis, JSArray* boundArgs);
void finishCreation(VM&, NativeExecutable*, int length, const String& name);
WriteBarrier<JSObject> m_targetFunction;
WriteBarrier<Unknown> m_boundThis;
- WriteBarrier<Unknown> m_boundArgs;
+ WriteBarrier<JSArray> m_boundArgs;
};
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/JSFunction.cpp (199945 => 199946)
--- trunk/Source/_javascript_Core/runtime/JSFunction.cpp 2016-04-23 01:14:02 UTC (rev 199945)
+++ trunk/Source/_javascript_Core/runtime/JSFunction.cpp 2016-04-23 02:00:38 UTC (rev 199946)
@@ -84,15 +84,7 @@
NativeExecutable* JSFunction::lookUpOrCreateNativeExecutable(VM& vm, NativeFunction nativeFunction, Intrinsic intrinsic, NativeFunction nativeConstructor, const String& name)
{
-#if !ENABLE(JIT)
- UNUSED_PARAM(intrinsic);
-#else
- if (intrinsic != NoIntrinsic && vm.canUseJIT()) {
- ASSERT(nativeConstructor == callHostFunctionAsConstructor);
- return vm.getHostFunction(nativeFunction, intrinsic, name);
- }
-#endif
- return vm.getHostFunction(nativeFunction, nativeConstructor, name);
+ return vm.getHostFunction(nativeFunction, intrinsic, nativeConstructor, name);
}
JSFunction* JSFunction::create(VM& vm, JSGlobalObject* globalObject, int length, const String& name, NativeFunction nativeFunction, Intrinsic intrinsic, NativeFunction nativeConstructor)
Modified: trunk/Source/_javascript_Core/runtime/VM.cpp (199945 => 199946)
--- trunk/Source/_javascript_Core/runtime/VM.cpp 2016-04-23 01:14:02 UTC (rev 199945)
+++ trunk/Source/_javascript_Core/runtime/VM.cpp 2016-04-23 02:00:38 UTC (rev 199946)
@@ -495,33 +495,34 @@
return imulThunkGenerator;
case RandomIntrinsic:
return randomThunkGenerator;
+ case BoundThisNoArgsFunctionCallIntrinsic:
+ return boundThisNoArgsFunctionCallGenerator;
default:
- return 0;
+ return nullptr;
}
}
+#endif // !ENABLE(JIT)
+
NativeExecutable* VM::getHostFunction(NativeFunction function, NativeFunction constructor, const String& name)
{
- return jitStubs->hostFunctionStub(this, function, constructor, name);
+ return getHostFunction(function, NoIntrinsic, constructor, name);
}
-NativeExecutable* VM::getHostFunction(NativeFunction function, Intrinsic intrinsic, const String& name)
-{
- ASSERT(canUseJIT());
- return jitStubs->hostFunctionStub(this, function, intrinsic != NoIntrinsic ? thunkGeneratorForIntrinsic(intrinsic) : 0, intrinsic, name);
-}
-#else // !ENABLE(JIT)
-
-NativeExecutable* VM::getHostFunction(NativeFunction function, NativeFunction constructor, const String& name)
+NativeExecutable* VM::getHostFunction(NativeFunction function, Intrinsic intrinsic, NativeFunction constructor, const String& name)
{
+ if (canUseJIT()) {
+ return jitStubs->hostFunctionStub(
+ this, function, constructor,
+ intrinsic != NoIntrinsic ? thunkGeneratorForIntrinsic(intrinsic) : 0,
+ intrinsic, name);
+ }
return NativeExecutable::create(*this,
adoptRef(new NativeJITCode(MacroAssemblerCodeRef::createLLIntCodeRef(llint_native_call_trampoline), JITCode::HostCallThunk)), function,
adoptRef(new NativeJITCode(MacroAssemblerCodeRef::createLLIntCodeRef(llint_native_construct_trampoline), JITCode::HostCallThunk)), constructor,
NoIntrinsic, name);
}
-#endif // !ENABLE(JIT)
-
VM::ClientData::~ClientData()
{
}
Modified: trunk/Source/_javascript_Core/runtime/VM.h (199945 => 199946)
--- trunk/Source/_javascript_Core/runtime/VM.h 2016-04-23 01:14:02 UTC (rev 199945)
+++ trunk/Source/_javascript_Core/runtime/VM.h 2016-04-23 02:00:38 UTC (rev 199946)
@@ -399,7 +399,6 @@
{
return jitStubs->ctiStub(this, generator);
}
- NativeExecutable* getHostFunction(NativeFunction, Intrinsic, const String& name);
std::unique_ptr<RegisterAtOffsetList> allCalleeSaveRegisterOffsets;
@@ -411,6 +410,7 @@
std::unique_ptr<FTL::Thunks> ftlThunks;
#endif
NativeExecutable* getHostFunction(NativeFunction, NativeFunction constructor, const String& name);
+ NativeExecutable* getHostFunction(NativeFunction, Intrinsic intrinsic, NativeFunction constructor, const String& name);
static ptrdiff_t exceptionOffset()
{