]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - dfg/DFGCapabilities.h
JavaScriptCore-7600.1.4.9.tar.gz
[apple/javascriptcore.git] / dfg / DFGCapabilities.h
index a9dc51325c326cdee65731b64c5b16f640e1eee1..b01f04464fe1f57535f7b55fa29bcc73f824b959 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2012, 2013, 2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #ifndef DFGCapabilities_h
 #define DFGCapabilities_h
 
-#include "Intrinsic.h"
+#include "CodeBlock.h"
 #include "DFGCommon.h"
-#include "DFGNode.h"
 #include "Executable.h"
-#include "Options.h"
 #include "Interpreter.h"
-#include <wtf/Platform.h>
+#include "Intrinsic.h"
+#include "Options.h"
 
 namespace JSC { namespace DFG {
 
 #if ENABLE(DFG_JIT)
 // Fast check functions; if they return true it is still necessary to
 // check opcodes.
+bool isSupported(CodeBlock*);
 bool mightCompileEval(CodeBlock*);
 bool mightCompileProgram(CodeBlock*);
 bool mightCompileFunctionForCall(CodeBlock*);
@@ -47,218 +47,9 @@ bool mightInlineFunctionForCall(CodeBlock*);
 bool mightInlineFunctionForClosureCall(CodeBlock*);
 bool mightInlineFunctionForConstruct(CodeBlock*);
 
-// Opcode checking.
-inline bool canInlineResolveOperations(ResolveOperations* operations)
-{
-    for (unsigned i = 0; i < operations->size(); i++) {
-        switch (operations->data()[i].m_operation) {
-        case ResolveOperation::ReturnGlobalObjectAsBase:
-        case ResolveOperation::SetBaseToGlobal:
-        case ResolveOperation::SetBaseToUndefined:
-        case ResolveOperation::GetAndReturnGlobalProperty:
-        case ResolveOperation::GetAndReturnGlobalVar:
-        case ResolveOperation::GetAndReturnGlobalVarWatchable:
-        case ResolveOperation::SkipScopes:
-        case ResolveOperation::SetBaseToScope:
-        case ResolveOperation::ReturnScopeAsBase:
-        case ResolveOperation::GetAndReturnScopedVar:
-            continue;
-
-        case ResolveOperation::Fail:
-            // Fall-back resolves don't know how to deal with the ExecState* having a different
-            // global object (and scope) than the inlined code that is invoking that resolve.
-            return false;
-
-        case ResolveOperation::SkipTopScopeNode:
-            // We don't inline code blocks that create activations. Creation of
-            // activations is the only thing that leads to SkipTopScopeNode.
-            return false;
-
-        case ResolveOperation::CheckForDynamicEntriesBeforeGlobalScope:
-            // This would be easy to support in all cases.
-            return false;
-        }
-    }
-    return true;
-}
-
-inline CapabilityLevel canCompileOpcode(OpcodeID opcodeID, CodeBlock*, Instruction*)
-{
-    switch (opcodeID) {
-    case op_enter:
-    case op_convert_this:
-    case op_create_this:
-    case op_get_callee:
-    case op_bitand:
-    case op_bitor:
-    case op_bitxor:
-    case op_rshift:
-    case op_lshift:
-    case op_urshift:
-    case op_inc:
-    case op_dec:
-    case op_add:
-    case op_sub:
-    case op_negate:
-    case op_mul:
-    case op_mod:
-    case op_div:
-#if ENABLE(DEBUG_WITH_BREAKPOINT)
-    case op_debug:
-#endif
-    case op_mov:
-    case op_check_has_instance:
-    case op_instanceof:
-    case op_is_undefined:
-    case op_is_boolean:
-    case op_is_number:
-    case op_is_string:
-    case op_is_object:
-    case op_is_function:
-    case op_not:
-    case op_less:
-    case op_lesseq:
-    case op_greater:
-    case op_greatereq:
-    case op_eq:
-    case op_eq_null:
-    case op_stricteq:
-    case op_neq:
-    case op_neq_null:
-    case op_nstricteq:
-    case op_get_by_val:
-    case op_put_by_val:
-    case op_get_by_id:
-    case op_get_by_id_out_of_line:
-    case op_get_array_length:
-    case op_put_by_id:
-    case op_put_by_id_out_of_line:
-    case op_put_by_id_transition_direct:
-    case op_put_by_id_transition_direct_out_of_line:
-    case op_put_by_id_transition_normal:
-    case op_put_by_id_transition_normal_out_of_line:
-    case op_init_global_const_nop:
-    case op_init_global_const:
-    case op_init_global_const_check:
-    case op_jmp:
-    case op_jtrue:
-    case op_jfalse:
-    case op_jeq_null:
-    case op_jneq_null:
-    case op_jless:
-    case op_jlesseq:
-    case op_jgreater:
-    case op_jgreatereq:
-    case op_jnless:
-    case op_jnlesseq:
-    case op_jngreater:
-    case op_jngreatereq:
-    case op_loop_hint:
-    case op_ret:
-    case op_end:
-    case op_call_put_result:
-    case op_new_object:
-    case op_new_array:
-    case op_new_array_with_size:
-    case op_new_array_buffer:
-    case op_strcat:
-    case op_to_primitive:
-    case op_throw:
-    case op_throw_static_error:
-    case op_call:
-    case op_construct:
-    case op_new_regexp: 
-    case op_init_lazy_reg:
-    case op_create_activation:
-    case op_tear_off_activation:
-    case op_create_arguments:
-    case op_tear_off_arguments:
-    case op_new_func:
-    case op_new_func_exp:
-    case op_get_argument_by_val:
-    case op_get_arguments_length:
-    case op_jneq_ptr:
-    case op_put_to_base_variable:
-    case op_put_to_base:
-    case op_typeof:
-    case op_to_number:
-        return CanCompile;
-        
-    case op_call_varargs:
-        return MayInline;
-
-    case op_resolve:
-    case op_resolve_global_property:
-    case op_resolve_global_var:
-    case op_resolve_scoped_var:
-    case op_resolve_scoped_var_on_top_scope:
-    case op_resolve_scoped_var_with_top_scope_check:
-        return CanCompile;
-
-    case op_get_scoped_var:
-    case op_put_scoped_var:
-        return CanCompile;
-
-    case op_resolve_base_to_global:
-    case op_resolve_base_to_global_dynamic:
-    case op_resolve_base_to_scope:
-    case op_resolve_base_to_scope_with_top_scope_check:
-    case op_resolve_base:
-    case op_resolve_with_base:
-    case op_resolve_with_this:
-        return CanCompile;
-
-    default:
-        return CannotCompile;
-    }
-}
-
-inline bool canInlineOpcode(OpcodeID opcodeID, CodeBlock* codeBlock, Instruction* pc)
-{
-    switch (opcodeID) {
-    case op_resolve:
-    case op_resolve_global_property:
-    case op_resolve_global_var:
-    case op_resolve_scoped_var:
-    case op_resolve_scoped_var_on_top_scope:
-    case op_resolve_scoped_var_with_top_scope_check:
-        return canInlineResolveOperations(pc[3].u.resolveOperations);
-
-    case op_resolve_base_to_global:
-    case op_resolve_base_to_global_dynamic:
-    case op_resolve_base_to_scope:
-    case op_resolve_base_to_scope_with_top_scope_check:
-    case op_resolve_base:
-    case op_resolve_with_base:
-    case op_resolve_with_this:
-        return canInlineResolveOperations(pc[4].u.resolveOperations);
+inline CapabilityLevel capabilityLevel(OpcodeID opcodeID, CodeBlock* codeBlock, Instruction* pc);
 
-    case op_get_scoped_var:
-    case op_put_scoped_var:
-        return !codeBlock->needsFullScopeChain();
-
-    // Inlining doesn't correctly remap regular expression operands.
-    case op_new_regexp:
-        
-    // We don't support inlining code that creates activations or has nested functions.
-    case op_create_activation:
-    case op_tear_off_activation:
-    case op_new_func:
-    case op_new_func_exp:
-        return false;
-        
-    // Inlining supports op_call_varargs if it's a call that just forwards the caller's
-    // arguments.
-    case op_call_varargs:
-        return codeBlock->usesArguments() && pc[3].u.operand == codeBlock->argumentsRegister();
-        
-    default:
-        return canCompileOpcode(opcodeID, codeBlock, pc) == CanCompile;
-    }
-}
-
-CapabilityLevel canCompileOpcodes(CodeBlock*);
-bool canInlineOpcodes(CodeBlock*);
+CapabilityLevel capabilityLevel(CodeBlock*);
 #else // ENABLE(DFG_JIT)
 inline bool mightCompileEval(CodeBlock*) { return false; }
 inline bool mightCompileProgram(CodeBlock*) { return false; }
@@ -268,57 +59,78 @@ inline bool mightInlineFunctionForCall(CodeBlock*) { return false; }
 inline bool mightInlineFunctionForClosureCall(CodeBlock*) { return false; }
 inline bool mightInlineFunctionForConstruct(CodeBlock*) { return false; }
 
-inline CapabilityLevel canCompileOpcode(OpcodeID, CodeBlock*, Instruction*) { return CannotCompile; }
-inline bool canInlineOpcode(OpcodeID, CodeBlock*, Instruction*) { return false; }
-inline CapabilityLevel canCompileOpcodes(CodeBlock*) { return CannotCompile; }
-inline bool canInlineOpcodes(CodeBlock*) { return false; }
+inline CapabilityLevel capabilityLevel(OpcodeID, CodeBlock*, Instruction*) { return CannotCompile; }
+inline CapabilityLevel capabilityLevel(CodeBlock*) { return CannotCompile; }
 #endif // ENABLE(DFG_JIT)
 
-inline CapabilityLevel canCompileEval(CodeBlock* codeBlock)
+inline CapabilityLevel evalCapabilityLevel(CodeBlock* codeBlock)
 {
     if (!mightCompileEval(codeBlock))
         return CannotCompile;
     
-    return canCompileOpcodes(codeBlock);
+    return capabilityLevel(codeBlock);
 }
 
-inline CapabilityLevel canCompileProgram(CodeBlock* codeBlock)
+inline CapabilityLevel programCapabilityLevel(CodeBlock* codeBlock)
 {
     if (!mightCompileProgram(codeBlock))
         return CannotCompile;
     
-    return canCompileOpcodes(codeBlock);
+    return capabilityLevel(codeBlock);
 }
 
-inline CapabilityLevel canCompileFunctionForCall(CodeBlock* codeBlock)
+inline CapabilityLevel functionCapabilityLevel(bool mightCompile, bool mightInline, CapabilityLevel computedCapabilityLevel)
 {
-    if (!mightCompileFunctionForCall(codeBlock))
+    if (mightCompile && mightInline)
+        return leastUpperBound(CanCompileAndInline, computedCapabilityLevel);
+    if (mightCompile && !mightInline)
+        return leastUpperBound(CanCompile, computedCapabilityLevel);
+    if (!mightCompile && mightInline)
+        return leastUpperBound(CanInline, computedCapabilityLevel);
+    if (!mightCompile && !mightInline)
         return CannotCompile;
-    
-    return canCompileOpcodes(codeBlock);
+    RELEASE_ASSERT_NOT_REACHED();
+    return CannotCompile;
 }
 
-inline CapabilityLevel canCompileFunctionForConstruct(CodeBlock* codeBlock)
+inline CapabilityLevel functionForCallCapabilityLevel(CodeBlock* codeBlock)
 {
-    if (!mightCompileFunctionForConstruct(codeBlock))
-        return CannotCompile;
-    
-    return canCompileOpcodes(codeBlock);
+    return functionCapabilityLevel(
+        mightCompileFunctionForCall(codeBlock),
+        mightInlineFunctionForCall(codeBlock),
+        capabilityLevel(codeBlock));
 }
 
-inline bool canInlineFunctionForCall(CodeBlock* codeBlock)
+inline CapabilityLevel functionForConstructCapabilityLevel(CodeBlock* codeBlock)
 {
-    return mightInlineFunctionForCall(codeBlock) && canInlineOpcodes(codeBlock);
+    return functionCapabilityLevel(
+        mightCompileFunctionForConstruct(codeBlock),
+        mightInlineFunctionForConstruct(codeBlock),
+        capabilityLevel(codeBlock));
+}
+
+inline CapabilityLevel inlineFunctionForCallCapabilityLevel(CodeBlock* codeBlock)
+{
+    if (!mightInlineFunctionForCall(codeBlock))
+        return CannotCompile;
+    
+    return capabilityLevel(codeBlock);
 }
 
-inline bool canInlineFunctionForClosureCall(CodeBlock* codeBlock)
+inline CapabilityLevel inlineFunctionForClosureCallCapabilityLevel(CodeBlock* codeBlock)
 {
-    return mightInlineFunctionForClosureCall(codeBlock) && canInlineOpcodes(codeBlock);
+    if (!mightInlineFunctionForClosureCall(codeBlock))
+        return CannotCompile;
+    
+    return capabilityLevel(codeBlock);
 }
 
-inline bool canInlineFunctionForConstruct(CodeBlock* codeBlock)
+inline CapabilityLevel inlineFunctionForConstructCapabilityLevel(CodeBlock* codeBlock)
 {
-    return mightInlineFunctionForConstruct(codeBlock) && canInlineOpcodes(codeBlock);
+    if (!mightInlineFunctionForConstruct(codeBlock))
+        return CannotCompile;
+    
+    return capabilityLevel(codeBlock);
 }
 
 inline bool mightInlineFunctionFor(CodeBlock* codeBlock, CodeSpecializationKind kind)
@@ -329,16 +141,27 @@ inline bool mightInlineFunctionFor(CodeBlock* codeBlock, CodeSpecializationKind
     return mightInlineFunctionForConstruct(codeBlock);
 }
 
-inline bool canInlineFunctionFor(CodeBlock* codeBlock, CodeSpecializationKind kind, bool isClosureCall)
+inline bool mightInlineFunction(CodeBlock* codeBlock)
+{
+    return mightInlineFunctionFor(codeBlock, codeBlock->specializationKind());
+}
+
+inline CapabilityLevel inlineFunctionForCapabilityLevel(CodeBlock* codeBlock, CodeSpecializationKind kind, bool isClosureCall)
 {
     if (isClosureCall) {
-        ASSERT(kind == CodeForCall);
-        return canInlineFunctionForClosureCall(codeBlock);
+        if (kind != CodeForCall)
+            return CannotCompile;
+        return inlineFunctionForClosureCallCapabilityLevel(codeBlock);
     }
     if (kind == CodeForCall)
-        return canInlineFunctionForCall(codeBlock);
+        return inlineFunctionForCallCapabilityLevel(codeBlock);
     ASSERT(kind == CodeForConstruct);
-    return canInlineFunctionForConstruct(codeBlock);
+    return inlineFunctionForConstructCapabilityLevel(codeBlock);
+}
+
+inline bool isSmallEnoughToInlineCodeInto(CodeBlock* codeBlock)
+{
+    return codeBlock->instructionCount() <= Options::maximumInliningCallerSize();
 }
 
 } } // namespace JSC::DFG