summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/runtime/Operations.h
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/JavaScriptCore/runtime/Operations.h
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/JavaScriptCore/runtime/Operations.h')
-rw-r--r--Source/JavaScriptCore/runtime/Operations.h200
1 files changed, 94 insertions, 106 deletions
diff --git a/Source/JavaScriptCore/runtime/Operations.h b/Source/JavaScriptCore/runtime/Operations.h
index cee00ebf4..29bacfa17 100644
--- a/Source/JavaScriptCore/runtime/Operations.h
+++ b/Source/JavaScriptCore/runtime/Operations.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2002, 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2002, 2005-2009, 2013-2014, 2016 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -19,31 +19,27 @@
*
*/
-#ifndef Operations_h
-#define Operations_h
+#pragma once
+#include "CallFrame.h"
#include "ExceptionHelpers.h"
-#include "GCIncomingRefCountedInlines.h"
-#include "Interpreter.h"
-#include "JSArrayBufferViewInlines.h"
-#include "JSCJSValueInlines.h"
-#include "JSFunctionInlines.h"
-#include "JSProxy.h"
-#include "JSString.h"
-#include "SlotVisitorInlines.h"
-#include "StructureInlines.h"
+#include "JSCJSValue.h"
namespace JSC {
+#define InvalidPrototypeChain (std::numeric_limits<size_t>::max())
+
NEVER_INLINE JSValue jsAddSlowCase(CallFrame*, JSValue, JSValue);
JSValue jsTypeStringForValue(CallFrame*, JSValue);
JSValue jsTypeStringForValue(VM&, JSGlobalObject*, JSValue);
-bool jsIsObjectType(CallFrame*, JSValue);
+bool jsIsObjectTypeOrNull(CallFrame*, JSValue);
bool jsIsFunctionType(JSValue);
+size_t normalizePrototypeChain(CallFrame*, Structure*);
-ALWAYS_INLINE JSValue jsString(ExecState* exec, JSString* s1, JSString* s2)
+ALWAYS_INLINE JSString* jsString(ExecState* exec, JSString* s1, JSString* s2)
{
VM& vm = exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
int32_t length1 = s1->length();
if (!length1)
@@ -51,45 +47,89 @@ ALWAYS_INLINE JSValue jsString(ExecState* exec, JSString* s1, JSString* s2)
int32_t length2 = s2->length();
if (!length2)
return s1;
- if (sumOverflows<int32_t>(length1, length2))
- return throwOutOfMemoryError(exec);
+ if (sumOverflows<int32_t>(length1, length2)) {
+ throwOutOfMemoryError(exec, scope);
+ return nullptr;
+ }
return JSRopeString::create(vm, s1, s2);
}
-ALWAYS_INLINE JSValue jsString(ExecState* exec, const String& u1, const String& u2, const String& u3)
+ALWAYS_INLINE JSString* jsString(ExecState* exec, JSString* s1, JSString* s2, JSString* s3)
+{
+ VM& vm = exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ int32_t length1 = s1->length();
+ if (!length1) {
+ scope.release();
+ return jsString(exec, s2, s3);
+ }
+ int32_t length2 = s2->length();
+ if (!length2) {
+ scope.release();
+ return jsString(exec, s1, s3);
+ }
+ int32_t length3 = s3->length();
+ if (!length3) {
+ scope.release();
+ return jsString(exec, s1, s2);
+ }
+
+ if (sumOverflows<int32_t>(length1, length2, length3)) {
+ throwOutOfMemoryError(exec, scope);
+ return nullptr;
+ }
+ return JSRopeString::create(vm, s1, s2, s3);
+}
+
+ALWAYS_INLINE JSString* jsString(ExecState* exec, const String& u1, const String& u2, const String& u3)
{
VM* vm = &exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(*vm);
int32_t length1 = u1.length();
int32_t length2 = u2.length();
int32_t length3 = u3.length();
- if (length1 < 0 || length2 < 0 || length3 < 0)
- return throwOutOfMemoryError(exec);
+ if (length1 < 0 || length2 < 0 || length3 < 0) {
+ throwOutOfMemoryError(exec, scope);
+ return nullptr;
+ }
- if (!length1)
+ if (!length1) {
+ scope.release();
return jsString(exec, jsString(vm, u2), jsString(vm, u3));
- if (!length2)
+ }
+ if (!length2) {
+ scope.release();
return jsString(exec, jsString(vm, u1), jsString(vm, u3));
- if (!length3)
+ }
+ if (!length3) {
+ scope.release();
return jsString(exec, jsString(vm, u1), jsString(vm, u2));
+ }
- if (sumOverflows<int32_t>(length1, length2, length3))
- return throwOutOfMemoryError(exec);
+ if (sumOverflows<int32_t>(length1, length2, length3)) {
+ throwOutOfMemoryError(exec, scope);
+ return nullptr;
+ }
- return JSRopeString::create(exec->vm(), jsString(vm, u1), jsString(vm, u2), jsString(vm, u3));
+ return JSRopeString::create(*vm, jsString(vm, u1), jsString(vm, u2), jsString(vm, u3));
}
ALWAYS_INLINE JSValue jsStringFromRegisterArray(ExecState* exec, Register* strings, unsigned count)
{
VM* vm = &exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(*vm);
JSRopeString::RopeBuilder ropeBuilder(*vm);
for (unsigned i = 0; i < count; ++i) {
JSValue v = strings[-static_cast<int>(i)].jsValue();
- if (!ropeBuilder.append(v.toString(exec)))
- return throwOutOfMemoryError(exec);
+ JSString* string = v.toString(exec);
+ RETURN_IF_EXCEPTION(scope, { });
+ if (!ropeBuilder.append(string))
+ return throwOutOfMemoryError(exec, scope);
}
return ropeBuilder.release();
@@ -98,13 +138,18 @@ ALWAYS_INLINE JSValue jsStringFromRegisterArray(ExecState* exec, Register* strin
ALWAYS_INLINE JSValue jsStringFromArguments(ExecState* exec, JSValue thisValue)
{
VM* vm = &exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(*vm);
JSRopeString::RopeBuilder ropeBuilder(*vm);
- ropeBuilder.append(thisValue.toString(exec));
+ JSString* str = thisValue.toString(exec);
+ RETURN_IF_EXCEPTION(scope, { });
+ ropeBuilder.append(str);
for (unsigned i = 0; i < exec->argumentCount(); ++i) {
JSValue v = exec->argument(i);
- if (!ropeBuilder.append(v.toString(exec)))
- return throwOutOfMemoryError(exec);
+ JSString* str = v.toString(exec);
+ RETURN_IF_EXCEPTION(scope, { });
+ if (UNLIKELY(!ropeBuilder.append(str)))
+ return throwOutOfMemoryError(exec, scope);
}
return ropeBuilder.release();
@@ -116,6 +161,9 @@ ALWAYS_INLINE JSValue jsStringFromArguments(ExecState* exec, JSValue thisValue)
template<bool leftFirst>
ALWAYS_INLINE bool jsLess(CallFrame* callFrame, JSValue v1, JSValue v2)
{
+ VM& vm = callFrame->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
if (v1.isInt32() && v2.isInt32())
return v1.asInt32() < v2.asInt32();
@@ -133,11 +181,14 @@ ALWAYS_INLINE bool jsLess(CallFrame* callFrame, JSValue v1, JSValue v2)
bool wasNotString2;
if (leftFirst) {
wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1);
+ RETURN_IF_EXCEPTION(scope, false);
wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2);
} else {
wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2);
+ RETURN_IF_EXCEPTION(scope, false);
wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1);
}
+ RETURN_IF_EXCEPTION(scope, false);
if (wasNotString1 | wasNotString2)
return n1 < n2;
@@ -150,6 +201,9 @@ ALWAYS_INLINE bool jsLess(CallFrame* callFrame, JSValue v1, JSValue v2)
template<bool leftFirst>
ALWAYS_INLINE bool jsLessEq(CallFrame* callFrame, JSValue v1, JSValue v2)
{
+ VM& vm = callFrame->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
if (v1.isInt32() && v2.isInt32())
return v1.asInt32() <= v2.asInt32();
@@ -167,11 +221,14 @@ ALWAYS_INLINE bool jsLessEq(CallFrame* callFrame, JSValue v1, JSValue v2)
bool wasNotString2;
if (leftFirst) {
wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1);
+ RETURN_IF_EXCEPTION(scope, false);
wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2);
} else {
wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2);
+ RETURN_IF_EXCEPTION(scope, false);
wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1);
}
+ RETURN_IF_EXCEPTION(scope, false);
if (wasNotString1 | wasNotString2)
return n1 <= n2;
@@ -199,87 +256,18 @@ ALWAYS_INLINE JSValue jsAdd(CallFrame* callFrame, JSValue v1, JSValue v2)
return jsAddSlowCase(callFrame, v1, v2);
}
-#define InvalidPrototypeChain (std::numeric_limits<size_t>::max())
-
-inline size_t normalizePrototypeChainForChainAccess(CallFrame* callFrame, JSValue base, JSValue slotBase, const Identifier& propertyName, PropertyOffset& slotOffset)
+inline bool scribbleFreeCells()
{
- JSCell* cell = base.asCell();
- size_t count = 0;
-
- while (!slotBase || slotBase != cell) {
- if (cell->isProxy())
- return InvalidPrototypeChain;
-
- const TypeInfo& typeInfo = cell->structure()->typeInfo();
- if (typeInfo.hasImpureGetOwnPropertySlot() && !typeInfo.newImpurePropertyFiresWatchpoints())
- return InvalidPrototypeChain;
-
- JSValue v = cell->structure()->prototypeForLookup(callFrame);
-
- // If we didn't find slotBase in base's prototype chain, then base
- // must be a proxy for another object.
-
- if (v.isNull()) {
- if (!slotBase)
- return count;
- return InvalidPrototypeChain;
- }
-
- cell = v.asCell();
-
- // Since we're accessing a prototype in a loop, it's a good bet that it
- // should not be treated as a dictionary.
- if (cell->structure()->isDictionary()) {
- asObject(cell)->flattenDictionaryObject(callFrame->vm());
- if (slotBase == cell)
- slotOffset = cell->structure()->get(callFrame->vm(), propertyName);
- }
-
- ++count;
- }
-
- return count;
-}
-
-inline size_t normalizePrototypeChain(CallFrame* callFrame, JSCell* base)
-{
- size_t count = 0;
- while (1) {
- if (base->isProxy())
- return InvalidPrototypeChain;
-
- JSValue v = base->structure()->prototypeForLookup(callFrame);
- if (v.isNull())
- return count;
-
- base = v.asCell();
-
- // Since we're accessing a prototype in a loop, it's a good bet that it
- // should not be treated as a dictionary.
- if (base->structure()->isDictionary())
- asObject(base)->flattenDictionaryObject(callFrame->vm());
-
- ++count;
- }
+ return !ASSERT_DISABLED || Options::scribbleFreeCells();
}
-inline bool isPrototypeChainNormalized(JSGlobalObject* globalObject, Structure* structure)
+inline void scribble(void* base, size_t size)
{
- for (;;) {
- if (structure->typeInfo().type() == ProxyType)
- return false;
-
- JSValue v = structure->prototypeForLookup(globalObject);
- if (v.isNull())
- return true;
-
- structure = v.asCell()->structure();
-
- if (structure->isDictionary())
- return false;
+ for (size_t i = size / sizeof(EncodedJSValue); i--;) {
+ // Use a 16-byte aligned value to ensure that it passes the cell check.
+ static_cast<EncodedJSValue*>(base)[i] = JSValue::encode(
+ bitwise_cast<JSCell*>(static_cast<intptr_t>(0xbadbeef0)));
}
}
} // namespace JSC
-
-#endif // Operations_h