diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/JavaScriptCore/runtime/Operations.h | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/JavaScriptCore/runtime/Operations.h')
-rw-r--r-- | Source/JavaScriptCore/runtime/Operations.h | 200 |
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 |