summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/jit/JITOperations.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2015-05-20 09:56:07 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2015-05-20 09:56:07 +0000
commit41386e9cb918eed93b3f13648cbef387e371e451 (patch)
treea97f9d7bd1d9d091833286085f72da9d83fd0606 /Source/JavaScriptCore/jit/JITOperations.cpp
parente15dd966d523731101f70ccf768bba12435a0208 (diff)
downloadWebKitGtk-tarball-41386e9cb918eed93b3f13648cbef387e371e451.tar.gz
webkitgtk-2.4.9webkitgtk-2.4.9
Diffstat (limited to 'Source/JavaScriptCore/jit/JITOperations.cpp')
-rw-r--r--Source/JavaScriptCore/jit/JITOperations.cpp1174
1 files changed, 476 insertions, 698 deletions
diff --git a/Source/JavaScriptCore/jit/JITOperations.cpp b/Source/JavaScriptCore/jit/JITOperations.cpp
index b59a028e1..578d15dac 100644
--- a/Source/JavaScriptCore/jit/JITOperations.cpp
+++ b/Source/JavaScriptCore/jit/JITOperations.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -24,41 +24,32 @@
*/
#include "config.h"
-#include "JITOperations.h"
-
#if ENABLE(JIT)
+#include "JITOperations.h"
+#include "Arguments.h"
#include "ArrayConstructor.h"
+#include "CallFrameInlines.h"
+#include "CommonSlowPaths.h"
#include "DFGCompilationMode.h"
#include "DFGDriver.h"
#include "DFGOSREntry.h"
-#include "DFGThunks.h"
#include "DFGWorklist.h"
-#include "Debugger.h"
-#include "DirectArguments.h"
#include "Error.h"
-#include "ErrorHandlingScope.h"
-#include "ExceptionFuzz.h"
#include "GetterSetter.h"
#include "HostCallReturnValue.h"
#include "JIT.h"
+#include "JITOperationWrappers.h"
#include "JITToDFGDeferredCompilationCallback.h"
-#include "JSCInlines.h"
#include "JSGlobalObjectFunctions.h"
-#include "JSLexicalEnvironment.h"
-#include "JSPropertyNameEnumerator.h"
+#include "JSNameScope.h"
+#include "JSPropertyNameIterator.h"
#include "JSStackInlines.h"
#include "JSWithScope.h"
-#include "LegacyProfiler.h"
#include "ObjectConstructor.h"
-#include "PropertyName.h"
+#include "Operations.h"
#include "Repatch.h"
#include "RepatchBuffer.h"
-#include "ScopedArguments.h"
-#include "TestRunnerUtils.h"
-#include "TypeProfilerLog.h"
-#include "VMInlines.h"
-#include <wtf/InlineASM.h>
namespace JSC {
@@ -80,34 +71,33 @@ void * _ReturnAddress(void);
#endif
-void JIT_OPERATION operationThrowStackOverflowError(ExecState* exec, CodeBlock* codeBlock)
+void JIT_OPERATION operationStackCheck(ExecState* exec, CodeBlock* codeBlock)
{
// We pass in our own code block, because the callframe hasn't been populated.
VM* vm = codeBlock->vm();
-
- VMEntryFrame* vmEntryFrame = vm->topVMEntryFrame;
- CallFrame* callerFrame = exec->callerFrame(vmEntryFrame);
+ CallFrame* callerFrame = exec->callerFrameSkippingVMEntrySentinel();
if (!callerFrame)
callerFrame = exec;
- NativeCallFrameTracerWithRestore tracer(vm, vmEntryFrame, callerFrame);
- ErrorHandlingScope errorScope(*vm);
- vm->throwException(callerFrame, createStackOverflowError(callerFrame));
+ NativeCallFrameTracer tracer(vm, callerFrame);
+
+ JSStack& stack = vm->interpreter->stack();
+
+ if (UNLIKELY(!stack.grow(&exec->registers()[virtualRegisterForLocal(codeBlock->frameRegisterCount()).offset()])))
+ vm->throwException(callerFrame, createStackOverflowError(callerFrame));
}
int32_t JIT_OPERATION operationCallArityCheck(ExecState* exec)
{
VM* vm = &exec->vm();
- VMEntryFrame* vmEntryFrame = vm->topVMEntryFrame;
- CallFrame* callerFrame = exec->callerFrame(vmEntryFrame);
+ CallFrame* callerFrame = exec->callerFrameSkippingVMEntrySentinel();
+ NativeCallFrameTracer tracer(vm, callerFrame);
JSStack& stack = vm->interpreter->stack();
int32_t missingArgCount = CommonSlowPaths::arityCheckFor(exec, &stack, CodeForCall);
- if (missingArgCount < 0) {
- NativeCallFrameTracerWithRestore tracer(vm, vmEntryFrame, callerFrame);
- throwStackOverflowError(callerFrame);
- }
+ if (missingArgCount < 0)
+ vm->throwException(callerFrame, createStackOverflowError(callerFrame));
return missingArgCount;
}
@@ -115,94 +105,81 @@ int32_t JIT_OPERATION operationCallArityCheck(ExecState* exec)
int32_t JIT_OPERATION operationConstructArityCheck(ExecState* exec)
{
VM* vm = &exec->vm();
- VMEntryFrame* vmEntryFrame = vm->topVMEntryFrame;
- CallFrame* callerFrame = exec->callerFrame(vmEntryFrame);
+ CallFrame* callerFrame = exec->callerFrameSkippingVMEntrySentinel();
+ NativeCallFrameTracer tracer(vm, callerFrame);
JSStack& stack = vm->interpreter->stack();
int32_t missingArgCount = CommonSlowPaths::arityCheckFor(exec, &stack, CodeForConstruct);
- if (missingArgCount < 0) {
- NativeCallFrameTracerWithRestore tracer(vm, vmEntryFrame, callerFrame);
- throwStackOverflowError(callerFrame);
- }
+ if (missingArgCount < 0)
+ vm->throwException(callerFrame, createStackOverflowError(callerFrame));
return missingArgCount;
}
-EncodedJSValue JIT_OPERATION operationGetById(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, UniquedStringImpl* uid)
+EncodedJSValue JIT_OPERATION operationGetById(ExecState* exec, StructureStubInfo*, EncodedJSValue base, StringImpl* uid)
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
- stubInfo->tookSlowPath = true;
-
JSValue baseValue = JSValue::decode(base);
PropertySlot slot(baseValue);
- Identifier ident = Identifier::fromUid(vm, uid);
+ Identifier ident(vm, uid);
return JSValue::encode(baseValue.get(exec, ident, slot));
}
-EncodedJSValue JIT_OPERATION operationGetByIdGeneric(ExecState* exec, EncodedJSValue base, UniquedStringImpl* uid)
-{
- VM* vm = &exec->vm();
- NativeCallFrameTracer tracer(vm, exec);
-
- JSValue baseValue = JSValue::decode(base);
- PropertySlot slot(baseValue);
- Identifier ident = Identifier::fromUid(vm, uid);
- return JSValue::encode(baseValue.get(exec, ident, slot));
-}
-
-EncodedJSValue JIT_OPERATION operationGetByIdBuildList(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, UniquedStringImpl* uid)
+EncodedJSValue JIT_OPERATION operationGetByIdBuildList(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, StringImpl* uid)
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
- Identifier ident = Identifier::fromUid(vm, uid);
+ Identifier ident(vm, uid);
AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
JSValue baseValue = JSValue::decode(base);
PropertySlot slot(baseValue);
- bool hasResult = baseValue.getPropertySlot(exec, ident, slot);
-
+ JSValue result = baseValue.get(exec, ident, slot);
+
if (accessType == static_cast<AccessType>(stubInfo->accessType))
buildGetByIDList(exec, baseValue, ident, slot, *stubInfo);
- return JSValue::encode(hasResult? slot.getValue(exec, ident) : jsUndefined());
+ return JSValue::encode(result);
}
-EncodedJSValue JIT_OPERATION operationGetByIdOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, UniquedStringImpl* uid)
+EncodedJSValue JIT_OPERATION operationGetByIdOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, StringImpl* uid)
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
- Identifier ident = Identifier::fromUid(vm, uid);
+ Identifier ident = uid->isEmptyUnique() ? Identifier::from(PrivateName(uid)) : Identifier(vm, uid);
+ AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
JSValue baseValue = JSValue::decode(base);
PropertySlot slot(baseValue);
+ JSValue result = baseValue.get(exec, ident, slot);
- bool hasResult = baseValue.getPropertySlot(exec, ident, slot);
- if (stubInfo->seen)
- repatchGetByID(exec, baseValue, ident, slot, *stubInfo);
- else
- stubInfo->seen = true;
-
- return JSValue::encode(hasResult? slot.getValue(exec, ident) : jsUndefined());
+ if (accessType == static_cast<AccessType>(stubInfo->accessType)) {
+ if (stubInfo->seen)
+ repatchGetByID(exec, baseValue, ident, slot, *stubInfo);
+ else
+ stubInfo->seen = true;
+ }
+ return JSValue::encode(result);
}
-EncodedJSValue JIT_OPERATION operationInOptimize(ExecState* exec, StructureStubInfo* stubInfo, JSCell* base, UniquedStringImpl* key)
+EncodedJSValue JIT_OPERATION operationInOptimize(ExecState* exec, StructureStubInfo* stubInfo, JSCell* base, StringImpl* key)
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
if (!base->isObject()) {
- vm->throwException(exec, createInvalidInParameterError(exec, base));
+ vm->throwException(exec, createInvalidParameterError(exec, "in", base));
return JSValue::encode(jsUndefined());
}
AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
- Identifier ident = Identifier::fromUid(vm, key);
+ Identifier ident(vm, key);
PropertySlot slot(base);
bool result = asObject(base)->getPropertySlot(exec, ident, slot);
@@ -216,19 +193,17 @@ EncodedJSValue JIT_OPERATION operationInOptimize(ExecState* exec, StructureStubI
return JSValue::encode(jsBoolean(result));
}
-EncodedJSValue JIT_OPERATION operationIn(ExecState* exec, StructureStubInfo* stubInfo, JSCell* base, UniquedStringImpl* key)
+EncodedJSValue JIT_OPERATION operationIn(ExecState* exec, StructureStubInfo*, JSCell* base, StringImpl* key)
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
-
- stubInfo->tookSlowPath = true;
if (!base->isObject()) {
- vm->throwException(exec, createInvalidInParameterError(exec, base));
+ vm->throwException(exec, createInvalidParameterError(exec, "in", base));
return JSValue::encode(jsUndefined());
}
- Identifier ident = Identifier::fromUid(vm, key);
+ Identifier ident(vm, key);
return JSValue::encode(jsBoolean(asObject(base)->hasProperty(exec, ident)));
}
@@ -240,232 +215,234 @@ EncodedJSValue JIT_OPERATION operationGenericIn(ExecState* exec, JSCell* base, E
return JSValue::encode(jsBoolean(CommonSlowPaths::opIn(exec, JSValue::decode(key), base)));
}
-void JIT_OPERATION operationPutByIdStrict(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
+EncodedJSValue JIT_OPERATION operationCallCustomGetter(ExecState* exec, JSCell* base, PropertySlot::GetValueFunc function, StringImpl* uid)
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
- stubInfo->tookSlowPath = true;
+ Identifier ident(vm, uid);
+
+ return function(exec, JSValue::encode(base), JSValue::encode(base), ident);
+}
+
+EncodedJSValue JIT_OPERATION operationCallGetter(ExecState* exec, JSCell* base, JSCell* getterSetter)
+{
+ VM* vm = &exec->vm();
+ NativeCallFrameTracer tracer(vm, exec);
+
+ return JSValue::encode(callGetter(exec, base, getterSetter));
+}
+
+void JIT_OPERATION operationPutByIdStrict(ExecState* exec, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
+{
+ VM* vm = &exec->vm();
+ NativeCallFrameTracer tracer(vm, exec);
- Identifier ident = Identifier::fromUid(vm, uid);
+ Identifier ident(vm, uid);
PutPropertySlot slot(JSValue::decode(encodedBase), true, exec->codeBlock()->putByIdContext());
JSValue::decode(encodedBase).put(exec, ident, JSValue::decode(encodedValue), slot);
}
-void JIT_OPERATION operationPutByIdNonStrict(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
+void JIT_OPERATION operationPutByIdNonStrict(ExecState* exec, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
- stubInfo->tookSlowPath = true;
-
- Identifier ident = Identifier::fromUid(vm, uid);
+ Identifier ident(vm, uid);
PutPropertySlot slot(JSValue::decode(encodedBase), false, exec->codeBlock()->putByIdContext());
JSValue::decode(encodedBase).put(exec, ident, JSValue::decode(encodedValue), slot);
}
-void JIT_OPERATION operationPutByIdDirectStrict(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
+void JIT_OPERATION operationPutByIdDirectStrict(ExecState* exec, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
- stubInfo->tookSlowPath = true;
-
- Identifier ident = Identifier::fromUid(vm, uid);
+ Identifier ident(vm, uid);
PutPropertySlot slot(JSValue::decode(encodedBase), true, exec->codeBlock()->putByIdContext());
asObject(JSValue::decode(encodedBase))->putDirect(exec->vm(), ident, JSValue::decode(encodedValue), slot);
}
-void JIT_OPERATION operationPutByIdDirectNonStrict(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
+void JIT_OPERATION operationPutByIdDirectNonStrict(ExecState* exec, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
- stubInfo->tookSlowPath = true;
-
- Identifier ident = Identifier::fromUid(vm, uid);
+ Identifier ident(vm, uid);
PutPropertySlot slot(JSValue::decode(encodedBase), false, exec->codeBlock()->putByIdContext());
asObject(JSValue::decode(encodedBase))->putDirect(exec->vm(), ident, JSValue::decode(encodedValue), slot);
}
-void JIT_OPERATION operationPutByIdStrictOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
+void JIT_OPERATION operationPutByIdStrictOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
- Identifier ident = Identifier::fromUid(vm, uid);
+ Identifier ident(vm, uid);
AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
JSValue value = JSValue::decode(encodedValue);
JSValue baseValue = JSValue::decode(encodedBase);
PutPropertySlot slot(baseValue, true, exec->codeBlock()->putByIdContext());
-
- Structure* structure = baseValue.isCell() ? baseValue.asCell()->structure(*vm) : nullptr;
+
baseValue.put(exec, ident, value, slot);
if (accessType != static_cast<AccessType>(stubInfo->accessType))
return;
if (stubInfo->seen)
- repatchPutByID(exec, baseValue, structure, ident, slot, *stubInfo, NotDirect);
+ repatchPutByID(exec, baseValue, ident, slot, *stubInfo, NotDirect);
else
stubInfo->seen = true;
}
-void JIT_OPERATION operationPutByIdNonStrictOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
+void JIT_OPERATION operationPutByIdNonStrictOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
- Identifier ident = Identifier::fromUid(vm, uid);
+ Identifier ident(vm, uid);
AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
JSValue value = JSValue::decode(encodedValue);
JSValue baseValue = JSValue::decode(encodedBase);
PutPropertySlot slot(baseValue, false, exec->codeBlock()->putByIdContext());
-
- Structure* structure = baseValue.isCell() ? baseValue.asCell()->structure(*vm) : nullptr;
+
baseValue.put(exec, ident, value, slot);
if (accessType != static_cast<AccessType>(stubInfo->accessType))
return;
if (stubInfo->seen)
- repatchPutByID(exec, baseValue, structure, ident, slot, *stubInfo, NotDirect);
+ repatchPutByID(exec, baseValue, ident, slot, *stubInfo, NotDirect);
else
stubInfo->seen = true;
}
-void JIT_OPERATION operationPutByIdDirectStrictOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
+void JIT_OPERATION operationPutByIdDirectStrictOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
- Identifier ident = Identifier::fromUid(vm, uid);
+ Identifier ident(vm, uid);
AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
JSValue value = JSValue::decode(encodedValue);
JSObject* baseObject = asObject(JSValue::decode(encodedBase));
PutPropertySlot slot(baseObject, true, exec->codeBlock()->putByIdContext());
- Structure* structure = baseObject->structure(*vm);
baseObject->putDirect(exec->vm(), ident, value, slot);
if (accessType != static_cast<AccessType>(stubInfo->accessType))
return;
if (stubInfo->seen)
- repatchPutByID(exec, baseObject, structure, ident, slot, *stubInfo, Direct);
+ repatchPutByID(exec, baseObject, ident, slot, *stubInfo, Direct);
else
stubInfo->seen = true;
}
-void JIT_OPERATION operationPutByIdDirectNonStrictOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
+void JIT_OPERATION operationPutByIdDirectNonStrictOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
- Identifier ident = Identifier::fromUid(vm, uid);
+ Identifier ident(vm, uid);
AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
JSValue value = JSValue::decode(encodedValue);
JSObject* baseObject = asObject(JSValue::decode(encodedBase));
PutPropertySlot slot(baseObject, false, exec->codeBlock()->putByIdContext());
- Structure* structure = baseObject->structure(*vm);
baseObject->putDirect(exec->vm(), ident, value, slot);
if (accessType != static_cast<AccessType>(stubInfo->accessType))
return;
if (stubInfo->seen)
- repatchPutByID(exec, baseObject, structure, ident, slot, *stubInfo, Direct);
+ repatchPutByID(exec, baseObject, ident, slot, *stubInfo, Direct);
else
stubInfo->seen = true;
}
-void JIT_OPERATION operationPutByIdStrictBuildList(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
+void JIT_OPERATION operationPutByIdStrictBuildList(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
- Identifier ident = Identifier::fromUid(vm, uid);
+ Identifier ident(vm, uid);
AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
JSValue value = JSValue::decode(encodedValue);
JSValue baseValue = JSValue::decode(encodedBase);
PutPropertySlot slot(baseValue, true, exec->codeBlock()->putByIdContext());
- Structure* structure = baseValue.isCell() ? baseValue.asCell()->structure(*vm) : nullptr;
baseValue.put(exec, ident, value, slot);
-
+
if (accessType != static_cast<AccessType>(stubInfo->accessType))
return;
-
- buildPutByIdList(exec, baseValue, structure, ident, slot, *stubInfo, NotDirect);
+
+ buildPutByIdList(exec, baseValue, ident, slot, *stubInfo, NotDirect);
}
-void JIT_OPERATION operationPutByIdNonStrictBuildList(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
+void JIT_OPERATION operationPutByIdNonStrictBuildList(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
- Identifier ident = Identifier::fromUid(vm, uid);
+ Identifier ident(vm, uid);
AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
JSValue value = JSValue::decode(encodedValue);
JSValue baseValue = JSValue::decode(encodedBase);
PutPropertySlot slot(baseValue, false, exec->codeBlock()->putByIdContext());
-
- Structure* structure = baseValue.isCell() ? baseValue.asCell()->structure(*vm) : nullptr;
+
baseValue.put(exec, ident, value, slot);
if (accessType != static_cast<AccessType>(stubInfo->accessType))
return;
- buildPutByIdList(exec, baseValue, structure, ident, slot, *stubInfo, NotDirect);
+ buildPutByIdList(exec, baseValue, ident, slot, *stubInfo, NotDirect);
}
-void JIT_OPERATION operationPutByIdDirectStrictBuildList(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
+void JIT_OPERATION operationPutByIdDirectStrictBuildList(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
- Identifier ident = Identifier::fromUid(vm, uid);
+ Identifier ident(vm, uid);
AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
JSValue value = JSValue::decode(encodedValue);
JSObject* baseObject = asObject(JSValue::decode(encodedBase));
PutPropertySlot slot(baseObject, true, exec->codeBlock()->putByIdContext());
-
- Structure* structure = baseObject->structure(*vm);
- baseObject->putDirect(*vm, ident, value, slot);
+
+ baseObject->putDirect(exec->vm(), ident, value, slot);
if (accessType != static_cast<AccessType>(stubInfo->accessType))
return;
- buildPutByIdList(exec, baseObject, structure, ident, slot, *stubInfo, Direct);
+ buildPutByIdList(exec, baseObject, ident, slot, *stubInfo, Direct);
}
-void JIT_OPERATION operationPutByIdDirectNonStrictBuildList(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
+void JIT_OPERATION operationPutByIdDirectNonStrictBuildList(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
- Identifier ident = Identifier::fromUid(vm, uid);
+ Identifier ident(vm, uid);
AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
JSValue value = JSValue::decode(encodedValue);
JSObject* baseObject = asObject(JSValue::decode(encodedBase));
PutPropertySlot slot(baseObject, false, exec->codeBlock()->putByIdContext());
-
- Structure* structure = baseObject->structure(*vm);
- baseObject->putDirect(*vm, ident, value, slot);
-
+
+ baseObject ->putDirect(exec->vm(), ident, value, slot);
+
if (accessType != static_cast<AccessType>(stubInfo->accessType))
return;
- buildPutByIdList(exec, baseObject, structure, ident, slot, *stubInfo, Direct);
+ buildPutByIdList(exec, baseObject, ident, slot, *stubInfo, Direct);
}
void JIT_OPERATION operationReallocateStorageAndFinishPut(ExecState* exec, JSObject* base, Structure* structure, PropertyOffset offset, EncodedJSValue value)
@@ -473,29 +450,29 @@ void JIT_OPERATION operationReallocateStorageAndFinishPut(ExecState* exec, JSObj
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
- ASSERT(structure->outOfLineCapacity() > base->structure(vm)->outOfLineCapacity());
+ ASSERT(structure->outOfLineCapacity() > base->structure()->outOfLineCapacity());
ASSERT(!vm.heap.storageAllocator().fastPathShouldSucceed(structure->outOfLineCapacity() * sizeof(JSValue)));
base->setStructureAndReallocateStorageIfNecessary(vm, structure);
base->putDirect(vm, offset, JSValue::decode(value));
}
-static void putByVal(CallFrame* callFrame, JSValue baseValue, JSValue subscript, JSValue value, ByValInfo* byValInfo)
+static void putByVal(CallFrame* callFrame, JSValue baseValue, JSValue subscript, JSValue value)
{
- VM& vm = callFrame->vm();
if (LIKELY(subscript.isUInt32())) {
uint32_t i = subscript.asUInt32();
if (baseValue.isObject()) {
JSObject* object = asObject(baseValue);
if (object->canSetIndexQuickly(i))
object->setIndexQuickly(callFrame->vm(), i, value);
- else {
- byValInfo->arrayProfile->setOutOfBounds();
- object->methodTable(vm)->putByIndex(object, callFrame, i, value, callFrame->codeBlock()->isStrictMode());
- }
+ else
+ object->methodTable()->putByIndex(object, callFrame, i, value, callFrame->codeBlock()->isStrictMode());
} else
baseValue.putByIndex(callFrame, i, value, callFrame->codeBlock()->isStrictMode());
+ } else if (isName(subscript)) {
+ PutPropertySlot slot(baseValue, callFrame->codeBlock()->isStrictMode());
+ baseValue.put(callFrame, jsCast<NameInstance*>(subscript.asCell())->privateName(), value, slot);
} else {
- auto property = subscript.toPropertyKey(callFrame);
+ Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
if (!callFrame->vm().exception()) { // Don't put to an object if toString threw an exception.
PutPropertySlot slot(baseValue, callFrame->codeBlock()->isStrictMode());
baseValue.put(callFrame, property, value, slot);
@@ -503,45 +480,23 @@ static void putByVal(CallFrame* callFrame, JSValue baseValue, JSValue subscript,
}
}
-static void directPutByVal(CallFrame* callFrame, JSObject* baseObject, JSValue subscript, JSValue value, ByValInfo* byValInfo)
+static void directPutByVal(CallFrame* callFrame, JSObject* baseObject, JSValue subscript, JSValue value)
{
- bool isStrictMode = callFrame->codeBlock()->isStrictMode();
if (LIKELY(subscript.isUInt32())) {
- // Despite its name, JSValue::isUInt32 will return true only for positive boxed int32_t; all those values are valid array indices.
- uint32_t index = subscript.asUInt32();
- ASSERT(isIndex(index));
- if (baseObject->canSetIndexQuicklyForPutDirect(index)) {
- baseObject->setIndexQuickly(callFrame->vm(), index, value);
- return;
- }
-
- byValInfo->arrayProfile->setOutOfBounds();
- baseObject->putDirectIndex(callFrame, index, value, 0, isStrictMode ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
- return;
- }
-
- if (subscript.isDouble()) {
- double subscriptAsDouble = subscript.asDouble();
- uint32_t subscriptAsUInt32 = static_cast<uint32_t>(subscriptAsDouble);
- if (subscriptAsDouble == subscriptAsUInt32 && isIndex(subscriptAsUInt32)) {
- baseObject->putDirectIndex(callFrame, subscriptAsUInt32, value, 0, isStrictMode ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
- return;
+ uint32_t i = subscript.asUInt32();
+ baseObject->putDirectIndex(callFrame, i, value);
+ } else if (isName(subscript)) {
+ PutPropertySlot slot(baseObject, callFrame->codeBlock()->isStrictMode());
+ baseObject->putDirect(callFrame->vm(), jsCast<NameInstance*>(subscript.asCell())->privateName(), value, slot);
+ } else {
+ Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
+ if (!callFrame->vm().exception()) { // Don't put to an object if toString threw an exception.
+ PutPropertySlot slot(baseObject, callFrame->codeBlock()->isStrictMode());
+ baseObject->putDirect(callFrame->vm(), property, value, slot);
}
}
-
- // Don't put to an object if toString threw an exception.
- auto property = subscript.toPropertyKey(callFrame);
- if (callFrame->vm().exception())
- return;
-
- if (Optional<uint32_t> index = parseIndex(property))
- baseObject->putDirectIndex(callFrame, index.value(), value, 0, isStrictMode ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
- else {
- PutPropertySlot slot(baseObject, isStrictMode);
- baseObject->putDirect(callFrame->vm(), property, value, slot);
- }
}
-void JIT_OPERATION operationPutByVal(ExecState* exec, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, ByValInfo* byValInfo)
+void JIT_OPERATION operationPutByVal(ExecState* exec, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue)
{
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
@@ -555,19 +510,16 @@ void JIT_OPERATION operationPutByVal(ExecState* exec, EncodedJSValue encodedBase
JSObject* object = asObject(baseValue);
bool didOptimize = false;
- ASSERT(exec->locationAsBytecodeOffset());
- ASSERT(!byValInfo->stubRoutine);
+ unsigned bytecodeOffset = exec->locationAsBytecodeOffset();
+ ASSERT(bytecodeOffset);
+ ByValInfo& byValInfo = exec->codeBlock()->getByValInfo(bytecodeOffset - 1);
+ ASSERT(!byValInfo.stubRoutine);
- Structure* structure = object->structure(vm);
- if (hasOptimizableIndexing(structure)) {
+ if (hasOptimizableIndexing(object->structure())) {
// Attempt to optimize.
- JITArrayMode arrayMode = jitArrayModeForStructure(structure);
- if (jitArrayModePermitsPut(arrayMode) && arrayMode != byValInfo->arrayMode) {
- CodeBlock* codeBlock = exec->codeBlock();
- ConcurrentJITLocker locker(codeBlock->m_lock);
- byValInfo->arrayProfile->computeUpdatedPrediction(locker, codeBlock, structure);
-
- JIT::compilePutByVal(&vm, exec->codeBlock(), byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode);
+ JITArrayMode arrayMode = jitArrayModeForStructure(object->structure());
+ if (arrayMode != byValInfo.arrayMode) {
+ JIT::compilePutByVal(&vm, exec->codeBlock(), &byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode);
didOptimize = true;
}
}
@@ -578,18 +530,19 @@ void JIT_OPERATION operationPutByVal(ExecState* exec, EncodedJSValue encodedBase
// that intercepts indexed get, then don't even wait until 10 times. For cases
// where we see non-index-intercepting objects, this gives 10 iterations worth of
// opportunity for us to observe that the get_by_val may be polymorphic.
- if (++byValInfo->slowPathCount >= 10
- || object->structure(vm)->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) {
+ if (++byValInfo.slowPathCount >= 10
+ || object->structure()->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) {
// Don't ever try to optimize.
- ctiPatchCallByReturnAddress(exec->codeBlock(), ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationPutByValGeneric));
+ RepatchBuffer repatchBuffer(exec->codeBlock());
+ repatchBuffer.relinkCallerToFunction(ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationPutByValGeneric));
}
}
}
- putByVal(exec, baseValue, subscript, value, byValInfo);
+ putByVal(exec, baseValue, subscript, value);
}
-void JIT_OPERATION operationDirectPutByVal(ExecState* callFrame, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, ByValInfo* byValInfo)
+void JIT_OPERATION operationDirectPutByVal(ExecState* callFrame, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue)
{
VM& vm = callFrame->vm();
NativeCallFrameTracer tracer(&vm, callFrame);
@@ -602,20 +555,17 @@ void JIT_OPERATION operationDirectPutByVal(ExecState* callFrame, EncodedJSValue
if (subscript.isInt32()) {
// See if it's worth optimizing at all.
bool didOptimize = false;
-
- ASSERT(callFrame->locationAsBytecodeOffset());
- ASSERT(!byValInfo->stubRoutine);
-
- Structure* structure = object->structure(vm);
- if (hasOptimizableIndexing(structure)) {
+
+ unsigned bytecodeOffset = callFrame->locationAsBytecodeOffset();
+ ASSERT(bytecodeOffset);
+ ByValInfo& byValInfo = callFrame->codeBlock()->getByValInfo(bytecodeOffset - 1);
+ ASSERT(!byValInfo.stubRoutine);
+
+ if (hasOptimizableIndexing(object->structure())) {
// Attempt to optimize.
- JITArrayMode arrayMode = jitArrayModeForStructure(structure);
- if (jitArrayModePermitsPut(arrayMode) && arrayMode != byValInfo->arrayMode) {
- CodeBlock* codeBlock = callFrame->codeBlock();
- ConcurrentJITLocker locker(codeBlock->m_lock);
- byValInfo->arrayProfile->computeUpdatedPrediction(locker, codeBlock, structure);
-
- JIT::compileDirectPutByVal(&vm, callFrame->codeBlock(), byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode);
+ JITArrayMode arrayMode = jitArrayModeForStructure(object->structure());
+ if (arrayMode != byValInfo.arrayMode) {
+ JIT::compileDirectPutByVal(&vm, callFrame->codeBlock(), &byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode);
didOptimize = true;
}
}
@@ -626,17 +576,18 @@ void JIT_OPERATION operationDirectPutByVal(ExecState* callFrame, EncodedJSValue
// that intercepts indexed get, then don't even wait until 10 times. For cases
// where we see non-index-intercepting objects, this gives 10 iterations worth of
// opportunity for us to observe that the get_by_val may be polymorphic.
- if (++byValInfo->slowPathCount >= 10
- || object->structure(vm)->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) {
+ if (++byValInfo.slowPathCount >= 10
+ || object->structure()->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) {
// Don't ever try to optimize.
- ctiPatchCallByReturnAddress(callFrame->codeBlock(), ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationDirectPutByValGeneric));
+ RepatchBuffer repatchBuffer(callFrame->codeBlock());
+ repatchBuffer.relinkCallerToFunction(ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationDirectPutByValGeneric));
}
}
}
- directPutByVal(callFrame, object, subscript, value, byValInfo);
+ directPutByVal(callFrame, object, subscript, value);
}
-void JIT_OPERATION operationPutByValGeneric(ExecState* exec, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, ByValInfo* byValInfo)
+void JIT_OPERATION operationPutByValGeneric(ExecState* exec, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue)
{
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
@@ -645,11 +596,11 @@ void JIT_OPERATION operationPutByValGeneric(ExecState* exec, EncodedJSValue enco
JSValue subscript = JSValue::decode(encodedSubscript);
JSValue value = JSValue::decode(encodedValue);
- putByVal(exec, baseValue, subscript, value, byValInfo);
+ putByVal(exec, baseValue, subscript, value);
}
-void JIT_OPERATION operationDirectPutByValGeneric(ExecState* exec, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, ByValInfo* byValInfo)
+void JIT_OPERATION operationDirectPutByValGeneric(ExecState* exec, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue)
{
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
@@ -658,13 +609,18 @@ void JIT_OPERATION operationDirectPutByValGeneric(ExecState* exec, EncodedJSValu
JSValue subscript = JSValue::decode(encodedSubscript);
JSValue value = JSValue::decode(encodedValue);
RELEASE_ASSERT(baseValue.isObject());
- directPutByVal(exec, asObject(baseValue), subscript, value, byValInfo);
+ directPutByVal(exec, asObject(baseValue), subscript, value);
}
-EncodedJSValue JIT_OPERATION operationCallEval(ExecState* exec, ExecState* execCallee)
+EncodedJSValue JIT_OPERATION operationCallEval(ExecState* execCallee)
{
- UNUSED_PARAM(exec);
+ CallFrame* callerFrame = execCallee->callerFrame();
+ ASSERT(execCallee->callerFrame()->codeBlock()->codeType() != FunctionCode
+ || !execCallee->callerFrame()->codeBlock()->needsFullScopeChain()
+ || execCallee->callerFrame()->uncheckedR(execCallee->callerFrame()->codeBlock()->activationRegister().offset()).jsValue());
+ execCallee->setScope(callerFrame->scope());
+ execCallee->setReturnPC(static_cast<Instruction*>(OUR_RETURN_ADDRESS));
execCallee->setCodeBlock(0);
if (!isHostFunction(execCallee->calleeAsValue(), globalFuncEval))
@@ -683,6 +639,7 @@ static void* handleHostCall(ExecState* execCallee, JSValue callee, CodeSpecializ
ExecState* exec = execCallee->callerFrame();
VM* vm = &exec->vm();
+ execCallee->setScope(exec->scope());
execCallee->setCodeBlock(0);
if (kind == CodeForCall) {
@@ -728,65 +685,60 @@ static void* handleHostCall(ExecState* execCallee, JSValue callee, CodeSpecializ
return vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
}
-char* JIT_OPERATION operationLinkCall(ExecState* execCallee, CallLinkInfo* callLinkInfo)
+inline char* linkFor(ExecState* execCallee, CodeSpecializationKind kind)
{
ExecState* exec = execCallee->callerFrame();
VM* vm = &exec->vm();
- CodeSpecializationKind kind = callLinkInfo->specializationKind();
NativeCallFrameTracer tracer(vm, exec);
JSValue calleeAsValue = execCallee->calleeAsValue();
JSCell* calleeAsFunctionCell = getJSFunction(calleeAsValue);
- if (!calleeAsFunctionCell) {
- // FIXME: We should cache these kinds of calls. They can be common and currently they are
- // expensive.
- // https://bugs.webkit.org/show_bug.cgi?id=144458
+ if (!calleeAsFunctionCell)
return reinterpret_cast<char*>(handleHostCall(execCallee, calleeAsValue, kind));
- }
JSFunction* callee = jsCast<JSFunction*>(calleeAsFunctionCell);
- JSScope* scope = callee->scopeUnchecked();
+ execCallee->setScope(callee->scopeUnchecked());
ExecutableBase* executable = callee->executable();
MacroAssemblerCodePtr codePtr;
CodeBlock* codeBlock = 0;
+ CallLinkInfo& callLinkInfo = exec->codeBlock()->getCallLinkInfo(execCallee->returnPC());
if (executable->isHostFunction())
- codePtr = executable->entrypointFor(*vm, kind, MustCheckArity, callLinkInfo->registerPreservationMode());
+ codePtr = executable->generatedJITCodeFor(kind)->addressForCall();
else {
FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
-
- if (!isCall(kind) && functionExecutable->constructAbility() == ConstructAbility::CannotConstruct) {
- exec->vm().throwException(exec, createNotAConstructorError(exec, callee));
- return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
- }
-
- JSObject* error = functionExecutable->prepareForExecution(execCallee, callee, scope, kind);
+ JSObject* error = functionExecutable->prepareForExecution(execCallee, callee->scope(), kind);
if (error) {
- exec->vm().throwException(exec, error);
+ vm->throwException(exec, createStackOverflowError(exec));
return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
}
codeBlock = functionExecutable->codeBlockFor(kind);
- ArityCheckMode arity;
- if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()) || callLinkInfo->callType() == CallLinkInfo::CallVarargs || callLinkInfo->callType() == CallLinkInfo::ConstructVarargs)
- arity = MustCheckArity;
+ if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()) || callLinkInfo.callType == CallLinkInfo::CallVarargs)
+ codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(kind);
else
- arity = ArityCheckNotRequired;
- codePtr = functionExecutable->entrypointFor(*vm, kind, arity, callLinkInfo->registerPreservationMode());
+ codePtr = functionExecutable->generatedJITCodeFor(kind)->addressForCall();
}
- if (!callLinkInfo->seenOnce())
- callLinkInfo->setSeen();
+ if (!callLinkInfo.seenOnce())
+ callLinkInfo.setSeen();
else
- linkFor(execCallee, *callLinkInfo, codeBlock, callee, codePtr);
-
+ linkFor(execCallee, callLinkInfo, codeBlock, callee, codePtr, kind);
return reinterpret_cast<char*>(codePtr.executableAddress());
}
-inline char* virtualForWithFunction(
- ExecState* execCallee, CallLinkInfo* callLinkInfo, JSCell*& calleeAsFunctionCell)
+char* JIT_OPERATION operationLinkCall(ExecState* execCallee)
+{
+ return linkFor(execCallee, CodeForCall);
+}
+
+char* JIT_OPERATION operationLinkConstruct(ExecState* execCallee)
+{
+ return linkFor(execCallee, CodeForConstruct);
+}
+
+inline char* virtualForWithFunction(ExecState* execCallee, CodeSpecializationKind kind, JSCell*& calleeAsFunctionCell)
{
ExecState* exec = execCallee->callerFrame();
VM* vm = &exec->vm();
- CodeSpecializationKind kind = callLinkInfo->specializationKind();
NativeCallFrameTracer tracer(vm, exec);
JSValue calleeAsValue = execCallee->calleeAsValue();
@@ -795,43 +747,80 @@ inline char* virtualForWithFunction(
return reinterpret_cast<char*>(handleHostCall(execCallee, calleeAsValue, kind));
JSFunction* function = jsCast<JSFunction*>(calleeAsFunctionCell);
- JSScope* scope = function->scopeUnchecked();
+ execCallee->setScope(function->scopeUnchecked());
ExecutableBase* executable = function->executable();
if (UNLIKELY(!executable->hasJITCodeFor(kind))) {
FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
-
- if (!isCall(kind) && functionExecutable->constructAbility() == ConstructAbility::CannotConstruct) {
- exec->vm().throwException(exec, createNotAConstructorError(exec, function));
- return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
- }
-
- JSObject* error = functionExecutable->prepareForExecution(execCallee, function, scope, kind);
+ JSObject* error = functionExecutable->prepareForExecution(execCallee, function->scope(), kind);
if (error) {
- exec->vm().throwException(exec, error);
+ exec->vm().throwException(execCallee, error);
return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
}
}
- return reinterpret_cast<char*>(executable->entrypointFor(
- *vm, kind, MustCheckArity, callLinkInfo->registerPreservationMode()).executableAddress());
+ return reinterpret_cast<char*>(executable->generatedJITCodeWithArityCheckFor(kind).executableAddress());
+}
+
+inline char* virtualFor(ExecState* execCallee, CodeSpecializationKind kind)
+{
+ JSCell* calleeAsFunctionCellIgnored;
+ return virtualForWithFunction(execCallee, kind, calleeAsFunctionCellIgnored);
+}
+
+static bool attemptToOptimizeClosureCall(ExecState* execCallee, JSCell* calleeAsFunctionCell, CallLinkInfo& callLinkInfo)
+{
+ if (!calleeAsFunctionCell)
+ return false;
+
+ JSFunction* callee = jsCast<JSFunction*>(calleeAsFunctionCell);
+ JSFunction* oldCallee = callLinkInfo.callee.get();
+
+ if (!oldCallee
+ || oldCallee->structure() != callee->structure()
+ || oldCallee->executable() != callee->executable())
+ return false;
+
+ ASSERT(callee->executable()->hasJITCodeForCall());
+ MacroAssemblerCodePtr codePtr = callee->executable()->generatedJITCodeForCall()->addressForCall();
+
+ CodeBlock* codeBlock;
+ if (callee->executable()->isHostFunction())
+ codeBlock = 0;
+ else {
+ codeBlock = jsCast<FunctionExecutable*>(callee->executable())->codeBlockForCall();
+ if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()))
+ return false;
+ }
+
+ linkClosureCall(
+ execCallee, callLinkInfo, codeBlock,
+ callee->structure(), callee->executable(), codePtr);
+
+ return true;
}
-char* JIT_OPERATION operationLinkPolymorphicCall(ExecState* execCallee, CallLinkInfo* callLinkInfo)
+char* JIT_OPERATION operationLinkClosureCall(ExecState* execCallee)
{
- ASSERT(callLinkInfo->specializationKind() == CodeForCall);
JSCell* calleeAsFunctionCell;
- char* result = virtualForWithFunction(execCallee, callLinkInfo, calleeAsFunctionCell);
+ char* result = virtualForWithFunction(execCallee, CodeForCall, calleeAsFunctionCell);
+ CallLinkInfo& callLinkInfo = execCallee->callerFrame()->codeBlock()->getCallLinkInfo(execCallee->returnPC());
- linkPolymorphicCall(execCallee, *callLinkInfo, CallVariant(calleeAsFunctionCell));
+ if (!attemptToOptimizeClosureCall(execCallee, calleeAsFunctionCell, callLinkInfo))
+ linkSlowFor(execCallee, callLinkInfo, CodeForCall);
return result;
}
-char* JIT_OPERATION operationVirtualCall(ExecState* execCallee, CallLinkInfo* callLinkInfo)
+char* JIT_OPERATION operationVirtualCall(ExecState* execCallee)
+{
+ return virtualFor(execCallee, CodeForCall);
+}
+
+char* JIT_OPERATION operationVirtualConstruct(ExecState* execCallee)
{
- JSCell* calleeAsFunctionCellIgnored;
- return virtualForWithFunction(execCallee, callLinkInfo, calleeAsFunctionCellIgnored);
+ return virtualFor(execCallee, CodeForConstruct);
}
+
size_t JIT_OPERATION operationCompareLess(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
{
VM* vm = &exec->vm();
@@ -889,7 +878,7 @@ size_t JIT_OPERATION operationCompareStringEq(ExecState* exec, JSCell* left, JSC
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
- bool result = WTF::equal(*asString(left)->value(exec).impl(), *asString(right)->value(exec).impl());
+ bool result = asString(left)->value(exec) == asString(right)->value(exec);
#if USE(JSVALUE64)
return JSValue::encode(jsBoolean(result));
#else
@@ -899,7 +888,7 @@ size_t JIT_OPERATION operationCompareStringEq(ExecState* exec, JSCell* left, JSC
size_t JIT_OPERATION operationHasProperty(ExecState* exec, JSObject* base, JSString* property)
{
- int result = base->hasProperty(exec, property->toIdentifier(exec));
+ int result = base->hasProperty(exec, Identifier(exec, property->value(exec)));
return result;
}
@@ -926,20 +915,12 @@ EncodedJSValue JIT_OPERATION operationNewArrayWithSizeAndProfile(ExecState* exec
return JSValue::encode(constructArrayWithSizeQuirk(exec, profile, exec->lexicalGlobalObject(), sizeValue));
}
-EncodedJSValue JIT_OPERATION operationNewFunction(ExecState* exec, JSScope* scope, JSCell* functionExecutable)
-{
- ASSERT(functionExecutable->inherits(FunctionExecutable::info()));
- VM& vm = exec->vm();
- NativeCallFrameTracer tracer(&vm, exec);
- return JSValue::encode(JSFunction::create(vm, static_cast<FunctionExecutable*>(functionExecutable), scope));
-}
-
-EncodedJSValue JIT_OPERATION operationNewFunctionWithInvalidatedReallocationWatchpoint(ExecState* exec, JSScope* scope, JSCell* functionExecutable)
+EncodedJSValue JIT_OPERATION operationNewFunction(ExecState* exec, JSCell* functionExecutable)
{
ASSERT(functionExecutable->inherits(FunctionExecutable::info()));
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
- return JSValue::encode(JSFunction::createWithInvalidatedReallocationWatchpoint(vm, static_cast<FunctionExecutable*>(functionExecutable), scope));
+ return JSValue::encode(JSFunction::create(vm, static_cast<FunctionExecutable*>(functionExecutable), exec->scope()));
}
JSCell* JIT_OPERATION operationNewObject(ExecState* exec, Structure* structure)
@@ -956,7 +937,7 @@ EncodedJSValue JIT_OPERATION operationNewRegexp(ExecState* exec, void* regexpPtr
NativeCallFrameTracer tracer(&vm, exec);
RegExp* regexp = static_cast<RegExp*>(regexpPtr);
if (!regexp->isValid()) {
- vm.throwException(exec, createSyntaxError(exec, ASCIILiteral("Invalid flags supplied to RegExp constructor.")));
+ vm.throwException(exec, createSyntaxError(exec, "Invalid flags supplied to RegExp constructor."));
return JSValue::encode(jsUndefined());
}
@@ -968,7 +949,7 @@ void JIT_OPERATION operationHandleWatchdogTimer(ExecState* exec)
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
- if (UNLIKELY(vm.shouldTriggerTermination(exec)))
+ if (UNLIKELY(vm.watchdog.didFire(exec)))
vm.throwException(exec, createTerminatedExecutionException(&vm));
}
@@ -976,13 +957,12 @@ void JIT_OPERATION operationThrowStaticError(ExecState* exec, EncodedJSValue enc
{
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
- JSValue errorMessageValue = JSValue::decode(encodedValue);
- RELEASE_ASSERT(errorMessageValue.isString());
- String errorMessage = asString(errorMessageValue)->value(exec);
+
+ String message = errorDescriptionForValue(exec, JSValue::decode(encodedValue))->value(exec);
if (referenceErrorFlag)
- vm.throwException(exec, createReferenceError(exec, errorMessage));
+ vm.throwException(exec, createReferenceError(exec, message));
else
- vm.throwException(exec, createTypeError(exec, errorMessage));
+ vm.throwException(exec, createTypeError(exec, message));
}
void JIT_OPERATION operationDebug(ExecState* exec, int32_t debugHookID)
@@ -994,13 +974,7 @@ void JIT_OPERATION operationDebug(ExecState* exec, int32_t debugHookID)
}
#if ENABLE(DFG_JIT)
-static void updateAllPredictionsAndOptimizeAfterWarmUp(CodeBlock* codeBlock)
-{
- codeBlock->updateAllPredictions();
- codeBlock->optimizeAfterWarmUp();
-}
-
-SlowPathReturnType JIT_OPERATION operationOptimize(ExecState* exec, int32_t bytecodeIndex)
+char* JIT_OPERATION operationOptimize(ExecState* exec, int32_t bytecodeIndex)
{
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
@@ -1022,11 +996,7 @@ SlowPathReturnType JIT_OPERATION operationOptimize(ExecState* exec, int32_t byte
DeferGCForAWhile deferGC(vm.heap);
CodeBlock* codeBlock = exec->codeBlock();
- if (codeBlock->jitType() != JITCode::BaselineJIT) {
- dataLog("Unexpected code block in Baseline->DFG tier-up: ", *codeBlock, "\n");
- RELEASE_ASSERT_NOT_REACHED();
- }
-
+
if (bytecodeIndex) {
// If we're attempting to OSR from a loop, assume that this should be
// separately optimized.
@@ -1050,37 +1020,26 @@ SlowPathReturnType JIT_OPERATION operationOptimize(ExecState* exec, int32_t byte
codeBlock->updateAllPredictions();
if (Options::verboseOSR())
dataLog("Choosing not to optimize ", *codeBlock, " yet, because the threshold hasn't been reached.\n");
- return encodeResult(0, 0);
+ return 0;
}
- if (vm.enabledProfiler()) {
- updateAllPredictionsAndOptimizeAfterWarmUp(codeBlock);
- return encodeResult(0, 0);
- }
-
- Debugger* debugger = codeBlock->globalObject()->debugger();
- if (debugger && (debugger->isStepping() || codeBlock->baselineAlternative()->hasDebuggerRequests())) {
- updateAllPredictionsAndOptimizeAfterWarmUp(codeBlock);
- return encodeResult(0, 0);
- }
-
if (codeBlock->m_shouldAlwaysBeInlined) {
- updateAllPredictionsAndOptimizeAfterWarmUp(codeBlock);
+ codeBlock->updateAllPredictions();
+ codeBlock->optimizeAfterWarmUp();
if (Options::verboseOSR())
dataLog("Choosing not to optimize ", *codeBlock, " yet, because m_shouldAlwaysBeInlined == true.\n");
- return encodeResult(0, 0);
+ return 0;
}
// We cannot be in the process of asynchronous compilation and also have an optimized
// replacement.
- DFG::Worklist* worklist = DFG::existingGlobalDFGWorklistOrNull();
ASSERT(
- !worklist
- || !(worklist->compilationState(DFG::CompilationKey(codeBlock, DFG::DFGMode)) != DFG::Worklist::NotKnown
+ !vm.worklist
+ || !(vm.worklist->compilationState(DFG::CompilationKey(codeBlock, DFG::DFGMode)) != DFG::Worklist::NotKnown
&& codeBlock->hasOptimizedReplacement()));
DFG::Worklist::State worklistState;
- if (worklist) {
+ if (vm.worklist) {
// The call to DFG::Worklist::completeAllReadyPlansForVM() will complete all ready
// (i.e. compiled) code blocks. But if it completes ours, we also need to know
// what the result was so that we don't plow ahead and attempt OSR or immediate
@@ -1099,7 +1058,7 @@ SlowPathReturnType JIT_OPERATION operationOptimize(ExecState* exec, int32_t byte
// probably a waste of memory. Our goal here is to complete code blocks as soon as
// possible in order to minimize the chances of us executing baseline code after
// optimized code is already available.
- worklistState = worklist->completeAllReadyPlansForVM(
+ worklistState = vm.worklist->completeAllReadyPlansForVM(
vm, DFG::CompilationKey(codeBlock, DFG::DFGMode));
} else
worklistState = DFG::Worklist::NotKnown;
@@ -1109,7 +1068,7 @@ SlowPathReturnType JIT_OPERATION operationOptimize(ExecState* exec, int32_t byte
// replacement.
RELEASE_ASSERT(!codeBlock->hasOptimizedReplacement());
codeBlock->setOptimizationThresholdBasedOnCompilationResult(CompilationDeferred);
- return encodeResult(0, 0);
+ return 0;
}
if (worklistState == DFG::Worklist::Compiled) {
@@ -1122,7 +1081,7 @@ SlowPathReturnType JIT_OPERATION operationOptimize(ExecState* exec, int32_t byte
codeBlock->updateAllPredictions();
if (Options::verboseOSR())
dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
- return encodeResult(0, 0);
+ return 0;
}
} else if (codeBlock->hasOptimizedReplacement()) {
if (Options::verboseOSR())
@@ -1146,8 +1105,8 @@ SlowPathReturnType JIT_OPERATION operationOptimize(ExecState* exec, int32_t byte
"Triggering reoptimization of ", *codeBlock,
"(", *codeBlock->replacement(), ") (in loop).\n");
}
- codeBlock->replacement()->jettison(Profiler::JettisonDueToBaselineLoopReoptimizationTrigger, CountReoptimization);
- return encodeResult(0, 0);
+ codeBlock->replacement()->jettison(CountReoptimization);
+ return 0;
}
} else {
if (!codeBlock->shouldOptimizeNow()) {
@@ -1156,7 +1115,7 @@ SlowPathReturnType JIT_OPERATION operationOptimize(ExecState* exec, int32_t byte
"Delaying optimization for ", *codeBlock,
" because of insufficient profiling.\n");
}
- return encodeResult(0, 0);
+ return 0;
}
if (Options::verboseOSR())
@@ -1170,31 +1129,40 @@ SlowPathReturnType JIT_OPERATION operationOptimize(ExecState* exec, int32_t byte
Operands<JSValue> mustHandleValues(codeBlock->numParameters(), numVarsWithValues);
for (size_t i = 0; i < mustHandleValues.size(); ++i) {
int operand = mustHandleValues.operandForIndex(i);
- mustHandleValues[i] = exec->uncheckedR(operand).jsValue();
+ if (operandIsArgument(operand)
+ && !VirtualRegister(operand).toArgument()
+ && codeBlock->codeType() == FunctionCode
+ && codeBlock->specializationKind() == CodeForConstruct) {
+ // Ugh. If we're in a constructor, the 'this' argument may hold garbage. It will
+ // also never be used. It doesn't matter what we put into the value for this,
+ // but it has to be an actual value that can be grokked by subsequent DFG passes,
+ // so we sanitize it here by turning it into Undefined.
+ mustHandleValues[i] = jsUndefined();
+ } else
+ mustHandleValues[i] = exec->uncheckedR(operand).jsValue();
}
- RefPtr<CodeBlock> replacementCodeBlock = codeBlock->newReplacement();
CompilationResult result = DFG::compile(
- vm, replacementCodeBlock.get(), 0, DFG::DFGMode, bytecodeIndex,
- mustHandleValues, JITToDFGDeferredCompilationCallback::create());
+ vm, codeBlock->newReplacement().get(), DFG::DFGMode, bytecodeIndex,
+ mustHandleValues, JITToDFGDeferredCompilationCallback::create(),
+ vm.ensureWorklist());
- if (result != CompilationSuccessful) {
- ASSERT(result == CompilationDeferred || replacementCodeBlock->hasOneRef());
- return encodeResult(0, 0);
- }
+ if (result != CompilationSuccessful)
+ return 0;
}
CodeBlock* optimizedCodeBlock = codeBlock->replacement();
ASSERT(JITCode::isOptimizingJIT(optimizedCodeBlock->jitType()));
- if (void* dataBuffer = DFG::prepareOSREntry(exec, optimizedCodeBlock, bytecodeIndex)) {
+ if (void* address = DFG::prepareOSREntry(exec, optimizedCodeBlock, bytecodeIndex)) {
if (Options::verboseOSR()) {
dataLog(
- "Performing OSR ", *codeBlock, " -> ", *optimizedCodeBlock, ".\n");
+ "Performing OSR ", *codeBlock, " -> ", *optimizedCodeBlock, ", address ",
+ RawPointer(OUR_RETURN_ADDRESS), " -> ", RawPointer(address), ".\n");
}
codeBlock->optimizeSoon();
- return encodeResult(vm.getCTIStub(DFG::osrEntryThunkGenerator).code().executableAddress(), dataBuffer);
+ return static_cast<char*>(address);
}
if (Options::verboseOSR()) {
@@ -1222,15 +1190,15 @@ SlowPathReturnType JIT_OPERATION operationOptimize(ExecState* exec, int32_t byte
"Triggering reoptimization of ", *codeBlock, " -> ",
*codeBlock->replacement(), " (after OSR fail).\n");
}
- optimizedCodeBlock->jettison(Profiler::JettisonDueToBaselineLoopReoptimizationTriggerOnOSREntryFail, CountReoptimization);
- return encodeResult(0, 0);
+ optimizedCodeBlock->jettison(CountReoptimization);
+ return 0;
}
// OSR failed this time, but it might succeed next time! Let the code run a bit
// longer and then try again.
codeBlock->optimizeAfterWarmUp();
- return encodeResult(0, 0);
+ return 0;
}
#endif
@@ -1245,32 +1213,6 @@ void JIT_OPERATION operationPutByIndex(ExecState* exec, EncodedJSValue encodedAr
}
#if USE(JSVALUE64)
-void JIT_OPERATION operationPutGetterById(ExecState* exec, EncodedJSValue encodedObjectValue, Identifier* identifier, EncodedJSValue encodedGetterValue)
-{
- VM& vm = exec->vm();
- NativeCallFrameTracer tracer(&vm, exec);
-
- ASSERT(JSValue::decode(encodedObjectValue).isObject());
- JSObject* baseObj = asObject(JSValue::decode(encodedObjectValue));
-
- JSValue getter = JSValue::decode(encodedGetterValue);
- ASSERT(getter.isObject());
- baseObj->putGetter(exec, *identifier, asObject(getter));
-}
-
-void JIT_OPERATION operationPutSetterById(ExecState* exec, EncodedJSValue encodedObjectValue, Identifier* identifier, EncodedJSValue encodedSetterValue)
-{
- VM& vm = exec->vm();
- NativeCallFrameTracer tracer(&vm, exec);
-
- ASSERT(JSValue::decode(encodedObjectValue).isObject());
- JSObject* baseObj = asObject(JSValue::decode(encodedObjectValue));
-
- JSValue setter = JSValue::decode(encodedSetterValue);
- ASSERT(setter.isObject());
- baseObj->putSetter(exec, *identifier, asObject(setter));
-}
-
void JIT_OPERATION operationPutGetterSetter(ExecState* exec, EncodedJSValue encodedObjectValue, Identifier* identifier, EncodedJSValue encodedGetterValue, EncodedJSValue encodedSetterValue)
{
VM& vm = exec->vm();
@@ -1279,7 +1221,7 @@ void JIT_OPERATION operationPutGetterSetter(ExecState* exec, EncodedJSValue enco
ASSERT(JSValue::decode(encodedObjectValue).isObject());
JSObject* baseObj = asObject(JSValue::decode(encodedObjectValue));
- GetterSetter* accessor = GetterSetter::create(vm, exec->lexicalGlobalObject());
+ GetterSetter* accessor = GetterSetter::create(vm);
JSValue getter = JSValue::decode(encodedGetterValue);
JSValue setter = JSValue::decode(encodedSetterValue);
@@ -1288,13 +1230,13 @@ void JIT_OPERATION operationPutGetterSetter(ExecState* exec, EncodedJSValue enco
ASSERT(getter.isObject() || setter.isObject());
if (!getter.isUndefined())
- accessor->setGetter(vm, exec->lexicalGlobalObject(), asObject(getter));
+ accessor->setGetter(vm, asObject(getter));
if (!setter.isUndefined())
- accessor->setSetter(vm, exec->lexicalGlobalObject(), asObject(setter));
+ accessor->setSetter(vm, asObject(setter));
baseObj->putDirectAccessor(exec, *identifier, accessor, Accessor);
}
#else
-void JIT_OPERATION operationPutGetterById(ExecState* exec, JSCell* object, Identifier* identifier, JSCell* getter)
+void JIT_OPERATION operationPutGetterSetter(ExecState* exec, JSCell* object, Identifier* identifier, JSCell* getter, JSCell* setter)
{
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
@@ -1302,51 +1244,48 @@ void JIT_OPERATION operationPutGetterById(ExecState* exec, JSCell* object, Ident
ASSERT(object && object->isObject());
JSObject* baseObj = object->getObject();
- ASSERT(getter->isObject());
- baseObj->putGetter(exec, *identifier, getter);
+ GetterSetter* accessor = GetterSetter::create(vm);
+
+ ASSERT(!getter || getter->isObject());
+ ASSERT(!setter || setter->isObject());
+ ASSERT(getter || setter);
+
+ if (getter)
+ accessor->setGetter(vm, getter->getObject());
+ if (setter)
+ accessor->setSetter(vm, setter->getObject());
+ baseObj->putDirectAccessor(exec, *identifier, accessor, Accessor);
}
+#endif
-void JIT_OPERATION operationPutSetterById(ExecState* exec, JSCell* object, Identifier* identifier, JSCell* setter)
+void JIT_OPERATION operationPushNameScope(ExecState* exec, Identifier* identifier, EncodedJSValue encodedValue, int32_t attibutes)
{
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
- ASSERT(object && object->isObject());
- JSObject* baseObj = object->getObject();
+ JSNameScope* scope = JSNameScope::create(exec, *identifier, JSValue::decode(encodedValue), attibutes);
- ASSERT(setter->isObject());
- baseObj->putSetter(exec, *identifier, setter);
+ exec->setScope(scope);
}
-void JIT_OPERATION operationPutGetterSetter(ExecState* exec, JSCell* object, Identifier* identifier, JSCell* getter, JSCell* setter)
+void JIT_OPERATION operationPushWithScope(ExecState* exec, EncodedJSValue encodedValue)
{
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
- ASSERT(object && object->isObject());
- JSObject* baseObj = object->getObject();
-
- GetterSetter* accessor = GetterSetter::create(vm, exec->lexicalGlobalObject());
-
- ASSERT(!getter || getter->isObject());
- ASSERT(!setter || setter->isObject());
- ASSERT(getter || setter);
+ JSObject* o = JSValue::decode(encodedValue).toObject(exec);
+ if (vm.exception())
+ return;
- if (getter)
- accessor->setGetter(vm, exec->lexicalGlobalObject(), getter->getObject());
- if (setter)
- accessor->setSetter(vm, exec->lexicalGlobalObject(), setter->getObject());
- baseObj->putDirectAccessor(exec, *identifier, accessor, Accessor);
+ exec->setScope(JSWithScope::create(exec, o));
}
-#endif
-void JIT_OPERATION operationPopScope(ExecState* exec, int32_t scopeReg)
+void JIT_OPERATION operationPopScope(ExecState* exec)
{
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
- JSScope* scope = exec->uncheckedR(scopeReg).Register::scope();
- exec->uncheckedR(scopeReg) = scope->next();
+ exec->setScope(exec->scope()->next());
}
void JIT_OPERATION operationProfileDidCall(ExecState* exec, EncodedJSValue encodedValue)
@@ -1369,246 +1308,141 @@ void JIT_OPERATION operationProfileWillCall(ExecState* exec, EncodedJSValue enco
EncodedJSValue JIT_OPERATION operationCheckHasInstance(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBaseVal)
{
- VM& vm = exec->vm();
- NativeCallFrameTracer tracer(&vm, exec);
+ VM* vm = &exec->vm();
+ NativeCallFrameTracer tracer(vm, exec);
JSValue value = JSValue::decode(encodedValue);
JSValue baseVal = JSValue::decode(encodedBaseVal);
if (baseVal.isObject()) {
JSObject* baseObject = asObject(baseVal);
- ASSERT(!baseObject->structure(vm)->typeInfo().implementsDefaultHasInstance());
- if (baseObject->structure(vm)->typeInfo().implementsHasInstance()) {
- bool result = baseObject->methodTable(vm)->customHasInstance(baseObject, exec, value);
+ ASSERT(!baseObject->structure()->typeInfo().implementsDefaultHasInstance());
+ if (baseObject->structure()->typeInfo().implementsHasInstance()) {
+ bool result = baseObject->methodTable()->customHasInstance(baseObject, exec, value);
return JSValue::encode(jsBoolean(result));
}
}
- vm.throwException(exec, createInvalidInstanceofParameterError(exec, baseVal));
+ vm->throwException(exec, createInvalidParameterError(exec, "instanceof", baseVal));
return JSValue::encode(JSValue());
}
+JSCell* JIT_OPERATION operationCreateActivation(ExecState* exec, int32_t offset)
+{
+ VM& vm = exec->vm();
+ NativeCallFrameTracer tracer(&vm, exec);
+ JSActivation* activation = JSActivation::create(vm, exec, exec->registers() + offset, exec->codeBlock());
+ exec->setScope(activation);
+ return activation;
}
-static bool canAccessArgumentIndexQuickly(JSObject& object, uint32_t index)
+JSCell* JIT_OPERATION operationCreateArguments(ExecState* exec)
{
- switch (object.structure()->typeInfo().type()) {
- case DirectArgumentsType: {
- DirectArguments* directArguments = jsCast<DirectArguments*>(&object);
- if (directArguments->canAccessArgumentIndexQuicklyInDFG(index))
- return true;
- break;
- }
- case ScopedArgumentsType: {
- ScopedArguments* scopedArguments = jsCast<ScopedArguments*>(&object);
- if (scopedArguments->canAccessArgumentIndexQuicklyInDFG(index))
- return true;
- break;
- }
- default:
- break;
- }
- return false;
+ VM& vm = exec->vm();
+ NativeCallFrameTracer tracer(&vm, exec);
+ // NB: This needs to be exceedingly careful with top call frame tracking, since it
+ // may be called from OSR exit, while the state of the call stack is bizarre.
+ Arguments* result = Arguments::create(vm, exec);
+ ASSERT(!vm.exception());
+ return result;
}
-static JSValue getByVal(ExecState* exec, JSValue baseValue, JSValue subscript, ByValInfo* byValInfo, ReturnAddressPtr returnAddress)
+EncodedJSValue JIT_OPERATION operationGetArgumentsLength(ExecState* exec, int32_t argumentsRegister)
+{
+ VM& vm = exec->vm();
+ NativeCallFrameTracer tracer(&vm, exec);
+ // Here we can assume that the argumernts were created. Because otherwise the JIT code would
+ // have not made this call.
+ Identifier ident(&vm, "length");
+ JSValue baseValue = exec->uncheckedR(argumentsRegister).jsValue();
+ PropertySlot slot(baseValue);
+ return JSValue::encode(baseValue.get(exec, ident, slot));
+}
+
+}
+
+static JSValue getByVal(ExecState* exec, JSValue baseValue, JSValue subscript, ReturnAddressPtr returnAddress)
{
if (LIKELY(baseValue.isCell() && subscript.isString())) {
- VM& vm = exec->vm();
- Structure& structure = *baseValue.asCell()->structure(vm);
- if (JSCell::canUseFastGetOwnProperty(structure)) {
- if (RefPtr<AtomicStringImpl> existingAtomicString = asString(subscript)->toExistingAtomicString(exec)) {
- if (JSValue result = baseValue.asCell()->fastGetOwnProperty(vm, structure, existingAtomicString.get())) {
- ASSERT(exec->locationAsBytecodeOffset());
- if (byValInfo->stubInfo && byValInfo->cachedId.impl() != existingAtomicString)
- byValInfo->tookSlowPath = true;
- return result;
- }
- }
- }
+ if (JSValue result = baseValue.asCell()->fastGetOwnProperty(exec, asString(subscript)->value(exec)))
+ return result;
}
if (subscript.isUInt32()) {
- ASSERT(exec->locationAsBytecodeOffset());
- byValInfo->tookSlowPath = true;
-
uint32_t i = subscript.asUInt32();
- if (isJSString(baseValue)) {
- if (asString(baseValue)->canGetIndex(i)) {
- ctiPatchCallByReturnAddress(exec->codeBlock(), returnAddress, FunctionPtr(operationGetByValString));
- return asString(baseValue)->getIndex(exec, i);
- }
- byValInfo->arrayProfile->setOutOfBounds();
- } else if (baseValue.isObject()) {
- JSObject* object = asObject(baseValue);
- if (object->canGetIndexQuickly(i))
- return object->getIndexQuickly(i);
-
- if (!canAccessArgumentIndexQuickly(*object, i))
- byValInfo->arrayProfile->setOutOfBounds();
+ if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i)) {
+ ctiPatchCallByReturnAddress(exec->codeBlock(), returnAddress, FunctionPtr(operationGetByValString));
+ return asString(baseValue)->getIndex(exec, i);
}
-
return baseValue.get(exec, i);
}
- baseValue.requireObjectCoercible(exec);
- if (exec->hadException())
- return jsUndefined();
- auto property = subscript.toPropertyKey(exec);
- if (exec->hadException())
- return jsUndefined();
-
- ASSERT(exec->locationAsBytecodeOffset());
- if (byValInfo->stubInfo && byValInfo->cachedId != property)
- byValInfo->tookSlowPath = true;
+ if (isName(subscript))
+ return baseValue.get(exec, jsCast<NameInstance*>(subscript.asCell())->privateName());
+ Identifier property(exec, subscript.toString(exec)->value(exec));
return baseValue.get(exec, property);
}
extern "C" {
-EncodedJSValue JIT_OPERATION operationGetByValGeneric(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo* byValInfo)
+EncodedJSValue JIT_OPERATION operationGetByValGeneric(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript)
{
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
JSValue baseValue = JSValue::decode(encodedBase);
JSValue subscript = JSValue::decode(encodedSubscript);
- JSValue result = getByVal(exec, baseValue, subscript, byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS));
+ JSValue result = getByVal(exec, baseValue, subscript, ReturnAddressPtr(OUR_RETURN_ADDRESS));
return JSValue::encode(result);
}
-EncodedJSValue JIT_OPERATION operationGetByValOptimize(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo* byValInfo)
+EncodedJSValue JIT_OPERATION operationGetByValDefault(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript)
{
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
JSValue baseValue = JSValue::decode(encodedBase);
JSValue subscript = JSValue::decode(encodedSubscript);
-
+
if (baseValue.isObject() && subscript.isInt32()) {
// See if it's worth optimizing this at all.
JSObject* object = asObject(baseValue);
bool didOptimize = false;
- ASSERT(exec->locationAsBytecodeOffset());
- ASSERT(!byValInfo->stubRoutine);
-
- if (hasOptimizableIndexing(object->structure(vm))) {
+ unsigned bytecodeOffset = exec->locationAsBytecodeOffset();
+ ASSERT(bytecodeOffset);
+ ByValInfo& byValInfo = exec->codeBlock()->getByValInfo(bytecodeOffset - 1);
+ ASSERT(!byValInfo.stubRoutine);
+
+ if (hasOptimizableIndexing(object->structure())) {
// Attempt to optimize.
- Structure* structure = object->structure(vm);
- JITArrayMode arrayMode = jitArrayModeForStructure(structure);
- if (arrayMode != byValInfo->arrayMode) {
- // If we reached this case, we got an interesting array mode we did not expect when we compiled.
- // Let's update the profile to do better next time.
- CodeBlock* codeBlock = exec->codeBlock();
- ConcurrentJITLocker locker(codeBlock->m_lock);
- byValInfo->arrayProfile->computeUpdatedPrediction(locker, codeBlock, structure);
-
- JIT::compileGetByVal(&vm, exec->codeBlock(), byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode);
+ JITArrayMode arrayMode = jitArrayModeForStructure(object->structure());
+ if (arrayMode != byValInfo.arrayMode) {
+ JIT::compileGetByVal(&vm, exec->codeBlock(), &byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode);
didOptimize = true;
}
}
-
+
if (!didOptimize) {
// If we take slow path more than 10 times without patching then make sure we
// never make that mistake again. Or, if we failed to patch and we have some object
// that intercepts indexed get, then don't even wait until 10 times. For cases
// where we see non-index-intercepting objects, this gives 10 iterations worth of
// opportunity for us to observe that the get_by_val may be polymorphic.
- if (++byValInfo->slowPathCount >= 10
- || object->structure(vm)->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) {
+ if (++byValInfo.slowPathCount >= 10
+ || object->structure()->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) {
// Don't ever try to optimize.
- ctiPatchCallByReturnAddress(exec->codeBlock(), ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationGetByValGeneric));
+ RepatchBuffer repatchBuffer(exec->codeBlock());
+ repatchBuffer.relinkCallerToFunction(ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationGetByValGeneric));
}
}
}
-
- if (baseValue.isObject() && (subscript.isSymbol() || subscript.isString())) {
- const Identifier propertyName = subscript.toPropertyKey(exec);
-
- if (!subscript.isString() || !parseIndex(propertyName)) {
- ASSERT(exec->locationAsBytecodeOffset());
- ASSERT(!byValInfo->stubRoutine);
- JIT::compileGetByValWithCachedId(&vm, exec->codeBlock(), byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), propertyName);
- }
-
- PropertySlot slot(baseValue);
- bool hasResult = baseValue.getPropertySlot(exec, propertyName, slot);
- return JSValue::encode(hasResult ? slot.getValue(exec, propertyName) : jsUndefined());
- }
-
- JSValue result = getByVal(exec, baseValue, subscript, byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS));
- return JSValue::encode(result);
-}
-
-EncodedJSValue JIT_OPERATION operationHasIndexedPropertyDefault(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo* byValInfo)
-{
- VM& vm = exec->vm();
- NativeCallFrameTracer tracer(&vm, exec);
- JSValue baseValue = JSValue::decode(encodedBase);
- JSValue subscript = JSValue::decode(encodedSubscript);
-
- ASSERT(baseValue.isObject());
- ASSERT(subscript.isUInt32());
-
- JSObject* object = asObject(baseValue);
- bool didOptimize = false;
-
- ASSERT(exec->locationAsBytecodeOffset());
- ASSERT(!byValInfo->stubRoutine);
-
- if (hasOptimizableIndexing(object->structure(vm))) {
- // Attempt to optimize.
- JITArrayMode arrayMode = jitArrayModeForStructure(object->structure(vm));
- if (arrayMode != byValInfo->arrayMode) {
- JIT::compileHasIndexedProperty(&vm, exec->codeBlock(), byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode);
- didOptimize = true;
- }
- }
-
- if (!didOptimize) {
- // If we take slow path more than 10 times without patching then make sure we
- // never make that mistake again. Or, if we failed to patch and we have some object
- // that intercepts indexed get, then don't even wait until 10 times. For cases
- // where we see non-index-intercepting objects, this gives 10 iterations worth of
- // opportunity for us to observe that the get_by_val may be polymorphic.
- if (++byValInfo->slowPathCount >= 10
- || object->structure(vm)->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) {
- // Don't ever try to optimize.
- ctiPatchCallByReturnAddress(exec->codeBlock(), ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationHasIndexedPropertyGeneric));
- }
- }
-
- uint32_t index = subscript.asUInt32();
- if (object->canGetIndexQuickly(index))
- return JSValue::encode(JSValue(JSValue::JSTrue));
-
- if (!canAccessArgumentIndexQuickly(*object, index))
- byValInfo->arrayProfile->setOutOfBounds();
- return JSValue::encode(jsBoolean(object->hasProperty(exec, index)));
-}
-
-EncodedJSValue JIT_OPERATION operationHasIndexedPropertyGeneric(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo* byValInfo)
-{
- VM& vm = exec->vm();
- NativeCallFrameTracer tracer(&vm, exec);
- JSValue baseValue = JSValue::decode(encodedBase);
- JSValue subscript = JSValue::decode(encodedSubscript);
- ASSERT(baseValue.isObject());
- ASSERT(subscript.isUInt32());
-
- JSObject* object = asObject(baseValue);
- uint32_t index = subscript.asUInt32();
- if (object->canGetIndexQuickly(index))
- return JSValue::encode(JSValue(JSValue::JSTrue));
-
- if (!canAccessArgumentIndexQuickly(*object, index))
- byValInfo->arrayProfile->setOutOfBounds();
- return JSValue::encode(jsBoolean(object->hasProperty(exec, subscript.asUInt32())));
+ JSValue result = getByVal(exec, baseValue, subscript, ReturnAddressPtr(OUR_RETURN_ADDRESS));
+ return JSValue::encode(result);
}
-EncodedJSValue JIT_OPERATION operationGetByValString(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo* byValInfo)
+EncodedJSValue JIT_OPERATION operationGetByValString(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript)
{
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
@@ -1622,23 +1456,37 @@ EncodedJSValue JIT_OPERATION operationGetByValString(ExecState* exec, EncodedJSV
result = asString(baseValue)->getIndex(exec, i);
else {
result = baseValue.get(exec, i);
- if (!isJSString(baseValue)) {
- ASSERT(exec->locationAsBytecodeOffset());
- ctiPatchCallByReturnAddress(exec->codeBlock(), ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(byValInfo->stubRoutine ? operationGetByValGeneric : operationGetByValOptimize));
- }
+ if (!isJSString(baseValue))
+ ctiPatchCallByReturnAddress(exec->codeBlock(), ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationGetByValDefault));
}
- } else {
- baseValue.requireObjectCoercible(exec);
- if (exec->hadException())
- return JSValue::encode(jsUndefined());
- auto property = subscript.toPropertyKey(exec);
- if (exec->hadException())
- return JSValue::encode(jsUndefined());
+ } else if (isName(subscript))
+ result = baseValue.get(exec, jsCast<NameInstance*>(subscript.asCell())->privateName());
+ else {
+ Identifier property(exec, subscript.toString(exec)->value(exec));
result = baseValue.get(exec, property);
}
return JSValue::encode(result);
}
+
+void JIT_OPERATION operationTearOffActivation(ExecState* exec, JSCell* activationCell)
+{
+ VM& vm = exec->vm();
+ NativeCallFrameTracer tracer(&vm, exec);
+
+ ASSERT(exec->codeBlock()->needsFullScopeChain());
+ jsCast<JSActivation*>(activationCell)->tearOff(vm);
+}
+
+void JIT_OPERATION operationTearOffArguments(ExecState* exec, JSCell* argumentsCell, JSCell* activationCell)
+{
+ ASSERT(exec->codeBlock()->usesArguments());
+ if (activationCell) {
+ jsCast<Arguments*>(argumentsCell)->didTearOffActivation(exec, jsCast<JSActivation*>(activationCell));
+ return;
+ }
+ jsCast<Arguments*>(argumentsCell)->tearOff(exec);
+}
EncodedJSValue JIT_OPERATION operationDeleteById(ExecState* exec, EncodedJSValue encodedBase, const Identifier* identifier)
{
@@ -1646,13 +1494,25 @@ EncodedJSValue JIT_OPERATION operationDeleteById(ExecState* exec, EncodedJSValue
NativeCallFrameTracer tracer(&vm, exec);
JSObject* baseObj = JSValue::decode(encodedBase).toObject(exec);
- bool couldDelete = baseObj->methodTable(vm)->deleteProperty(baseObj, exec, *identifier);
+ bool couldDelete = baseObj->methodTable()->deleteProperty(baseObj, exec, *identifier);
JSValue result = jsBoolean(couldDelete);
if (!couldDelete && exec->codeBlock()->isStrictMode())
- vm.throwException(exec, createTypeError(exec, ASCIILiteral("Unable to delete property.")));
+ vm.throwException(exec, createTypeError(exec, "Unable to delete property."));
return JSValue::encode(result);
}
+JSCell* JIT_OPERATION operationGetPNames(ExecState* exec, JSObject* obj)
+{
+ VM& vm = exec->vm();
+ NativeCallFrameTracer tracer(&vm, exec);
+
+ Structure* structure = obj->structure();
+ JSPropertyNameIterator* jsPropertyNameIterator = structure->enumerationCache();
+ if (!jsPropertyNameIterator || jsPropertyNameIterator->cachedPrototypeChain() != structure->prototypeChain(exec))
+ jsPropertyNameIterator = JSPropertyNameIterator::create(exec, obj);
+ return jsPropertyNameIterator;
+}
+
EncodedJSValue JIT_OPERATION operationInstanceOf(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedProto)
{
VM& vm = exec->vm();
@@ -1666,21 +1526,23 @@ EncodedJSValue JIT_OPERATION operationInstanceOf(ExecState* exec, EncodedJSValue
return JSValue::encode(jsBoolean(result));
}
-int32_t JIT_OPERATION operationSizeFrameForVarargs(ExecState* exec, EncodedJSValue encodedArguments, int32_t numUsedStackSlots, int32_t firstVarArgOffset)
+CallFrame* JIT_OPERATION operationSizeAndAllocFrameForVarargs(ExecState* exec, EncodedJSValue encodedArguments, int32_t firstFreeRegister)
{
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
JSStack* stack = &exec->interpreter()->stack();
JSValue arguments = JSValue::decode(encodedArguments);
- return sizeFrameForVarargs(exec, stack, arguments, numUsedStackSlots, firstVarArgOffset);
+ CallFrame* newCallFrame = sizeAndAllocFrameForVarargs(exec, stack, arguments, firstFreeRegister);
+ return newCallFrame;
}
-CallFrame* JIT_OPERATION operationSetupVarargsFrame(ExecState* exec, CallFrame* newCallFrame, EncodedJSValue encodedArguments, int32_t firstVarArgOffset, int32_t length)
+CallFrame* JIT_OPERATION operationLoadVarargs(ExecState* exec, CallFrame* newCallFrame, EncodedJSValue encodedThis, EncodedJSValue encodedArguments)
{
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
+ JSValue thisValue = JSValue::decode(encodedThis);
JSValue arguments = JSValue::decode(encodedArguments);
- setupVarargsFrame(exec, newCallFrame, arguments, firstVarArgOffset, length);
+ loadVarargs(exec, newCallFrame, thisValue, arguments);
return newCallFrame;
}
@@ -1747,13 +1609,12 @@ char* JIT_OPERATION operationSwitchStringWithUnknownKeyType(ExecState* exec, Enc
return reinterpret_cast<char*>(result);
}
-EncodedJSValue JIT_OPERATION operationResolveScope(ExecState* exec, int32_t scopeReg, int32_t identifierIndex)
+EncodedJSValue JIT_OPERATION operationResolveScope(ExecState* exec, int32_t identifierIndex)
{
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
const Identifier& ident = exec->codeBlock()->identifier(identifierIndex);
- JSScope* scope = exec->uncheckedR(scopeReg).Register::scope();
- return JSValue::encode(JSScope::resolve(exec, scope, ident));
+ return JSValue::encode(JSScope::resolve(exec, exec->scope(), ident));
}
EncodedJSValue JIT_OPERATION operationGetFromScope(ExecState* exec, Instruction* bytecodePC)
@@ -1775,15 +1636,11 @@ EncodedJSValue JIT_OPERATION operationGetFromScope(ExecState* exec, Instruction*
}
// Covers implicit globals. Since they don't exist until they first execute, we didn't know how to cache them at compile time.
- if (slot.isCacheableValue() && slot.slotBase() == scope && scope->structure(vm)->propertyAccessesAreCacheable()) {
+ if (slot.isCacheableValue() && slot.slotBase() == scope && scope->structure()->propertyAccessesAreCacheable()) {
if (modeAndType.type() == GlobalProperty || modeAndType.type() == GlobalPropertyWithVarInjectionChecks) {
- Structure* structure = scope->structure(vm);
- {
- ConcurrentJITLocker locker(codeBlock->m_lock);
- pc[5].u.structure.set(exec->vm(), codeBlock->ownerExecutable(), structure);
- pc[6].u.operand = slot.cachedOffset();
- }
- structure->startWatchingPropertyForReplacements(vm, slot.cachedOffset());
+ ConcurrentJITLocker locker(codeBlock->m_lock);
+ pc[5].u.structure.set(exec->vm(), codeBlock->ownerExecutable(), scope->structure());
+ pc[6].u.operand = slot.cachedOffset();
}
}
@@ -1801,13 +1658,7 @@ void JIT_OPERATION operationPutToScope(ExecState* exec, Instruction* bytecodePC)
JSObject* scope = jsCast<JSObject*>(exec->uncheckedR(pc[1].u.operand).jsValue());
JSValue value = exec->r(pc[3].u.operand).jsValue();
ResolveModeAndType modeAndType = ResolveModeAndType(pc[4].u.operand);
- if (modeAndType.type() == LocalClosureVar) {
- JSLexicalEnvironment* environment = jsCast<JSLexicalEnvironment*>(scope);
- environment->variableAt(ScopeOffset(pc[6].u.operand)).set(vm, environment, value);
- if (WatchpointSet* set = pc[5].u.watchpointSet)
- set->touch("Executed op_put_scope<LocalClosureVar>");
- return;
- }
+
if (modeAndType.mode() == ThrowIfNotFound && !scope->hasProperty(exec, ident)) {
exec->vm().throwException(exec, createUndefinedVariableError(exec, ident));
return;
@@ -1819,7 +1670,14 @@ void JIT_OPERATION operationPutToScope(ExecState* exec, Instruction* bytecodePC)
if (exec->vm().exception())
return;
- CommonSlowPaths::tryCachePutToScopeGlobal(exec, codeBlock, pc, scope, modeAndType, slot);
+ // Covers implicit globals. Since they don't exist until they first execute, we didn't know how to cache them at compile time.
+ if (modeAndType.type() == GlobalProperty || modeAndType.type() == GlobalPropertyWithVarInjectionChecks) {
+ if (slot.isCacheable() && slot.base() == scope && scope->structure()->propertyAccessesAreCacheable()) {
+ ConcurrentJITLocker locker(codeBlock->m_lock);
+ pc[5].u.structure.set(exec->vm(), codeBlock->ownerExecutable(), scope->structure());
+ pc[6].u.operand = slot.cachedOffset();
+ }
+ }
}
void JIT_OPERATION operationThrow(ExecState* exec, EncodedJSValue encodedExceptionValue)
@@ -1830,8 +1688,8 @@ void JIT_OPERATION operationThrow(ExecState* exec, EncodedJSValue encodedExcepti
JSValue exceptionValue = JSValue::decode(encodedExceptionValue);
vm->throwException(exec, exceptionValue);
- // Results stored out-of-band in vm.targetMachinePCForThrow, vm.callFrameForThrow & vm.vmEntryFrameForThrow
- genericUnwind(vm, exec);
+ // Results stored out-of-band in vm.targetMachinePCForThrow & vm.callFrameForThrow
+ genericUnwind(vm, exec, exceptionValue);
}
void JIT_OPERATION operationFlushWriteBarrierBuffer(ExecState* exec, JSCell* cell)
@@ -1845,7 +1703,7 @@ void JIT_OPERATION operationOSRWriteBarrier(ExecState* exec, JSCell* cell)
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
- vm->heap.writeBarrier(cell);
+ exec->heap()->writeBarrier(cell);
}
// NB: We don't include the value as part of the barrier because the write barrier elision
@@ -1855,7 +1713,7 @@ void JIT_OPERATION operationUnconditionalWriteBarrier(ExecState* exec, JSCell* c
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
- vm->heap.writeBarrier(cell);
+ Heap::writeBarrier(cell);
}
void JIT_OPERATION operationInitGlobalConst(ExecState* exec, Instruction* pc)
@@ -1864,24 +1722,18 @@ void JIT_OPERATION operationInitGlobalConst(ExecState* exec, Instruction* pc)
NativeCallFrameTracer tracer(vm, exec);
JSValue value = exec->r(pc[2].u.operand).jsValue();
- pc[1].u.variablePointer->set(*vm, exec->codeBlock()->globalObject(), value);
+ pc[1].u.registerPointer->set(*vm, exec->codeBlock()->globalObject(), value);
}
-void JIT_OPERATION lookupExceptionHandler(VM* vm, ExecState* exec)
+void JIT_OPERATION lookupExceptionHandler(ExecState* exec)
{
+ VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
- genericUnwind(vm, exec);
- ASSERT(vm->targetMachinePCForThrow);
-}
-void JIT_OPERATION lookupExceptionHandlerFromCallerFrame(VM* vm, ExecState* exec)
-{
- VMEntryFrame* vmEntryFrame = vm->topVMEntryFrame;
- CallFrame* callerFrame = exec->callerFrame(vmEntryFrame);
- ASSERT(callerFrame);
-
- NativeCallFrameTracerWithRestore tracer(vm, vmEntryFrame, callerFrame);
- genericUnwind(vm, callerFrame);
+ JSValue exceptionValue = exec->exception();
+ ASSERT(exceptionValue);
+
+ genericUnwind(vm, exec, exceptionValue);
ASSERT(vm->targetMachinePCForThrow);
}
@@ -1889,72 +1741,9 @@ void JIT_OPERATION operationVMHandleException(ExecState* exec)
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
- genericUnwind(vm, exec);
-}
-
-// This function "should" just take the ExecState*, but doing so would make it more difficult
-// to call from exception check sites. So, unlike all of our other functions, we allow
-// ourselves to play some gnarly ABI tricks just to simplify the calling convention. This is
-// particularly safe here since this is never called on the critical path - it's only for
-// testing.
-void JIT_OPERATION operationExceptionFuzz()
-{
-#if COMPILER(GCC_OR_CLANG)
- ExecState* exec = static_cast<ExecState*>(__builtin_frame_address(1));
- void* returnPC = __builtin_return_address(0);
- doExceptionFuzzing(exec, "JITOperations", returnPC);
-#endif // COMPILER(GCC_OR_CLANG)
-}
-
-EncodedJSValue JIT_OPERATION operationHasGenericProperty(ExecState* exec, EncodedJSValue encodedBaseValue, JSCell* propertyName)
-{
- VM& vm = exec->vm();
- NativeCallFrameTracer tracer(&vm, exec);
- JSValue baseValue = JSValue::decode(encodedBaseValue);
- if (baseValue.isUndefinedOrNull())
- return JSValue::encode(jsBoolean(false));
-
- JSObject* base = baseValue.toObject(exec);
- return JSValue::encode(jsBoolean(base->hasProperty(exec, asString(propertyName)->toIdentifier(exec))));
-}
-
-EncodedJSValue JIT_OPERATION operationHasIndexedProperty(ExecState* exec, JSCell* baseCell, int32_t subscript)
-{
- VM& vm = exec->vm();
- NativeCallFrameTracer tracer(&vm, exec);
- JSObject* object = baseCell->toObject(exec, exec->lexicalGlobalObject());
- return JSValue::encode(jsBoolean(object->hasProperty(exec, subscript)));
-}
-
-JSCell* JIT_OPERATION operationGetPropertyEnumerator(ExecState* exec, JSCell* cell)
-{
- VM& vm = exec->vm();
- NativeCallFrameTracer tracer(&vm, exec);
-
- JSObject* base = cell->toObject(exec, exec->lexicalGlobalObject());
- return propertyNameEnumerator(exec, base);
-}
-
-EncodedJSValue JIT_OPERATION operationNextEnumeratorPname(ExecState* exec, JSCell* enumeratorCell, int32_t index)
-{
- VM& vm = exec->vm();
- NativeCallFrameTracer tracer(&vm, exec);
- JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(enumeratorCell);
- JSString* propertyName = enumerator->propertyNameAtIndex(index);
- return JSValue::encode(propertyName ? propertyName : jsNull());
-}
-
-JSCell* JIT_OPERATION operationToIndexString(ExecState* exec, int32_t index)
-{
- VM& vm = exec->vm();
- NativeCallFrameTracer tracer(&vm, exec);
- return jsString(exec, Identifier::from(exec, index).string());
-}
-
-void JIT_OPERATION operationProcessTypeProfilerLog(ExecState* exec)
-{
- exec->vm().typeProfilerLog()->processLogEntries(ASCIILiteral("Log Full, called from inside baseline JIT"));
+ ASSERT(!exec->isVMEntrySentinel());
+ genericUnwind(vm, exec, vm->exception());
}
} // extern "C"
@@ -1969,31 +1758,28 @@ extern "C" EncodedJSValue HOST_CALL_RETURN_VALUE_OPTION getHostCallReturnValueWi
return JSValue::encode(exec->vm().hostCallReturnValue);
}
-#if COMPILER(GCC_OR_CLANG) && CPU(X86_64)
+#if COMPILER(GCC) && CPU(X86_64)
asm (
".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
HIDE_SYMBOL(getHostCallReturnValue) "\n"
SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
+ "mov 0(%rbp), %rbp\n" // CallerFrameAndPC::callerFrame
"mov %rbp, %rdi\n"
"jmp " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
);
-#elif COMPILER(GCC_OR_CLANG) && CPU(X86)
+#elif COMPILER(GCC) && CPU(X86)
asm (
".text" "\n" \
".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
HIDE_SYMBOL(getHostCallReturnValue) "\n"
SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
- "push %ebp\n"
- "leal -4(%esp), %esp\n"
- "push %ebp\n"
- "call " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
- "leal 8(%esp), %esp\n"
- "pop %ebp\n"
- "ret\n"
+ "mov 0(%ebp), %ebp\n" // CallerFrameAndPC::callerFrame
+ "mov %ebp, 4(%esp)\n"
+ "jmp " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
);
-#elif COMPILER(GCC_OR_CLANG) && CPU(ARM_THUMB2)
+#elif COMPILER(GCC) && CPU(ARM_THUMB2)
asm (
".text" "\n"
".align 2" "\n"
@@ -2002,17 +1788,19 @@ HIDE_SYMBOL(getHostCallReturnValue) "\n"
".thumb" "\n"
".thumb_func " THUMB_FUNC_PARAM(getHostCallReturnValue) "\n"
SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
+ "ldr r7, [r7, #0]" "\n" // CallerFrameAndPC::callerFrame
"mov r0, r7" "\n"
"b " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
);
-#elif COMPILER(GCC_OR_CLANG) && CPU(ARM_TRADITIONAL)
+#elif COMPILER(GCC) && CPU(ARM_TRADITIONAL)
asm (
".text" "\n"
".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
HIDE_SYMBOL(getHostCallReturnValue) "\n"
INLINE_ARM_FUNCTION(getHostCallReturnValue)
SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
+ "ldr r11, [r11, #0]" "\n" // CallerFrameAndPC::callerFrame
"mov r0, r11" "\n"
"b " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
);
@@ -2024,41 +1812,30 @@ asm (
".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
HIDE_SYMBOL(getHostCallReturnValue) "\n"
SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
+ "ldur x29, [x29, #0]" "\n"
"mov x0, x29" "\n"
"b " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
);
-#elif COMPILER(GCC_OR_CLANG) && CPU(MIPS)
-
-#if WTF_MIPS_PIC
-#define LOAD_FUNCTION_TO_T9(function) \
- ".set noreorder" "\n" \
- ".cpload $25" "\n" \
- ".set reorder" "\n" \
- "la $t9, " LOCAL_REFERENCE(function) "\n"
-#else
-#define LOAD_FUNCTION_TO_T9(function) "" "\n"
-#endif
-
+#elif COMPILER(GCC) && CPU(MIPS)
asm (
".text" "\n"
".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
HIDE_SYMBOL(getHostCallReturnValue) "\n"
SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
LOAD_FUNCTION_TO_T9(getHostCallReturnValueWithExecState)
+ "lw $fp, 0($fp)" "\n" // CallerFrameAndPC::callerFrame
"move $a0, $fp" "\n"
"b " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
);
-#elif COMPILER(GCC_OR_CLANG) && CPU(SH4)
-
-#define SH4_SCRATCH_REGISTER "r11"
-
+#elif COMPILER(GCC) && CPU(SH4)
asm (
".text" "\n"
".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
HIDE_SYMBOL(getHostCallReturnValue) "\n"
SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
+ "mov.l @r14, r14" "\n" // CallerFrameAndPC::callerFrame
"mov r14, r4" "\n"
"mov.l 2f, " SH4_SCRATCH_REGISTER "\n"
"braf " SH4_SCRATCH_REGISTER "\n"
@@ -2071,6 +1848,7 @@ SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
extern "C" {
__declspec(naked) EncodedJSValue HOST_CALL_RETURN_VALUE_OPTION getHostCallReturnValue()
{
+ __asm mov ebp, [ebp + 0]; // CallerFrameAndPC::callerFrame
__asm mov [esp + 4], ebp;
__asm jmp getHostCallReturnValueWithExecState
}