]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - runtime/CommonSlowPaths.h
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / runtime / CommonSlowPaths.h
index 12e3805c3b63b1333d5000b3c9633c8f425035f6..4d8e3fc8e370f1ea90112e4beca4e843ee9d4770 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
+ * 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
 #include "CodeBlock.h"
 #include "CodeSpecializationKind.h"
 #include "ExceptionHelpers.h"
-#include "JSArray.h"
-#include "NameInstance.h"
+#include "JSStackInlines.h"
+#include "StackAlignment.h"
+#include "Symbol.h"
+#include "VM.h"
+#include <wtf/StdLibExtras.h>
 
 namespace JSC {
 
@@ -43,42 +46,33 @@ namespace JSC {
 
 namespace CommonSlowPaths {
 
-ALWAYS_INLINE ExecState* arityCheckFor(ExecState* exec, JSStack* stack, CodeSpecializationKind kind)
+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()->generatedBytecodeFor(kind);
+    CodeBlock* newCodeBlock = callee->jsExecutable()->codeBlockFor(kind);
     int argumentCountIncludingThis = exec->argumentCountIncludingThis();
-
-    // This ensures enough space for the worst case scenario of zero arguments passed by the caller.
-    if (!stack->grow(exec->registers() + newCodeBlock->numParameters() + newCodeBlock->m_numCalleeRegisters))
-        return 0;
-
+    
     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);
 
-    // Too few arguments -- copy call frame and arguments, then fill in missing arguments with undefined.
-    size_t delta = newCodeBlock->numParameters() - argumentCountIncludingThis;
-    Register* src = exec->registers();
-    Register* dst = exec->registers() + delta;
-
-    int i;
-    int end = -ExecState::offsetFor(argumentCountIncludingThis);
-    for (i = -1; i >= end; --i)
-        dst[i] = src[i];
-
-    end -= delta;
-    for ( ; i >= end; --i)
-        dst[i] = jsUndefined();
-
-    ExecState* newExec = ExecState::create(dst);
-    ASSERT((void*)newExec <= stack->end());
-    return newExec;
+    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().exception = createInvalidParamError(exec, "in", baseVal);
+        exec->vm().throwException(exec, createInvalidInParameterError(exec, baseVal));
         return false;
     }
 
@@ -88,15 +82,158 @@ inline bool opIn(ExecState* exec, JSValue propName, JSValue baseVal)
     if (propName.getUInt32(i))
         return baseObj->hasProperty(exec, i);
 
-    if (isName(propName))
-        return baseObj->hasProperty(exec, jsCast<NameInstance*>(propName.asCell())->privateName());
-
-    Identifier property(exec, propName.toString(exec)->value(exec));
-    if (exec->vm().exception)
+    auto property = propName.toPropertyKey(exec);
+    if (exec->vm().exception())
         return false;
     return baseObj->hasProperty(exec, property);
 }
 
-} } // namespace JSC::CommonSlowPaths
+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);
+
+} // namespace JSC
 
 #endif // CommonSlowPaths_h