summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/runtime/CommonSlowPaths.h
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/runtime/CommonSlowPaths.h')
-rw-r--r--Source/JavaScriptCore/runtime/CommonSlowPaths.h241
1 files changed, 241 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/runtime/CommonSlowPaths.h b/Source/JavaScriptCore/runtime/CommonSlowPaths.h
new file mode 100644
index 000000000..067df0c38
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/CommonSlowPaths.h
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2011-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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CommonSlowPaths_h
+#define CommonSlowPaths_h
+
+#include "CodeBlock.h"
+#include "CodeSpecializationKind.h"
+#include "ExceptionHelpers.h"
+#include "JSStackInlines.h"
+#include "StackAlignment.h"
+#include "Symbol.h"
+#include "VM.h"
+#include <wtf/StdLibExtras.h>
+
+namespace JSC {
+
+// The purpose of this namespace is to include slow paths that are shared
+// between the interpreter and baseline JIT. They are written to be agnostic
+// with respect to the slow-path calling convention, but they do rely on the
+// JS code being executed more-or-less directly from bytecode (so the call
+// frame layout is unmodified, making it potentially awkward to use these
+// from any optimizing JIT, like the DFG).
+
+namespace CommonSlowPaths {
+
+struct ArityCheckData {
+ unsigned paddedStackSpace;
+ void* thunkToCall;
+ void* returnPC;
+};
+
+ALWAYS_INLINE int arityCheckFor(ExecState* exec, JSStack* stack, CodeSpecializationKind kind)
+{
+ JSFunction* callee = jsCast<JSFunction*>(exec->callee());
+ ASSERT(!callee->isHostFunction());
+ CodeBlock* newCodeBlock = callee->jsExecutable()->codeBlockFor(kind);
+ int argumentCountIncludingThis = exec->argumentCountIncludingThis();
+
+ ASSERT(argumentCountIncludingThis < newCodeBlock->numParameters());
+ int missingArgumentCount = newCodeBlock->numParameters() - argumentCountIncludingThis;
+ int neededStackSpace = missingArgumentCount + 1; // Allow space to save the original return PC.
+ int paddedStackSpace = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), neededStackSpace);
+
+ if (!stack->ensureCapacityFor(exec->registers() - paddedStackSpace))
+ return -1;
+ return paddedStackSpace / stackAlignmentRegisters();
+}
+
+inline bool opIn(ExecState* exec, JSValue propName, JSValue baseVal)
+{
+ if (!baseVal.isObject()) {
+ exec->vm().throwException(exec, createInvalidInParameterError(exec, baseVal));
+ return false;
+ }
+
+ JSObject* baseObj = asObject(baseVal);
+
+ uint32_t i;
+ if (propName.getUInt32(i))
+ return baseObj->hasProperty(exec, i);
+
+ auto property = propName.toPropertyKey(exec);
+ if (exec->vm().exception())
+ return false;
+ return baseObj->hasProperty(exec, property);
+}
+
+inline void tryCachePutToScopeGlobal(
+ ExecState* exec, CodeBlock* codeBlock, Instruction* pc, JSObject* scope,
+ ResolveModeAndType modeAndType, PutPropertySlot& 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)
+ return;
+
+ if (!slot.isCacheablePut()
+ || slot.base() != scope
+ || !scope->structure()->propertyAccessesAreCacheable())
+ return;
+
+ if (slot.type() == PutPropertySlot::NewProperty) {
+ // Don't cache if we've done a transition. We want to detect the first replace so that we
+ // can invalidate the watchpoint.
+ return;
+ }
+
+ scope->structure()->didCachePropertyReplacement(exec->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();
+}
+
+} // namespace CommonSlowPaths
+
+class ExecState;
+struct Instruction;
+
+#if USE(JSVALUE64)
+// According to C++ rules, a type used for the return signature of function with C linkage (i.e.
+// 'extern "C"') needs to be POD; hence putting any constructors into it could cause either compiler
+// warnings, or worse, a change in the ABI used to return these types.
+struct SlowPathReturnType {
+ void* a;
+ void* b;
+};
+
+inline SlowPathReturnType encodeResult(void* a, void* b)
+{
+ SlowPathReturnType result;
+ result.a = a;
+ result.b = b;
+ return result;
+}
+
+inline void decodeResult(SlowPathReturnType result, void*& a, void*& b)
+{
+ a = result.a;
+ b = result.b;
+}
+
+#else // USE(JSVALUE32_64)
+typedef int64_t SlowPathReturnType;
+
+typedef union {
+ struct {
+ void* a;
+ void* b;
+ } pair;
+ int64_t i;
+} SlowPathReturnTypeEncoding;
+
+inline SlowPathReturnType encodeResult(void* a, void* b)
+{
+ SlowPathReturnTypeEncoding u;
+ u.pair.a = a;
+ u.pair.b = b;
+ return u.i;
+}
+
+inline void decodeResult(SlowPathReturnType result, void*& a, void*& b)
+{
+ SlowPathReturnTypeEncoding u;
+ u.i = result;
+ a = u.pair.a;
+ b = u.pair.b;
+}
+#endif // USE(JSVALUE32_64)
+
+#define SLOW_PATH
+
+#define SLOW_PATH_DECL(name) \
+extern "C" SlowPathReturnType SLOW_PATH name(ExecState* exec, Instruction* pc)
+
+#define SLOW_PATH_HIDDEN_DECL(name) \
+SLOW_PATH_DECL(name) WTF_INTERNAL
+
+SLOW_PATH_HIDDEN_DECL(slow_path_call_arityCheck);
+SLOW_PATH_HIDDEN_DECL(slow_path_construct_arityCheck);
+SLOW_PATH_HIDDEN_DECL(slow_path_create_direct_arguments);
+SLOW_PATH_HIDDEN_DECL(slow_path_create_scoped_arguments);
+SLOW_PATH_HIDDEN_DECL(slow_path_create_out_of_band_arguments);
+SLOW_PATH_HIDDEN_DECL(slow_path_create_this);
+SLOW_PATH_HIDDEN_DECL(slow_path_enter);
+SLOW_PATH_HIDDEN_DECL(slow_path_get_callee);
+SLOW_PATH_HIDDEN_DECL(slow_path_to_this);
+SLOW_PATH_HIDDEN_DECL(slow_path_throw_tdz_error);
+SLOW_PATH_HIDDEN_DECL(slow_path_not);
+SLOW_PATH_HIDDEN_DECL(slow_path_eq);
+SLOW_PATH_HIDDEN_DECL(slow_path_neq);
+SLOW_PATH_HIDDEN_DECL(slow_path_stricteq);
+SLOW_PATH_HIDDEN_DECL(slow_path_nstricteq);
+SLOW_PATH_HIDDEN_DECL(slow_path_less);
+SLOW_PATH_HIDDEN_DECL(slow_path_lesseq);
+SLOW_PATH_HIDDEN_DECL(slow_path_greater);
+SLOW_PATH_HIDDEN_DECL(slow_path_greatereq);
+SLOW_PATH_HIDDEN_DECL(slow_path_inc);
+SLOW_PATH_HIDDEN_DECL(slow_path_dec);
+SLOW_PATH_HIDDEN_DECL(slow_path_to_number);
+SLOW_PATH_HIDDEN_DECL(slow_path_to_string);
+SLOW_PATH_HIDDEN_DECL(slow_path_negate);
+SLOW_PATH_HIDDEN_DECL(slow_path_add);
+SLOW_PATH_HIDDEN_DECL(slow_path_mul);
+SLOW_PATH_HIDDEN_DECL(slow_path_sub);
+SLOW_PATH_HIDDEN_DECL(slow_path_div);
+SLOW_PATH_HIDDEN_DECL(slow_path_mod);
+SLOW_PATH_HIDDEN_DECL(slow_path_lshift);
+SLOW_PATH_HIDDEN_DECL(slow_path_rshift);
+SLOW_PATH_HIDDEN_DECL(slow_path_urshift);
+SLOW_PATH_HIDDEN_DECL(slow_path_unsigned);
+SLOW_PATH_HIDDEN_DECL(slow_path_bitand);
+SLOW_PATH_HIDDEN_DECL(slow_path_bitor);
+SLOW_PATH_HIDDEN_DECL(slow_path_bitxor);
+SLOW_PATH_HIDDEN_DECL(slow_path_typeof);
+SLOW_PATH_HIDDEN_DECL(slow_path_is_object);
+SLOW_PATH_HIDDEN_DECL(slow_path_is_object_or_null);
+SLOW_PATH_HIDDEN_DECL(slow_path_is_function);
+SLOW_PATH_HIDDEN_DECL(slow_path_in);
+SLOW_PATH_HIDDEN_DECL(slow_path_del_by_val);
+SLOW_PATH_HIDDEN_DECL(slow_path_strcat);
+SLOW_PATH_HIDDEN_DECL(slow_path_to_primitive);
+SLOW_PATH_HIDDEN_DECL(slow_path_get_enumerable_length);
+SLOW_PATH_HIDDEN_DECL(slow_path_has_generic_property);
+SLOW_PATH_HIDDEN_DECL(slow_path_has_structure_property);
+SLOW_PATH_HIDDEN_DECL(slow_path_has_indexed_property);
+SLOW_PATH_HIDDEN_DECL(slow_path_get_direct_pname);
+SLOW_PATH_HIDDEN_DECL(slow_path_get_property_enumerator);
+SLOW_PATH_HIDDEN_DECL(slow_path_next_structure_enumerator_pname);
+SLOW_PATH_HIDDEN_DECL(slow_path_next_generic_enumerator_pname);
+SLOW_PATH_HIDDEN_DECL(slow_path_to_index_string);
+SLOW_PATH_HIDDEN_DECL(slow_path_profile_type_clear_log);
+SLOW_PATH_HIDDEN_DECL(slow_path_create_lexical_environment);
+SLOW_PATH_HIDDEN_DECL(slow_path_push_with_scope);
+
+} // namespace JSC
+
+#endif // CommonSlowPaths_h