/*
- * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
#if ENABLE(JIT)
-#include "Arguments.h"
#include "ArrayConstructor.h"
#include "DFGCompilationMode.h"
#include "DFGDriver.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 "JITToDFGDeferredCompilationCallback.h"
+#include "JSCInlines.h"
+#include "JSCatchScope.h"
+#include "JSFunctionNameScope.h"
#include "JSGlobalObjectFunctions.h"
+#include "JSLexicalEnvironment.h"
#include "JSNameScope.h"
-#include "JSPropertyNameIterator.h"
+#include "JSPropertyNameEnumerator.h"
#include "JSStackInlines.h"
#include "JSWithScope.h"
+#include "LegacyProfiler.h"
#include "ObjectConstructor.h"
-#include "JSCInlines.h"
+#include "PropertyName.h"
#include "Repatch.h"
#include "RepatchBuffer.h"
+#include "ScopedArguments.h"
#include "TestRunnerUtils.h"
+#include "TypeProfilerLog.h"
#include <wtf/InlineASM.h>
namespace JSC {
-static unsigned s_numberOfExceptionFuzzChecks;
-unsigned numberOfExceptionFuzzChecks() { return s_numberOfExceptionFuzzChecks; }
+template<typename ScopeType>
+void pushNameScope(ExecState* exec, int32_t dst, SymbolTable* symbolTable, EncodedJSValue encodedValue)
+{
+ VM& vm = exec->vm();
+ NativeCallFrameTracer tracer(&vm, exec);
+
+ ASSERT(!JITCode::isOptimizingJIT(exec->codeBlock()->jitType()));
+
+ // FIXME: This won't work if this operation is called from the DFG or FTL.
+ // This should be changed to pass in the new scope.
+ JSScope* currentScope = exec->uncheckedR(dst).Register::scope();
+ JSNameScope* scope = ScopeType::create(vm, exec->lexicalGlobalObject(), currentScope, symbolTable, JSValue::decode(encodedValue));
+
+ // FIXME: This won't work if this operation is called from the DFG or FTL.
+ // This should be changed to return the new scope.
+ exec->uncheckedR(dst) = scope;
+}
extern "C" {
{
// We pass in our own code block, because the callframe hasn't been populated.
VM* vm = codeBlock->vm();
- CallFrame* callerFrame = exec->callerFrameSkippingVMEntrySentinel();
+
+ VMEntryFrame* vmEntryFrame = vm->topVMEntryFrame;
+ CallFrame* callerFrame = exec->callerFrame(vmEntryFrame);
if (!callerFrame)
callerFrame = exec;
- NativeCallFrameTracer tracer(vm, callerFrame);
+ NativeCallFrameTracerWithRestore tracer(vm, vmEntryFrame, callerFrame);
ErrorHandlingScope errorScope(*vm);
vm->throwException(callerFrame, createStackOverflowError(callerFrame));
}
int32_t JIT_OPERATION operationCallArityCheck(ExecState* exec)
{
VM* vm = &exec->vm();
- CallFrame* callerFrame = exec->callerFrameSkippingVMEntrySentinel();
- NativeCallFrameTracer tracer(vm, callerFrame);
+ VMEntryFrame* vmEntryFrame = vm->topVMEntryFrame;
+ CallFrame* callerFrame = exec->callerFrame(vmEntryFrame);
JSStack& stack = vm->interpreter->stack();
int32_t missingArgCount = CommonSlowPaths::arityCheckFor(exec, &stack, CodeForCall);
- if (missingArgCount < 0)
+ if (missingArgCount < 0) {
+ NativeCallFrameTracerWithRestore tracer(vm, vmEntryFrame, callerFrame);
throwStackOverflowError(callerFrame);
+ }
return missingArgCount;
}
int32_t JIT_OPERATION operationConstructArityCheck(ExecState* exec)
{
VM* vm = &exec->vm();
- CallFrame* callerFrame = exec->callerFrameSkippingVMEntrySentinel();
- NativeCallFrameTracer tracer(vm, callerFrame);
+ VMEntryFrame* vmEntryFrame = vm->topVMEntryFrame;
+ CallFrame* callerFrame = exec->callerFrame(vmEntryFrame);
JSStack& stack = vm->interpreter->stack();
int32_t missingArgCount = CommonSlowPaths::arityCheckFor(exec, &stack, CodeForConstruct);
- if (missingArgCount < 0)
+ if (missingArgCount < 0) {
+ NativeCallFrameTracerWithRestore tracer(vm, vmEntryFrame, callerFrame);
throwStackOverflowError(callerFrame);
+ }
return missingArgCount;
}
-EncodedJSValue JIT_OPERATION operationGetById(ExecState* exec, StructureStubInfo*, EncodedJSValue base, StringImpl* uid)
+EncodedJSValue JIT_OPERATION operationGetById(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, UniquedStringImpl* 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);
+ 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(vm, uid);
+ Identifier ident = Identifier::fromUid(vm, uid);
return JSValue::encode(baseValue.get(exec, ident, slot));
}
-EncodedJSValue JIT_OPERATION operationGetByIdBuildList(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, StringImpl* uid)
+EncodedJSValue JIT_OPERATION operationGetByIdBuildList(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, UniquedStringImpl* uid)
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
- Identifier ident(vm, uid);
+ Identifier ident = Identifier::fromUid(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 (accessType == static_cast<AccessType>(stubInfo->accessType))
buildGetByIDList(exec, baseValue, ident, slot, *stubInfo);
- return JSValue::encode(result);
+ return JSValue::encode(hasResult? slot.getValue(exec, ident) : jsUndefined());
}
-EncodedJSValue JIT_OPERATION operationGetByIdOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, StringImpl* uid)
+EncodedJSValue JIT_OPERATION operationGetByIdOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, UniquedStringImpl* uid)
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
- Identifier ident = uid->isEmptyUnique() ? Identifier::from(PrivateName(uid)) : Identifier(vm, uid);
- AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
+ Identifier ident = Identifier::fromUid(vm, uid);
JSValue baseValue = JSValue::decode(base);
PropertySlot slot(baseValue);
- JSValue result = baseValue.get(exec, ident, slot);
- if (accessType == static_cast<AccessType>(stubInfo->accessType)) {
- if (stubInfo->seen)
- repatchGetByID(exec, baseValue, ident, slot, *stubInfo);
- else
- stubInfo->seen = true;
- }
+ 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());
- return JSValue::encode(result);
}
-EncodedJSValue JIT_OPERATION operationInOptimize(ExecState* exec, StructureStubInfo* stubInfo, JSCell* base, StringImpl* key)
+EncodedJSValue JIT_OPERATION operationInOptimize(ExecState* exec, StructureStubInfo* stubInfo, JSCell* base, UniquedStringImpl* key)
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
if (!base->isObject()) {
- vm->throwException(exec, createInvalidParameterError(exec, "in", base));
+ vm->throwException(exec, createInvalidInParameterError(exec, base));
return JSValue::encode(jsUndefined());
}
AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
- Identifier ident(vm, key);
+ Identifier ident = Identifier::fromUid(vm, key);
PropertySlot slot(base);
bool result = asObject(base)->getPropertySlot(exec, ident, slot);
return JSValue::encode(jsBoolean(result));
}
-EncodedJSValue JIT_OPERATION operationIn(ExecState* exec, StructureStubInfo*, JSCell* base, StringImpl* key)
+EncodedJSValue JIT_OPERATION operationIn(ExecState* exec, StructureStubInfo* stubInfo, JSCell* base, UniquedStringImpl* key)
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
+
+ stubInfo->tookSlowPath = true;
if (!base->isObject()) {
- vm->throwException(exec, createInvalidParameterError(exec, "in", base));
+ vm->throwException(exec, createInvalidInParameterError(exec, base));
return JSValue::encode(jsUndefined());
}
- Identifier ident(vm, key);
+ Identifier ident = Identifier::fromUid(vm, key);
return JSValue::encode(jsBoolean(asObject(base)->hasProperty(exec, ident)));
}
return JSValue::encode(jsBoolean(CommonSlowPaths::opIn(exec, JSValue::decode(key), base)));
}
-void JIT_OPERATION operationPutByIdStrict(ExecState* exec, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
+void JIT_OPERATION operationPutByIdStrict(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
- Identifier ident(vm, uid);
+ stubInfo->tookSlowPath = true;
+
+ Identifier ident = Identifier::fromUid(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*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
+void JIT_OPERATION operationPutByIdNonStrict(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
- Identifier ident(vm, uid);
+ stubInfo->tookSlowPath = true;
+
+ Identifier ident = Identifier::fromUid(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*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
+void JIT_OPERATION operationPutByIdDirectStrict(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
- Identifier ident(vm, uid);
+ stubInfo->tookSlowPath = true;
+
+ Identifier ident = Identifier::fromUid(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*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
+void JIT_OPERATION operationPutByIdDirectNonStrict(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
- Identifier ident(vm, uid);
+ stubInfo->tookSlowPath = true;
+
+ Identifier ident = Identifier::fromUid(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, StringImpl* uid)
+void JIT_OPERATION operationPutByIdStrictOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
- Identifier ident(vm, uid);
+ Identifier ident = Identifier::fromUid(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, ident, slot, *stubInfo, NotDirect);
+ repatchPutByID(exec, baseValue, structure, ident, slot, *stubInfo, NotDirect);
else
stubInfo->seen = true;
}
-void JIT_OPERATION operationPutByIdNonStrictOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
+void JIT_OPERATION operationPutByIdNonStrictOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
- Identifier ident(vm, uid);
+ Identifier ident = Identifier::fromUid(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, ident, slot, *stubInfo, NotDirect);
+ repatchPutByID(exec, baseValue, structure, ident, slot, *stubInfo, NotDirect);
else
stubInfo->seen = true;
}
-void JIT_OPERATION operationPutByIdDirectStrictOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
+void JIT_OPERATION operationPutByIdDirectStrictOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
- Identifier ident(vm, uid);
+ Identifier ident = Identifier::fromUid(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, ident, slot, *stubInfo, Direct);
+ repatchPutByID(exec, baseObject, structure, ident, slot, *stubInfo, Direct);
else
stubInfo->seen = true;
}
-void JIT_OPERATION operationPutByIdDirectNonStrictOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
+void JIT_OPERATION operationPutByIdDirectNonStrictOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
- Identifier ident(vm, uid);
+ Identifier ident = Identifier::fromUid(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, ident, slot, *stubInfo, Direct);
+ repatchPutByID(exec, baseObject, structure, ident, slot, *stubInfo, Direct);
else
stubInfo->seen = true;
}
-void JIT_OPERATION operationPutByIdStrictBuildList(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
+void JIT_OPERATION operationPutByIdStrictBuildList(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
- Identifier ident(vm, uid);
+ Identifier ident = Identifier::fromUid(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, ident, slot, *stubInfo, NotDirect);
+
+ buildPutByIdList(exec, baseValue, structure, ident, slot, *stubInfo, NotDirect);
}
-void JIT_OPERATION operationPutByIdNonStrictBuildList(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
+void JIT_OPERATION operationPutByIdNonStrictBuildList(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
- Identifier ident(vm, uid);
+ Identifier ident = Identifier::fromUid(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, ident, slot, *stubInfo, NotDirect);
+ buildPutByIdList(exec, baseValue, structure, ident, slot, *stubInfo, NotDirect);
}
-void JIT_OPERATION operationPutByIdDirectStrictBuildList(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
+void JIT_OPERATION operationPutByIdDirectStrictBuildList(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
- Identifier ident(vm, uid);
+ Identifier ident = Identifier::fromUid(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());
-
- baseObject->putDirect(exec->vm(), ident, value, slot);
+
+ Structure* structure = baseObject->structure(*vm);
+ baseObject->putDirect(*vm, ident, value, slot);
if (accessType != static_cast<AccessType>(stubInfo->accessType))
return;
- buildPutByIdList(exec, baseObject, ident, slot, *stubInfo, Direct);
+ buildPutByIdList(exec, baseObject, structure, ident, slot, *stubInfo, Direct);
}
-void JIT_OPERATION operationPutByIdDirectNonStrictBuildList(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
+void JIT_OPERATION operationPutByIdDirectNonStrictBuildList(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
- Identifier ident(vm, uid);
+ Identifier ident = Identifier::fromUid(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());
-
- baseObject ->putDirect(exec->vm(), ident, value, slot);
-
+
+ Structure* structure = baseObject->structure(*vm);
+ baseObject->putDirect(*vm, ident, value, slot);
+
if (accessType != static_cast<AccessType>(stubInfo->accessType))
return;
- buildPutByIdList(exec, baseObject, ident, slot, *stubInfo, Direct);
+ buildPutByIdList(exec, baseObject, structure, ident, slot, *stubInfo, Direct);
}
void JIT_OPERATION operationReallocateStorageAndFinishPut(ExecState* exec, JSObject* base, Structure* structure, PropertyOffset offset, EncodedJSValue value)
base->putDirect(vm, offset, JSValue::decode(value));
}
-static void putByVal(CallFrame* callFrame, JSValue baseValue, JSValue subscript, JSValue value)
+static void putByVal(CallFrame* callFrame, JSValue baseValue, JSValue subscript, JSValue value, ArrayProfile* arrayProfile)
{
VM& vm = callFrame->vm();
if (LIKELY(subscript.isUInt32())) {
JSObject* object = asObject(baseValue);
if (object->canSetIndexQuickly(i))
object->setIndexQuickly(callFrame->vm(), i, value);
- else
+ else {
+ arrayProfile->setOutOfBounds();
object->methodTable(vm)->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 {
- Identifier property = subscript.toString(callFrame)->toIdentifier(callFrame);
+ auto property = subscript.toPropertyKey(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);
}
}
-static void directPutByVal(CallFrame* callFrame, JSObject* baseObject, JSValue subscript, JSValue value)
+static void directPutByVal(CallFrame* callFrame, JSObject* baseObject, JSValue subscript, JSValue value, ArrayProfile* arrayProfile)
{
+ bool isStrictMode = callFrame->codeBlock()->isStrictMode();
if (LIKELY(subscript.isUInt32())) {
- 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);
+ // 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;
+ }
+
+ 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;
}
}
+
+ // 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)
+void JIT_OPERATION operationPutByVal(ExecState* exec, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, ArrayProfile* arrayProfile)
{
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
ByValInfo& byValInfo = exec->codeBlock()->getByValInfo(bytecodeOffset - 1);
ASSERT(!byValInfo.stubRoutine);
- if (hasOptimizableIndexing(object->structure(vm))) {
+ Structure* structure = object->structure(vm);
+ if (hasOptimizableIndexing(structure)) {
// Attempt to optimize.
- JITArrayMode arrayMode = jitArrayModeForStructure(object->structure(vm));
- if (arrayMode != byValInfo.arrayMode) {
+ JITArrayMode arrayMode = jitArrayModeForStructure(structure);
+ if (jitArrayModePermitsPut(arrayMode) && arrayMode != byValInfo.arrayMode) {
+ CodeBlock* codeBlock = exec->codeBlock();
+ ConcurrentJITLocker locker(codeBlock->m_lock);
+ arrayProfile->computeUpdatedPrediction(locker, codeBlock, structure);
+
JIT::compilePutByVal(&vm, exec->codeBlock(), &byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode);
didOptimize = true;
}
if (++byValInfo.slowPathCount >= 10
|| object->structure(vm)->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) {
// Don't ever try to optimize.
- RepatchBuffer repatchBuffer(exec->codeBlock());
- repatchBuffer.relinkCallerToFunction(ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationPutByValGeneric));
+ ctiPatchCallByReturnAddress(exec->codeBlock(), ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationPutByValGeneric));
}
}
}
- putByVal(exec, baseValue, subscript, value);
+ putByVal(exec, baseValue, subscript, value, arrayProfile);
}
-void JIT_OPERATION operationDirectPutByVal(ExecState* callFrame, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue)
+void JIT_OPERATION operationDirectPutByVal(ExecState* callFrame, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, ArrayProfile* arrayProfile)
{
VM& vm = callFrame->vm();
NativeCallFrameTracer tracer(&vm, callFrame);
ASSERT(bytecodeOffset);
ByValInfo& byValInfo = callFrame->codeBlock()->getByValInfo(bytecodeOffset - 1);
ASSERT(!byValInfo.stubRoutine);
-
- if (hasOptimizableIndexing(object->structure(vm))) {
+
+ Structure* structure = object->structure(vm);
+ if (hasOptimizableIndexing(structure)) {
// Attempt to optimize.
- JITArrayMode arrayMode = jitArrayModeForStructure(object->structure(vm));
- if (arrayMode != byValInfo.arrayMode) {
+ JITArrayMode arrayMode = jitArrayModeForStructure(structure);
+ if (jitArrayModePermitsPut(arrayMode) && arrayMode != byValInfo.arrayMode) {
+ CodeBlock* codeBlock = callFrame->codeBlock();
+ ConcurrentJITLocker locker(codeBlock->m_lock);
+ arrayProfile->computeUpdatedPrediction(locker, codeBlock, structure);
+
JIT::compileDirectPutByVal(&vm, callFrame->codeBlock(), &byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode);
didOptimize = true;
}
if (++byValInfo.slowPathCount >= 10
|| object->structure(vm)->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) {
// Don't ever try to optimize.
- RepatchBuffer repatchBuffer(callFrame->codeBlock());
- repatchBuffer.relinkCallerToFunction(ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationDirectPutByValGeneric));
+ ctiPatchCallByReturnAddress(callFrame->codeBlock(), ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationDirectPutByValGeneric));
}
}
}
- directPutByVal(callFrame, object, subscript, value);
+ directPutByVal(callFrame, object, subscript, value, arrayProfile);
}
-void JIT_OPERATION operationPutByValGeneric(ExecState* exec, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue)
+void JIT_OPERATION operationPutByValGeneric(ExecState* exec, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, ArrayProfile* arrayProfile)
{
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
JSValue subscript = JSValue::decode(encodedSubscript);
JSValue value = JSValue::decode(encodedValue);
- putByVal(exec, baseValue, subscript, value);
+ putByVal(exec, baseValue, subscript, value, arrayProfile);
}
-void JIT_OPERATION operationDirectPutByValGeneric(ExecState* exec, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue)
+void JIT_OPERATION operationDirectPutByValGeneric(ExecState* exec, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, ArrayProfile* arrayProfile)
{
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
JSValue subscript = JSValue::decode(encodedSubscript);
JSValue value = JSValue::decode(encodedValue);
RELEASE_ASSERT(baseValue.isObject());
- directPutByVal(exec, asObject(baseValue), subscript, value);
+ directPutByVal(exec, asObject(baseValue), subscript, value, arrayProfile);
}
EncodedJSValue JIT_OPERATION operationCallEval(ExecState* exec, ExecState* execCallee)
{
- ASSERT(exec->codeBlock()->codeType() != FunctionCode
+
+ ASSERT_UNUSED(exec, exec->codeBlock()->codeType() != FunctionCode
|| !exec->codeBlock()->needsActivation()
|| exec->hasActivation());
- execCallee->setScope(exec->scope());
execCallee->setCodeBlock(0);
if (!isHostFunction(execCallee->calleeAsValue(), globalFuncEval))
ExecState* exec = execCallee->callerFrame();
VM* vm = &exec->vm();
- execCallee->setScope(exec->scope());
execCallee->setCodeBlock(0);
if (kind == CodeForCall) {
JSValue calleeAsValue = execCallee->calleeAsValue();
JSCell* calleeAsFunctionCell = getJSFunction(calleeAsValue);
- if (!calleeAsFunctionCell)
+ 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
return reinterpret_cast<char*>(handleHostCall(execCallee, calleeAsValue, kind));
+ }
JSFunction* callee = jsCast<JSFunction*>(calleeAsFunctionCell);
JSScope* scope = callee->scopeUnchecked();
- execCallee->setScope(scope);
ExecutableBase* executable = callee->executable();
MacroAssemblerCodePtr codePtr;
codePtr = executable->entrypointFor(*vm, kind, MustCheckArity, registers);
else {
FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
- JSObject* error = functionExecutable->prepareForExecution(execCallee, callee, &scope, kind);
- execCallee->setScope(scope);
+
+ if (!isCall(kind) && functionExecutable->isBuiltinFunction()) {
+ exec->vm().throwException(exec, createNotAConstructorError(exec, callee));
+ return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
+ }
+
+ JSObject* error = functionExecutable->prepareForExecution(execCallee, callee, scope, kind);
if (error) {
- throwStackOverflowError(exec);
+ exec->vm().throwException(exec, error);
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)
+ if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()) || callLinkInfo->callType() == CallLinkInfo::CallVarargs || callLinkInfo->callType() == CallLinkInfo::ConstructVarargs)
arity = MustCheckArity;
else
arity = ArityCheckNotRequired;
callLinkInfo->setSeen();
else
linkFor(execCallee, *callLinkInfo, codeBlock, callee, codePtr, kind, registers);
+
return reinterpret_cast<char*>(codePtr.executableAddress());
}
JSFunction* function = jsCast<JSFunction*>(calleeAsFunctionCell);
JSScope* scope = function->scopeUnchecked();
- execCallee->setScope(scope);
ExecutableBase* executable = function->executable();
if (UNLIKELY(!executable->hasJITCodeFor(kind))) {
FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
- JSObject* error = functionExecutable->prepareForExecution(execCallee, function, &scope, kind);
- execCallee->setScope(scope);
+
+ if (!isCall(kind) && functionExecutable->isBuiltinFunction()) {
+ exec->vm().throwException(exec, createNotAConstructorError(exec, function));
+ return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
+ }
+
+ JSObject* error = functionExecutable->prepareForExecution(execCallee, function, scope, kind);
if (error) {
exec->vm().throwException(exec, error);
return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
return virtualForWithFunction(execCallee, kind, registers, calleeAsFunctionCellIgnored);
}
-static bool attemptToOptimizeClosureCall(
- ExecState* execCallee, RegisterPreservationMode registers, JSCell* calleeAsFunctionCell,
- CallLinkInfo& callLinkInfo)
-{
- if (!calleeAsFunctionCell)
- return false;
-
- VM& vm = execCallee->vm();
- JSFunction* callee = jsCast<JSFunction*>(calleeAsFunctionCell);
- JSFunction* oldCallee = callLinkInfo.callee.get();
-
- if (!oldCallee
- || oldCallee->structure(vm) != callee->structure(vm)
- || oldCallee->executable() != callee->executable())
- return false;
-
- ASSERT(callee->executable()->hasJITCodeForCall());
- MacroAssemblerCodePtr codePtr =
- callee->executable()->generatedJITCodeForCall()->addressForCall(
- *execCallee->callerFrame()->codeBlock()->vm(), callee->executable(),
- ArityCheckNotRequired, registers);
-
- CodeBlock* codeBlock;
- if (callee->executable()->isHostFunction())
- codeBlock = 0;
- else {
- codeBlock = jsCast<FunctionExecutable*>(callee->executable())->codeBlockForCall();
- if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()) || callLinkInfo.callType == CallLinkInfo::CallVarargs || callLinkInfo.callType == CallLinkInfo::ConstructVarargs)
- return false;
- }
-
- linkClosureCall(
- execCallee, callLinkInfo, codeBlock,
- callee->structure(), callee->executable(), codePtr, registers);
-
- return true;
-}
-
-char* JIT_OPERATION operationLinkClosureCall(ExecState* execCallee, CallLinkInfo* callLinkInfo)
+char* JIT_OPERATION operationLinkPolymorphicCall(ExecState* execCallee, CallLinkInfo* callLinkInfo)
{
JSCell* calleeAsFunctionCell;
char* result = virtualForWithFunction(execCallee, CodeForCall, RegisterPreservationNotRequired, calleeAsFunctionCell);
- if (!attemptToOptimizeClosureCall(execCallee, RegisterPreservationNotRequired, calleeAsFunctionCell, *callLinkInfo))
- linkSlowFor(execCallee, *callLinkInfo, CodeForCall, RegisterPreservationNotRequired);
+ linkPolymorphicCall(execCallee, *callLinkInfo, CallVariant(calleeAsFunctionCell), RegisterPreservationNotRequired);
return result;
}
return virtualFor(execCallee, CodeForConstruct, RegisterPreservationNotRequired);
}
-char* JIT_OPERATION operationLinkClosureCallThatPreservesRegs(ExecState* execCallee, CallLinkInfo* callLinkInfo)
+char* JIT_OPERATION operationLinkPolymorphicCallThatPreservesRegs(ExecState* execCallee, CallLinkInfo* callLinkInfo)
{
JSCell* calleeAsFunctionCell;
char* result = virtualForWithFunction(execCallee, CodeForCall, MustPreserveRegisters, calleeAsFunctionCell);
- if (!attemptToOptimizeClosureCall(execCallee, MustPreserveRegisters, calleeAsFunctionCell, *callLinkInfo))
- linkSlowFor(execCallee, *callLinkInfo, CodeForCall, MustPreserveRegisters);
+ linkPolymorphicCall(execCallee, *callLinkInfo, CallVariant(calleeAsFunctionCell), MustPreserveRegisters);
return result;
}
size_t JIT_OPERATION operationHasProperty(ExecState* exec, JSObject* base, JSString* property)
{
- int result = base->hasProperty(exec, Identifier(exec, property->value(exec)));
+ int result = base->hasProperty(exec, property->toIdentifier(exec));
return result;
}
return JSValue::encode(constructArrayWithSizeQuirk(exec, profile, exec->lexicalGlobalObject(), sizeValue));
}
-EncodedJSValue JIT_OPERATION operationNewFunction(ExecState* exec, JSCell* functionExecutable)
+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), exec->scope()));
+ return JSValue::encode(JSFunction::create(vm, static_cast<FunctionExecutable*>(functionExecutable), scope));
+}
+
+EncodedJSValue JIT_OPERATION operationNewFunctionWithInvalidatedReallocationWatchpoint(ExecState* exec, JSScope* scope, 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));
}
JSCell* JIT_OPERATION operationNewObject(ExecState* exec, Structure* structure)
NativeCallFrameTracer tracer(&vm, exec);
RegExp* regexp = static_cast<RegExp*>(regexpPtr);
if (!regexp->isValid()) {
- vm.throwException(exec, createSyntaxError(exec, "Invalid flags supplied to RegExp constructor."));
+ vm.throwException(exec, createSyntaxError(exec, ASCIILiteral("Invalid flags supplied to RegExp constructor.")));
return JSValue::encode(jsUndefined());
}
{
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
-
- String message = errorDescriptionForValue(exec, JSValue::decode(encodedValue))->value(exec);
+ JSValue errorMessageValue = JSValue::decode(encodedValue);
+ RELEASE_ASSERT(errorMessageValue.isString());
+ String errorMessage = asString(errorMessageValue)->value(exec);
if (referenceErrorFlag)
- vm.throwException(exec, createReferenceError(exec, message));
+ vm.throwException(exec, createReferenceError(exec, errorMessage));
else
- vm.throwException(exec, createTypeError(exec, message));
+ vm.throwException(exec, createTypeError(exec, errorMessage));
}
void JIT_OPERATION operationDebug(ExecState* exec, int32_t debugHookID)
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
Operands<JSValue> mustHandleValues(codeBlock->numParameters(), numVarsWithValues);
for (size_t i = 0; i < mustHandleValues.size(); ++i) {
int operand = mustHandleValues.operandForIndex(i);
- 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();
+ mustHandleValues[i] = exec->uncheckedR(operand).jsValue();
}
RefPtr<CodeBlock> replacementCodeBlock = codeBlock->newReplacement();
}
#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();
ASSERT(JSValue::decode(encodedObjectValue).isObject());
JSObject* baseObj = asObject(JSValue::decode(encodedObjectValue));
- GetterSetter* accessor = GetterSetter::create(vm);
+ GetterSetter* accessor = GetterSetter::create(vm, exec->lexicalGlobalObject());
JSValue getter = JSValue::decode(encodedGetterValue);
JSValue setter = JSValue::decode(encodedSetterValue);
ASSERT(getter.isObject() || setter.isObject());
if (!getter.isUndefined())
- accessor->setGetter(vm, asObject(getter));
+ accessor->setGetter(vm, exec->lexicalGlobalObject(), asObject(getter));
if (!setter.isUndefined())
- accessor->setSetter(vm, asObject(setter));
+ accessor->setSetter(vm, exec->lexicalGlobalObject(), asObject(setter));
baseObj->putDirectAccessor(exec, *identifier, accessor, Accessor);
}
#else
+void JIT_OPERATION operationPutGetterById(ExecState* exec, JSCell* object, Identifier* identifier, JSCell* getter)
+{
+ VM& vm = exec->vm();
+ NativeCallFrameTracer tracer(&vm, exec);
+
+ ASSERT(object && object->isObject());
+ JSObject* baseObj = object->getObject();
+
+ ASSERT(getter->isObject());
+ baseObj->putGetter(exec, *identifier, getter);
+}
+
+void JIT_OPERATION operationPutSetterById(ExecState* exec, JSCell* object, Identifier* identifier, JSCell* setter)
+{
+ VM& vm = exec->vm();
+ NativeCallFrameTracer tracer(&vm, exec);
+
+ ASSERT(object && object->isObject());
+ JSObject* baseObj = object->getObject();
+
+ ASSERT(setter->isObject());
+ baseObj->putSetter(exec, *identifier, setter);
+}
+
void JIT_OPERATION operationPutGetterSetter(ExecState* exec, JSCell* object, Identifier* identifier, JSCell* getter, JSCell* setter)
{
VM& vm = exec->vm();
ASSERT(object && object->isObject());
JSObject* baseObj = object->getObject();
- GetterSetter* accessor = GetterSetter::create(vm);
+ GetterSetter* accessor = GetterSetter::create(vm, exec->lexicalGlobalObject());
ASSERT(!getter || getter->isObject());
ASSERT(!setter || setter->isObject());
ASSERT(getter || setter);
if (getter)
- accessor->setGetter(vm, getter->getObject());
+ accessor->setGetter(vm, exec->lexicalGlobalObject(), getter->getObject());
if (setter)
- accessor->setSetter(vm, setter->getObject());
+ accessor->setSetter(vm, exec->lexicalGlobalObject(), setter->getObject());
baseObj->putDirectAccessor(exec, *identifier, accessor, Accessor);
}
#endif
-void JIT_OPERATION operationPushNameScope(ExecState* exec, Identifier* identifier, EncodedJSValue encodedValue, int32_t attibutes)
+void JIT_OPERATION operationPushCatchScope(ExecState* exec, int32_t dst, SymbolTable* symbolTable, EncodedJSValue encodedValue)
{
- VM& vm = exec->vm();
- NativeCallFrameTracer tracer(&vm, exec);
-
- JSNameScope* scope = JSNameScope::create(exec, *identifier, JSValue::decode(encodedValue), attibutes);
+ pushNameScope<JSCatchScope>(exec, dst, symbolTable, encodedValue);
+}
- exec->setScope(scope);
+void JIT_OPERATION operationPushFunctionNameScope(ExecState* exec, int32_t dst, SymbolTable* symbolTable, EncodedJSValue encodedValue)
+{
+ pushNameScope<JSFunctionNameScope>(exec, dst, symbolTable, encodedValue);
}
-void JIT_OPERATION operationPushWithScope(ExecState* exec, EncodedJSValue encodedValue)
+void JIT_OPERATION operationPushWithScope(ExecState* exec, int32_t dst, EncodedJSValue encodedValue)
{
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
if (vm.exception())
return;
- exec->setScope(JSWithScope::create(exec, o));
+ // FIXME: This won't work if this operation is called from the DFG or FTL.
+ // This should be changed to pass in the old scope and return the new scope.
+ JSScope* currentScope = exec->uncheckedR(dst).Register::scope();
+ exec->uncheckedR(dst) = JSWithScope::create(exec, o, currentScope);
}
-void JIT_OPERATION operationPopScope(ExecState* exec)
+void JIT_OPERATION operationPopScope(ExecState* exec, int32_t scopeReg)
{
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
- exec->setScope(exec->scope()->next());
+ JSScope* scope = exec->uncheckedR(scopeReg).Register::scope();
+ exec->uncheckedR(scopeReg) = scope->next();
}
void JIT_OPERATION operationProfileDidCall(ExecState* exec, EncodedJSValue encodedValue)
}
}
- vm.throwException(exec, createInvalidParameterError(exec, "instanceof", baseVal));
+ vm.throwException(exec, createInvalidInstanceofParameterError(exec, 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;
-}
-
-JSCell* JIT_OPERATION operationCreateArguments(ExecState* exec)
+JSCell* JIT_OPERATION operationCreateActivation(ExecState* exec, JSScope* currentScope)
{
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;
+ JSLexicalEnvironment* lexicalEnvironment = JSLexicalEnvironment::create(vm, exec, currentScope, exec->codeBlock());
+ return lexicalEnvironment;
}
-JSCell* JIT_OPERATION operationCreateArgumentsDuringOSRExit(ExecState* exec)
-{
- DeferGCForAWhile(exec->vm().heap);
- return operationCreateArguments(exec);
}
-EncodedJSValue JIT_OPERATION operationGetArgumentsLength(ExecState* exec, int32_t argumentsRegister)
+static bool canAccessArgumentIndexQuickly(JSObject& object, uint32_t index)
{
- 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));
-}
-
+ 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;
}
-static JSValue getByVal(ExecState* exec, JSValue baseValue, JSValue subscript, ReturnAddressPtr returnAddress)
+static JSValue getByVal(ExecState* exec, JSValue baseValue, JSValue subscript, ArrayProfile* arrayProfile, ReturnAddressPtr returnAddress)
{
if (LIKELY(baseValue.isCell() && subscript.isString())) {
VM& vm = exec->vm();
Structure& structure = *baseValue.asCell()->structure(vm);
if (JSCell::canUseFastGetOwnProperty(structure)) {
- if (JSValue result = baseValue.asCell()->fastGetOwnProperty(vm, structure, asString(subscript)->value(exec)))
- return result;
+ if (RefPtr<AtomicStringImpl> existingAtomicString = asString(subscript)->toExistingAtomicString(exec)) {
+ if (JSValue result = baseValue.asCell()->fastGetOwnProperty(vm, structure, existingAtomicString.get()))
+ return result;
+ }
}
}
if (subscript.isUInt32()) {
uint32_t i = subscript.asUInt32();
- if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i)) {
- ctiPatchCallByReturnAddress(exec->codeBlock(), returnAddress, FunctionPtr(operationGetByValString));
- return asString(baseValue)->getIndex(exec, i);
+ if (isJSString(baseValue)) {
+ if (asString(baseValue)->canGetIndex(i)) {
+ ctiPatchCallByReturnAddress(exec->codeBlock(), returnAddress, FunctionPtr(operationGetByValString));
+ return asString(baseValue)->getIndex(exec, i);
+ }
+ arrayProfile->setOutOfBounds();
+ } else if (baseValue.isObject()) {
+ JSObject* object = asObject(baseValue);
+ if (object->canGetIndexQuickly(i))
+ return object->getIndexQuickly(i);
+
+ if (!canAccessArgumentIndexQuickly(*object, i))
+ arrayProfile->setOutOfBounds();
}
+
return baseValue.get(exec, i);
}
- if (isName(subscript))
- return baseValue.get(exec, jsCast<NameInstance*>(subscript.asCell())->privateName());
-
- Identifier property = subscript.toString(exec)->toIdentifier(exec);
+ baseValue.requireObjectCoercible(exec);
+ if (exec->hadException())
+ return jsUndefined();
+ auto property = subscript.toPropertyKey(exec);
+ if (exec->hadException())
+ return jsUndefined();
return baseValue.get(exec, property);
}
extern "C" {
-EncodedJSValue JIT_OPERATION operationGetByValGeneric(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript)
+EncodedJSValue JIT_OPERATION operationGetByValGeneric(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ArrayProfile* arrayProfile)
{
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
JSValue baseValue = JSValue::decode(encodedBase);
JSValue subscript = JSValue::decode(encodedSubscript);
- JSValue result = getByVal(exec, baseValue, subscript, ReturnAddressPtr(OUR_RETURN_ADDRESS));
+ JSValue result = getByVal(exec, baseValue, subscript, arrayProfile, ReturnAddressPtr(OUR_RETURN_ADDRESS));
return JSValue::encode(result);
}
-EncodedJSValue JIT_OPERATION operationGetByValDefault(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript)
+EncodedJSValue JIT_OPERATION operationGetByValDefault(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ArrayProfile* arrayProfile)
{
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
if (hasOptimizableIndexing(object->structure(vm))) {
// Attempt to optimize.
- JITArrayMode arrayMode = jitArrayModeForStructure(object->structure(vm));
+ 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);
+ arrayProfile->computeUpdatedPrediction(locker, codeBlock, structure);
+
JIT::compileGetByVal(&vm, exec->codeBlock(), &byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode);
didOptimize = true;
}
if (++byValInfo.slowPathCount >= 10
|| object->structure(vm)->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) {
// Don't ever try to optimize.
- RepatchBuffer repatchBuffer(exec->codeBlock());
- repatchBuffer.relinkCallerToFunction(ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationGetByValGeneric));
+ ctiPatchCallByReturnAddress(exec->codeBlock(), ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationGetByValGeneric));
}
}
}
- JSValue result = getByVal(exec, baseValue, subscript, ReturnAddressPtr(OUR_RETURN_ADDRESS));
+ JSValue result = getByVal(exec, baseValue, subscript, arrayProfile, ReturnAddressPtr(OUR_RETURN_ADDRESS));
return JSValue::encode(result);
}
+EncodedJSValue JIT_OPERATION operationHasIndexedPropertyDefault(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ArrayProfile* arrayProfile)
+{
+ 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;
+
+ unsigned bytecodeOffset = exec->locationAsBytecodeOffset();
+ ASSERT(bytecodeOffset);
+ ByValInfo& byValInfo = exec->codeBlock()->getByValInfo(bytecodeOffset - 1);
+ 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))
+ arrayProfile->setOutOfBounds();
+ return JSValue::encode(jsBoolean(object->hasProperty(exec, index)));
+}
+
+EncodedJSValue JIT_OPERATION operationHasIndexedPropertyGeneric(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ArrayProfile* arrayProfile)
+{
+ 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))
+ arrayProfile->setOutOfBounds();
+ return JSValue::encode(jsBoolean(object->hasProperty(exec, subscript.asUInt32())));
+}
+
EncodedJSValue JIT_OPERATION operationGetByValString(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript)
{
VM& vm = exec->vm();
if (!isJSString(baseValue))
ctiPatchCallByReturnAddress(exec->codeBlock(), ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationGetByValDefault));
}
- } else if (isName(subscript))
- result = baseValue.get(exec, jsCast<NameInstance*>(subscript.asCell())->privateName());
- else {
- Identifier property = subscript.toString(exec)->toIdentifier(exec);
+ } else {
+ baseValue.requireObjectCoercible(exec);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
+ auto property = subscript.toPropertyKey(exec);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
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()->needsActivation());
- 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)
{
bool couldDelete = baseObj->methodTable(vm)->deleteProperty(baseObj, exec, *identifier);
JSValue result = jsBoolean(couldDelete);
if (!couldDelete && exec->codeBlock()->isStrictMode())
- vm.throwException(exec, createTypeError(exec, "Unable to delete property."));
+ vm.throwException(exec, createTypeError(exec, ASCIILiteral("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(vm);
- 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();
return JSValue::encode(jsBoolean(result));
}
-CallFrame* JIT_OPERATION operationSizeFrameForVarargs(ExecState* exec, EncodedJSValue encodedArguments, int32_t firstFreeRegister, int32_t firstVarArgOffset)
+int32_t JIT_OPERATION operationSizeFrameForVarargs(ExecState* exec, EncodedJSValue encodedArguments, int32_t numUsedStackSlots, int32_t firstVarArgOffset)
{
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
JSStack* stack = &exec->interpreter()->stack();
JSValue arguments = JSValue::decode(encodedArguments);
- CallFrame* newCallFrame = sizeFrameForVarargs(exec, stack, arguments, firstFreeRegister, firstVarArgOffset);
- return newCallFrame;
+ return sizeFrameForVarargs(exec, stack, arguments, numUsedStackSlots, firstVarArgOffset);
}
-CallFrame* JIT_OPERATION operationLoadVarargs(ExecState* exec, CallFrame* newCallFrame, EncodedJSValue encodedThis, EncodedJSValue encodedArguments, int32_t firstVarArgOffset)
+CallFrame* JIT_OPERATION operationSetupVarargsFrame(ExecState* exec, CallFrame* newCallFrame, EncodedJSValue encodedArguments, int32_t firstVarArgOffset, int32_t length)
{
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
- JSValue thisValue = JSValue::decode(encodedThis);
JSValue arguments = JSValue::decode(encodedArguments);
- loadVarargs(exec, newCallFrame, thisValue, arguments, firstVarArgOffset);
+ setupVarargsFrame(exec, newCallFrame, arguments, firstVarArgOffset, length);
return newCallFrame;
}
return reinterpret_cast<char*>(result);
}
-EncodedJSValue JIT_OPERATION operationResolveScope(ExecState* exec, int32_t identifierIndex)
+EncodedJSValue JIT_OPERATION operationResolveScope(ExecState* exec, int32_t scopeReg, int32_t identifierIndex)
{
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
const Identifier& ident = exec->codeBlock()->identifier(identifierIndex);
- return JSValue::encode(JSScope::resolve(exec, exec->scope(), ident));
+ JSScope* scope = exec->uncheckedR(scopeReg).Register::scope();
+ return JSValue::encode(JSScope::resolve(exec, scope, ident));
}
EncodedJSValue JIT_OPERATION operationGetFromScope(ExecState* exec, Instruction* bytecodePC)
// 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 (modeAndType.type() == GlobalProperty || modeAndType.type() == GlobalPropertyWithVarInjectionChecks) {
- ConcurrentJITLocker locker(codeBlock->m_lock);
- pc[5].u.structure.set(exec->vm(), codeBlock->ownerExecutable(), scope->structure(vm));
- pc[6].u.operand = slot.cachedOffset();
+ 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());
}
}
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;
if (exec->vm().exception())
return;
- // 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.isCacheablePut() && 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();
- }
- }
+ CommonSlowPaths::tryCachePutToScopeGlobal(exec, codeBlock, pc, scope, modeAndType, slot);
}
void JIT_OPERATION operationThrow(ExecState* exec, EncodedJSValue encodedExceptionValue)
JSValue exceptionValue = JSValue::decode(encodedExceptionValue);
vm->throwException(exec, exceptionValue);
- // Results stored out-of-band in vm.targetMachinePCForThrow & vm.callFrameForThrow
- genericUnwind(vm, exec, exceptionValue);
+ // Results stored out-of-band in vm.targetMachinePCForThrow, vm.callFrameForThrow & vm.vmEntryFrameForThrow
+ genericUnwind(vm, exec);
}
void JIT_OPERATION operationFlushWriteBarrierBuffer(ExecState* exec, JSCell* cell)
NativeCallFrameTracer tracer(vm, exec);
JSValue value = exec->r(pc[2].u.operand).jsValue();
- pc[1].u.registerPointer->set(*vm, exec->codeBlock()->globalObject(), value);
+ pc[1].u.variablePointer->set(*vm, exec->codeBlock()->globalObject(), value);
}
void JIT_OPERATION lookupExceptionHandler(VM* vm, ExecState* exec)
{
- NativeCallFrameTracer tracer(vm, exec, NativeCallFrameTracer::VMEntrySentinelOK);
+ NativeCallFrameTracer tracer(vm, exec);
+ genericUnwind(vm, exec);
+ ASSERT(vm->targetMachinePCForThrow);
+}
- JSValue exceptionValue = vm->exception();
- ASSERT(exceptionValue);
-
- genericUnwind(vm, exec, exceptionValue);
+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);
ASSERT(vm->targetMachinePCForThrow);
}
{
VM* vm = &exec->vm();
NativeCallFrameTracer tracer(vm, exec);
-
- ASSERT(!exec->isVMEntrySentinel());
- genericUnwind(vm, exec, vm->exception());
+ genericUnwind(vm, exec);
}
// This function "should" just take the ExecState*, but doing so would make it more difficult
// testing.
void JIT_OPERATION operationExceptionFuzz()
{
- ASSERT(Options::enableExceptionFuzz());
-
// This probably "just works" for GCC also, but I haven't tried.
#if COMPILER(CLANG)
ExecState* exec = static_cast<ExecState*>(__builtin_frame_address(1));
- DeferGCForAWhile deferGC(exec->vm().heap);
-
- s_numberOfExceptionFuzzChecks++;
-
- unsigned fireTarget = Options::fireExceptionFuzzAt();
- if (fireTarget == s_numberOfExceptionFuzzChecks) {
- printf("JSC EXCEPTION FUZZ: Throwing fuzz exception with call frame %p and return address %p.\n", exec, __builtin_return_address(0));
- exec->vm().throwException(
- exec, createError(exec->lexicalGlobalObject(), ASCIILiteral("Exception Fuzz")));
- }
+ void* returnPC = __builtin_return_address(0);
+ doExceptionFuzzing(exec, "JITOperations", returnPC);
#endif // COMPILER(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"));
+}
+
} // extern "C"
// Note: getHostCallReturnValueWithExecState() needs to be placed before the