WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
getting interesting
blah.patch (text/plain), 44.72 KB, created by
Filip Pizlo
on 2013-11-29 20:41:08 PST
(
hide
)
Description:
getting interesting
Filename:
MIME Type:
Creator:
Filip Pizlo
Created:
2013-11-29 20:41:08 PST
Size:
44.72 KB
patch
obsolete
>Index: Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj >=================================================================== >--- Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (revision 159882) >+++ Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (working copy) >@@ -289,6 +289,7 @@ > 0F8335B71639C1E6001443B5 /* ArrayAllocationProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F8335B41639C1E3001443B5 /* ArrayAllocationProfile.cpp */; }; > 0F8335B81639C1EA001443B5 /* ArrayAllocationProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F8335B51639C1E3001443B5 /* ArrayAllocationProfile.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0F8364B7164B0C110053329A /* DFGBranchDirection.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F8364B5164B0C0E0053329A /* DFGBranchDirection.h */; settings = {ATTRIBUTES = (Private, ); }; }; >+ 0F885E111849A3BE00F1E3FA /* BytecodeUseDef.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F885E101849A3BE00F1E3FA /* BytecodeUseDef.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0F8F2B95172E04A0007DBDA5 /* FTLLink.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F8F2B93172E049E007DBDA5 /* FTLLink.cpp */; }; > 0F8F2B96172E04A3007DBDA5 /* FTLLink.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F8F2B94172E049E007DBDA5 /* FTLLink.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 0F8F2B99172F04FF007DBDA5 /* DFGDesiredIdentifiers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F8F2B97172F04FD007DBDA5 /* DFGDesiredIdentifiers.cpp */; }; >@@ -1583,6 +1584,7 @@ > 0F8335B51639C1E3001443B5 /* ArrayAllocationProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArrayAllocationProfile.h; sourceTree = "<group>"; }; > 0F8364B5164B0C0E0053329A /* DFGBranchDirection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGBranchDirection.h; path = dfg/DFGBranchDirection.h; sourceTree = "<group>"; }; > 0F85A31E16AB76AE0077571E /* DFGVariadicFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGVariadicFunction.h; path = dfg/DFGVariadicFunction.h; sourceTree = "<group>"; }; >+ 0F885E101849A3BE00F1E3FA /* BytecodeUseDef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BytecodeUseDef.h; sourceTree = "<group>"; }; > 0F8F2B93172E049E007DBDA5 /* FTLLink.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = FTLLink.cpp; path = ftl/FTLLink.cpp; sourceTree = "<group>"; }; > 0F8F2B94172E049E007DBDA5 /* FTLLink.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FTLLink.h; path = ftl/FTLLink.h; sourceTree = "<group>"; }; > 0F8F2B97172F04FD007DBDA5 /* DFGDesiredIdentifiers.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = DFGDesiredIdentifiers.cpp; path = dfg/DFGDesiredIdentifiers.cpp; sourceTree = "<group>"; }; >@@ -4058,6 +4060,7 @@ > C2FCAE0E17A9C24E0034C735 /* BytecodeLivenessAnalysis.cpp */, > C2FCAE0F17A9C24E0034C735 /* BytecodeLivenessAnalysis.h */, > 0F666EBE183566F900D017F1 /* BytecodeLivenessAnalysisInlines.h */, >+ 0F885E101849A3BE00F1E3FA /* BytecodeUseDef.h */, > 0F8023E91613832300A0BA45 /* ByValInfo.h */, > 0F0B83AE14BCF71400885B4F /* CallLinkInfo.cpp */, > 0F0B83AF14BCF71400885B4F /* CallLinkInfo.h */, >@@ -4269,6 +4272,7 @@ > BC3135640F302FA3003DFD3A /* DebuggerActivation.h in Headers */, > BC18C3FB0E16F5CD00B34460 /* DebuggerCallFrame.h in Headers */, > 0F136D4D174AD69E0075B354 /* DeferGC.h in Headers */, >+ 0F885E111849A3BE00F1E3FA /* BytecodeUseDef.h in Headers */, > 0FC712DF17CD877C008CC93C /* DeferredCompilationCallback.h in Headers */, > A77A423E17A0BBFD00A8DB81 /* DFGAbstractHeap.h in Headers */, > A704D90317A0BAA8006BA554 /* DFGAbstractInterpreter.h in Headers */, >Index: Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp >=================================================================== >--- Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp (revision 159882) >+++ Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp (working copy) >@@ -27,6 +27,7 @@ > #include "BytecodeLivenessAnalysis.h" > > #include "BytecodeLivenessAnalysisInlines.h" >+#include "BytecodeUseDef.h" > #include "CodeBlock.h" > #include "FullBytecodeLiveness.h" > #include "PreciseJumpTargets.h" >@@ -67,424 +68,26 @@ static void setForOperand(CodeBlock* cod > bits.set(virtualReg.toLocal() - codeBlock->captureCount()); > } > >-static void computeUsesForBytecodeOffset(CodeBlock* codeBlock, unsigned bytecodeOffset, FastBitVector& uses) >-{ >- Interpreter* interpreter = codeBlock->vm()->interpreter; >- Instruction* instructionsBegin = codeBlock->instructions().begin(); >- Instruction* instruction = &instructionsBegin[bytecodeOffset]; >- OpcodeID opcodeID = interpreter->getOpcodeID(instruction->u.opcode); >- switch (opcodeID) { >- // No uses. >- case op_new_regexp: >- case op_new_array_buffer: >- case op_throw_static_error: >- case op_debug: >- case op_resolve_scope: >- case op_pop_scope: >- case op_jneq_ptr: >- case op_new_func_exp: >- case op_loop_hint: >- case op_jmp: >- case op_new_object: >- case op_init_lazy_reg: >- case op_get_callee: >- case op_enter: >- case op_catch: >- return; >- // First argument. >- case op_new_func: >- case op_create_activation: >- case op_create_arguments: >- case op_to_this: >- case op_tear_off_activation: >- case op_profile_will_call: >- case op_profile_did_call: >- case op_throw: >- case op_push_with_scope: >- case op_end: >- case op_ret: >- case op_jtrue: >- case op_jfalse: >- case op_jeq_null: >- case op_jneq_null: >- case op_dec: >- case op_inc: { >- if (isValidRegisterForLiveness(codeBlock, instruction[1].u.operand)) >- setForOperand(codeBlock, uses, instruction[1].u.operand); >- return; >- } >- // First and second arguments. >- case op_del_by_id: >- case op_ret_object_or_this: >- case op_jlesseq: >- case op_jgreater: >- case op_jgreatereq: >- case op_jnless: >- case op_jnlesseq: >- case op_jngreater: >- case op_jngreatereq: >- case op_jless: { >- if (isValidRegisterForLiveness(codeBlock, instruction[1].u.operand)) >- setForOperand(codeBlock, uses, instruction[1].u.operand); >- if (isValidRegisterForLiveness(codeBlock, instruction[2].u.operand)) >- setForOperand(codeBlock, uses, instruction[2].u.operand); >- return; >- } >- // First, second, and third arguments. >- case op_del_by_val: >- case op_put_by_val_direct: >- case op_put_by_val: { >- if (isValidRegisterForLiveness(codeBlock, instruction[1].u.operand)) >- setForOperand(codeBlock, uses, instruction[1].u.operand); >- if (isValidRegisterForLiveness(codeBlock, instruction[2].u.operand)) >- setForOperand(codeBlock, uses, instruction[2].u.operand); >- if (isValidRegisterForLiveness(codeBlock, instruction[3].u.operand)) >- setForOperand(codeBlock, uses, instruction[3].u.operand); >- return; >- } >- // First and third arguments. >- case op_put_by_index: >- case op_put_by_id_replace: >- case op_put_by_id_transition: >- 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_put_by_id_generic: >- case op_put_by_id_out_of_line: >- case op_put_by_id: >- case op_put_to_scope: { >- if (isValidRegisterForLiveness(codeBlock, instruction[1].u.operand)) >- setForOperand(codeBlock, uses, instruction[1].u.operand); >- if (isValidRegisterForLiveness(codeBlock, instruction[3].u.operand)) >- setForOperand(codeBlock, uses, instruction[3].u.operand); >- return; >- } >- // First, third, and fourth arguments. >- case op_put_getter_setter: { >- if (isValidRegisterForLiveness(codeBlock, instruction[1].u.operand)) >- setForOperand(codeBlock, uses, instruction[1].u.operand); >- if (isValidRegisterForLiveness(codeBlock, instruction[3].u.operand)) >- setForOperand(codeBlock, uses, instruction[3].u.operand); >- if (isValidRegisterForLiveness(codeBlock, instruction[4].u.operand)) >- setForOperand(codeBlock, uses, instruction[4].u.operand); >- return; >- } >- // Second argument. >- case op_init_global_const_nop: >- case op_init_global_const: >- case op_push_name_scope: >- case op_get_from_scope: >- case op_to_primitive: >- case op_get_by_id: >- case op_get_by_id_out_of_line: >- case op_get_by_id_self: >- case op_get_by_id_proto: >- case op_get_by_id_chain: >- case op_get_by_id_getter_self: >- case op_get_by_id_getter_proto: >- case op_get_by_id_getter_chain: >- case op_get_by_id_custom_self: >- case op_get_by_id_custom_proto: >- case op_get_by_id_custom_chain: >- case op_get_by_id_generic: >- case op_get_array_length: >- case op_get_string_length: >- case op_get_arguments_length: >- case op_typeof: >- 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_to_number: >- case op_negate: >- case op_neq_null: >- case op_eq_null: >- case op_not: >- case op_mov: >- case op_new_array_with_size: >- case op_create_this: { >- if (isValidRegisterForLiveness(codeBlock, instruction[2].u.operand)) >- setForOperand(codeBlock, uses, instruction[2].u.operand); >- return; >- } >- // Second and third arguments. >- case op_get_by_val: >- case op_get_argument_by_val: >- case op_in: >- case op_instanceof: >- case op_check_has_instance: >- case op_add: >- case op_mul: >- case op_div: >- case op_mod: >- case op_sub: >- case op_lshift: >- case op_rshift: >- case op_urshift: >- case op_bitand: >- case op_bitxor: >- case op_bitor: >- case op_less: >- case op_lesseq: >- case op_greater: >- case op_greatereq: >- case op_nstricteq: >- case op_stricteq: >- case op_neq: >- case op_eq: { >- if (isValidRegisterForLiveness(codeBlock, instruction[2].u.operand)) >- setForOperand(codeBlock, uses, instruction[2].u.operand); >- if (isValidRegisterForLiveness(codeBlock, instruction[3].u.operand)) >- setForOperand(codeBlock, uses, instruction[3].u.operand); >- return; >- } >- // Second, third, and fourth arguments. >- case op_call_varargs: >- case op_get_pnames: { >- if (isValidRegisterForLiveness(codeBlock, instruction[2].u.operand)) >- setForOperand(codeBlock, uses, instruction[2].u.operand); >- if (isValidRegisterForLiveness(codeBlock, instruction[3].u.operand)) >- setForOperand(codeBlock, uses, instruction[3].u.operand); >- if (isValidRegisterForLiveness(codeBlock, instruction[4].u.operand)) >- setForOperand(codeBlock, uses, instruction[4].u.operand); >- return; >- } >- // Second, third, fourth, and fifth arguments. >- case op_next_pname: { >- if (isValidRegisterForLiveness(codeBlock, instruction[2].u.operand)) >- setForOperand(codeBlock, uses, instruction[2].u.operand); >- if (isValidRegisterForLiveness(codeBlock, instruction[3].u.operand)) >- setForOperand(codeBlock, uses, instruction[3].u.operand); >- if (isValidRegisterForLiveness(codeBlock, instruction[4].u.operand)) >- setForOperand(codeBlock, uses, instruction[4].u.operand); >- if (isValidRegisterForLiveness(codeBlock, instruction[5].u.operand)) >- setForOperand(codeBlock, uses, instruction[5].u.operand); >- return; >- } >- // Second, third, fourth, fifth, and sixth arguments. >- case op_get_by_pname: { >- if (isValidRegisterForLiveness(codeBlock, instruction[2].u.operand)) >- setForOperand(codeBlock, uses, instruction[2].u.operand); >- if (isValidRegisterForLiveness(codeBlock, instruction[3].u.operand)) >- setForOperand(codeBlock, uses, instruction[3].u.operand); >- if (isValidRegisterForLiveness(codeBlock, instruction[4].u.operand)) >- setForOperand(codeBlock, uses, instruction[4].u.operand); >- if (isValidRegisterForLiveness(codeBlock, instruction[5].u.operand)) >- setForOperand(codeBlock, uses, instruction[5].u.operand); >- if (isValidRegisterForLiveness(codeBlock, instruction[6].u.operand)) >- setForOperand(codeBlock, uses, instruction[6].u.operand); >- return; >- } >- // Third argument. >- case op_switch_string: >- case op_switch_char: >- case op_switch_imm: { >- if (isValidRegisterForLiveness(codeBlock, instruction[3].u.operand)) >- setForOperand(codeBlock, uses, instruction[3].u.operand); >- return; >- } >- // Variable number of arguments. >- case op_new_array: >- case op_strcat: { >- int base = instruction[2].u.operand; >- int count = instruction[3].u.operand; >- for (int i = 0; i < count; i++) { >- if (isValidRegisterForLiveness(codeBlock, base - i)) >- setForOperand(codeBlock, uses, base - i); >- } >- return; >- } >- // Crazy stuff for calls. >- case op_construct: >- case op_call_eval: >- case op_call: { >- if (isValidRegisterForLiveness(codeBlock, instruction[2].u.operand)) >- setForOperand(codeBlock, uses, instruction[2].u.operand); >- int argCount = instruction[3].u.operand; >- int registerOffset = -instruction[4].u.operand; >- int lastArg = registerOffset + CallFrame::thisArgumentOffset(); >- for (int i = opcodeID == op_construct ? 1 : 0; i < argCount; i++) { >- if (isValidRegisterForLiveness(codeBlock, lastArg + i)) >- setForOperand(codeBlock, uses, lastArg + i); >- } >- return; >- } >- // Special stuff for tear off arguments. >- case op_tear_off_arguments: { >- if (isValidRegisterForLiveness(codeBlock, instruction[1].u.operand)) >- setForOperand(codeBlock, uses, instruction[1].u.operand); >- if (isValidRegisterForLiveness(codeBlock, unmodifiedArgumentsRegister(VirtualRegister(instruction[1].u.operand)).offset())) >- setForOperand(codeBlock, uses, unmodifiedArgumentsRegister(VirtualRegister(instruction[1].u.operand)).offset()); >- if (isValidRegisterForLiveness(codeBlock, instruction[2].u.operand)) >- setForOperand(codeBlock, uses, instruction[2].u.operand); >- return; >- } >- default: >- RELEASE_ASSERT_NOT_REACHED(); >- break; >- } >-} >+namespace { > >-static void computeDefsForBytecodeOffset(CodeBlock* codeBlock, unsigned bytecodeOffset, FastBitVector& defs) >-{ >- Interpreter* interpreter = codeBlock->vm()->interpreter; >- Instruction* instructionsBegin = codeBlock->instructions().begin(); >- Instruction* instruction = &instructionsBegin[bytecodeOffset]; >- OpcodeID opcodeID = interpreter->getOpcodeID(instruction->u.opcode); >- switch (opcodeID) { >- // These don't define anything. >- case op_init_global_const: >- case op_init_global_const_nop: >- case op_push_name_scope: >- case op_push_with_scope: >- case op_put_to_scope: >- case op_pop_scope: >- case op_end: >- case op_profile_will_call: >- case op_profile_did_call: >- case op_throw: >- case op_throw_static_error: >- case op_debug: >- case op_ret: >- case op_ret_object_or_this: >- case op_jmp: >- case op_jtrue: >- case op_jfalse: >- case op_jeq_null: >- case op_jneq_null: >- case op_jneq_ptr: >- 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_switch_imm: >- case op_switch_char: >- case op_switch_string: >- case op_put_by_id: >- case op_put_by_id_out_of_line: >- case op_put_by_id_replace: >- case op_put_by_id_transition: >- 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_put_by_id_generic: >- case op_put_getter_setter: >- case op_put_by_val: >- case op_put_by_val_direct: >- case op_put_by_index: >- case op_del_by_id: >- case op_del_by_val: >-#define LLINT_HELPER_OPCODES(opcode, length) case opcode: >- FOR_EACH_LLINT_OPCODE_EXTENSION(LLINT_HELPER_OPCODES); >-#undef LLINT_HELPER_OPCODES >- return; >- // These all have a single destination for the first argument. >- case op_next_pname: >- case op_get_pnames: >- case op_resolve_scope: >- case op_strcat: >- case op_tear_off_activation: >- case op_to_primitive: >- case op_catch: >- case op_create_this: >- case op_new_array: >- case op_new_array_buffer: >- case op_new_array_with_size: >- case op_new_regexp: >- case op_new_func: >- case op_new_func_exp: >- case op_call_varargs: >- case op_get_from_scope: >- case op_call: >- case op_call_eval: >- case op_construct: >- case op_get_by_id: >- case op_get_by_id_out_of_line: >- case op_get_by_id_self: >- case op_get_by_id_proto: >- case op_get_by_id_chain: >- case op_get_by_id_getter_self: >- case op_get_by_id_getter_proto: >- case op_get_by_id_getter_chain: >- case op_get_by_id_custom_self: >- case op_get_by_id_custom_proto: >- case op_get_by_id_custom_chain: >- case op_get_by_id_generic: >- case op_get_array_length: >- case op_get_string_length: >- case op_check_has_instance: >- case op_instanceof: >- case op_get_by_val: >- case op_get_argument_by_val: >- case op_get_by_pname: >- case op_get_arguments_length: >- case op_typeof: >- 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_in: >- case op_to_number: >- case op_negate: >- case op_add: >- case op_mul: >- case op_div: >- case op_mod: >- case op_sub: >- case op_lshift: >- case op_rshift: >- case op_urshift: >- case op_bitand: >- case op_bitxor: >- case op_bitor: >- case op_inc: >- case op_dec: >- case op_eq: >- case op_neq: >- case op_stricteq: >- case op_nstricteq: >- case op_less: >- case op_lesseq: >- case op_greater: >- case op_greatereq: >- case op_neq_null: >- case op_eq_null: >- case op_not: >- case op_mov: >- case op_new_object: >- case op_to_this: >- case op_get_callee: >- case op_init_lazy_reg: >- case op_create_activation: >- case op_create_arguments: { >- if (isValidRegisterForLiveness(codeBlock, instruction[1].u.operand)) >- setForOperand(codeBlock, defs, instruction[1].u.operand); >- return; >+class SetBit { >+public: >+ SetBit(FastBitVector& bits) >+ : m_bits(bits) >+ { > } >- case op_tear_off_arguments: { >- int operand = unmodifiedArgumentsRegister( >- VirtualRegister(instruction[1].u.operand)).offset(); >+ >+ void operator()(CodeBlock* codeBlock, Instruction*, OpcodeID, int operand) >+ { > if (isValidRegisterForLiveness(codeBlock, operand)) >- setForOperand(codeBlock, defs, operand); >- return; >+ setForOperand(codeBlock, m_bits, operand); > } >- case op_enter: { >- defs.setAll(); >- return; >- } } >- RELEASE_ASSERT_NOT_REACHED(); >-} >+ >+private: >+ FastBitVector& m_bits; >+}; >+ >+} // anonymous namespace > > static unsigned getLeaderOffsetForBasicBlock(RefPtr<BytecodeBasicBlock>* basicBlock) > { >@@ -535,8 +138,10 @@ static void stepOverInstruction(CodeBloc > uses.clearAll(); > defs.clearAll(); > >- computeUsesForBytecodeOffset(codeBlock, bytecodeOffset, uses); >- computeDefsForBytecodeOffset(codeBlock, bytecodeOffset, defs); >+ SetBit setUses(uses); >+ SetBit setDefs(defs); >+ computeUsesForBytecodeOffset(codeBlock, bytecodeOffset, setUses); >+ computeDefsForBytecodeOffset(codeBlock, bytecodeOffset, setDefs); > > out.exclude(defs); > out.merge(uses); >Index: Source/JavaScriptCore/bytecode/BytecodeUseDef.h >=================================================================== >--- Source/JavaScriptCore/bytecode/BytecodeUseDef.h (revision 0) >+++ Source/JavaScriptCore/bytecode/BytecodeUseDef.h (working copy) >@@ -0,0 +1,426 @@ >+/* >+ * Copyright (C) 2013 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. AND ITS CONTRIBUTORS ``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 ITS 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 BytecodeUseDef_h >+#define BytecodeUseDef_h >+ >+#include "CodeBlock.h" >+ >+namespace JSC { >+ >+template<typename Functor> >+void computeUsesForBytecodeOffset( >+ CodeBlock* codeBlock, unsigned bytecodeOffset, Functor& functor) >+{ >+ Interpreter* interpreter = codeBlock->vm()->interpreter; >+ Instruction* instructionsBegin = codeBlock->instructions().begin(); >+ Instruction* instruction = &instructionsBegin[bytecodeOffset]; >+ OpcodeID opcodeID = interpreter->getOpcodeID(instruction->u.opcode); >+ switch (opcodeID) { >+ // No uses. >+ case op_new_regexp: >+ case op_new_array_buffer: >+ case op_throw_static_error: >+ case op_debug: >+ case op_resolve_scope: >+ case op_pop_scope: >+ case op_jneq_ptr: >+ case op_new_func_exp: >+ case op_loop_hint: >+ case op_jmp: >+ case op_new_object: >+ case op_init_lazy_reg: >+ case op_get_callee: >+ case op_enter: >+ case op_catch: >+ return; >+ // First argument. >+ case op_new_func: >+ case op_create_activation: >+ case op_create_arguments: >+ case op_to_this: >+ case op_tear_off_activation: >+ case op_profile_will_call: >+ case op_profile_did_call: >+ case op_throw: >+ case op_push_with_scope: >+ case op_end: >+ case op_ret: >+ case op_jtrue: >+ case op_jfalse: >+ case op_jeq_null: >+ case op_jneq_null: >+ case op_dec: >+ case op_inc: { >+ functor(codeBlock, instruction, opcodeID, instruction[1].u.operand); >+ return; >+ } >+ // First and second arguments. >+ case op_ret_object_or_this: >+ case op_jlesseq: >+ case op_jgreater: >+ case op_jgreatereq: >+ case op_jnless: >+ case op_jnlesseq: >+ case op_jngreater: >+ case op_jngreatereq: >+ case op_jless: { >+ functor(codeBlock, instruction, opcodeID, instruction[1].u.operand); >+ functor(codeBlock, instruction, opcodeID, instruction[2].u.operand); >+ return; >+ } >+ // First, second, and third arguments. >+ case op_del_by_val: >+ case op_put_by_val_direct: >+ case op_put_by_val: { >+ functor(codeBlock, instruction, opcodeID, instruction[1].u.operand); >+ functor(codeBlock, instruction, opcodeID, instruction[2].u.operand); >+ functor(codeBlock, instruction, opcodeID, instruction[3].u.operand); >+ return; >+ } >+ // First and third arguments. >+ case op_put_by_index: >+ case op_put_by_id_replace: >+ case op_put_by_id_transition: >+ 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_put_by_id_generic: >+ case op_put_by_id_out_of_line: >+ case op_put_by_id: >+ case op_put_to_scope: { >+ functor(codeBlock, instruction, opcodeID, instruction[1].u.operand); >+ functor(codeBlock, instruction, opcodeID, instruction[3].u.operand); >+ return; >+ } >+ // First, third, and fourth arguments. >+ case op_put_getter_setter: { >+ functor(codeBlock, instruction, opcodeID, instruction[1].u.operand); >+ functor(codeBlock, instruction, opcodeID, instruction[3].u.operand); >+ functor(codeBlock, instruction, opcodeID, instruction[4].u.operand); >+ return; >+ } >+ // Second argument. >+ case op_init_global_const_nop: >+ case op_init_global_const: >+ case op_push_name_scope: >+ case op_get_from_scope: >+ case op_to_primitive: >+ case op_get_by_id: >+ case op_get_by_id_out_of_line: >+ case op_get_by_id_self: >+ case op_get_by_id_proto: >+ case op_get_by_id_chain: >+ case op_get_by_id_getter_self: >+ case op_get_by_id_getter_proto: >+ case op_get_by_id_getter_chain: >+ case op_get_by_id_custom_self: >+ case op_get_by_id_custom_proto: >+ case op_get_by_id_custom_chain: >+ case op_get_by_id_generic: >+ case op_get_array_length: >+ case op_get_string_length: >+ case op_get_arguments_length: >+ case op_typeof: >+ 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_to_number: >+ case op_negate: >+ case op_neq_null: >+ case op_eq_null: >+ case op_not: >+ case op_mov: >+ case op_captured_mov: >+ case op_new_array_with_size: >+ case op_create_this: >+ case op_get_pnames: >+ case op_del_by_id: { >+ functor(codeBlock, instruction, opcodeID, instruction[2].u.operand); >+ return; >+ } >+ // Second and third arguments. >+ case op_get_by_val: >+ case op_get_argument_by_val: >+ case op_in: >+ case op_instanceof: >+ case op_check_has_instance: >+ case op_add: >+ case op_mul: >+ case op_div: >+ case op_mod: >+ case op_sub: >+ case op_lshift: >+ case op_rshift: >+ case op_urshift: >+ case op_bitand: >+ case op_bitxor: >+ case op_bitor: >+ case op_less: >+ case op_lesseq: >+ case op_greater: >+ case op_greatereq: >+ case op_nstricteq: >+ case op_stricteq: >+ case op_neq: >+ case op_eq: { >+ functor(codeBlock, instruction, opcodeID, instruction[2].u.operand); >+ functor(codeBlock, instruction, opcodeID, instruction[3].u.operand); >+ return; >+ } >+ // Second, third, and fourth arguments. >+ case op_call_varargs: { >+ functor(codeBlock, instruction, opcodeID, instruction[2].u.operand); >+ functor(codeBlock, instruction, opcodeID, instruction[3].u.operand); >+ functor(codeBlock, instruction, opcodeID, instruction[4].u.operand); >+ return; >+ } >+ // Second, third, fourth, and fifth arguments. >+ case op_next_pname: { >+ functor(codeBlock, instruction, opcodeID, instruction[2].u.operand); >+ functor(codeBlock, instruction, opcodeID, instruction[3].u.operand); >+ functor(codeBlock, instruction, opcodeID, instruction[4].u.operand); >+ functor(codeBlock, instruction, opcodeID, instruction[5].u.operand); >+ return; >+ } >+ // Second, third, fourth, fifth, and sixth arguments. >+ case op_get_by_pname: { >+ functor(codeBlock, instruction, opcodeID, instruction[2].u.operand); >+ functor(codeBlock, instruction, opcodeID, instruction[3].u.operand); >+ functor(codeBlock, instruction, opcodeID, instruction[4].u.operand); >+ functor(codeBlock, instruction, opcodeID, instruction[5].u.operand); >+ functor(codeBlock, instruction, opcodeID, instruction[6].u.operand); >+ return; >+ } >+ // Third argument. >+ case op_switch_string: >+ case op_switch_char: >+ case op_switch_imm: { >+ functor(codeBlock, instruction, opcodeID, instruction[3].u.operand); >+ return; >+ } >+ // Variable number of arguments. >+ case op_new_array: >+ case op_strcat: { >+ int base = instruction[2].u.operand; >+ int count = instruction[3].u.operand; >+ for (int i = 0; i < count; i++) >+ functor(codeBlock, instruction, opcodeID, base - i); >+ return; >+ } >+ // Crazy stuff for calls. >+ case op_construct: >+ case op_call_eval: >+ case op_call: { >+ functor(codeBlock, instruction, opcodeID, instruction[2].u.operand); >+ int argCount = instruction[3].u.operand; >+ int registerOffset = -instruction[4].u.operand; >+ int lastArg = registerOffset + CallFrame::thisArgumentOffset(); >+ for (int i = opcodeID == op_construct ? 1 : 0; i < argCount; i++) >+ functor(codeBlock, instruction, opcodeID, lastArg + i); >+ return; >+ } >+ // Special stuff for tear off arguments. >+ case op_tear_off_arguments: { >+ functor(codeBlock, instruction, opcodeID, instruction[1].u.operand); >+ functor(codeBlock, instruction, opcodeID, unmodifiedArgumentsRegister(VirtualRegister(instruction[1].u.operand)).offset()); >+ functor(codeBlock, instruction, opcodeID, instruction[2].u.operand); >+ return; >+ } >+ default: >+ RELEASE_ASSERT_NOT_REACHED(); >+ break; >+ } >+} >+ >+template<typename Functor> >+void computeDefsForBytecodeOffset(CodeBlock* codeBlock, unsigned bytecodeOffset, Functor& functor) >+{ >+ Interpreter* interpreter = codeBlock->vm()->interpreter; >+ Instruction* instructionsBegin = codeBlock->instructions().begin(); >+ Instruction* instruction = &instructionsBegin[bytecodeOffset]; >+ OpcodeID opcodeID = interpreter->getOpcodeID(instruction->u.opcode); >+ switch (opcodeID) { >+ // These don't define anything. >+ case op_init_global_const: >+ case op_init_global_const_nop: >+ case op_push_name_scope: >+ case op_push_with_scope: >+ case op_put_to_scope: >+ case op_pop_scope: >+ case op_end: >+ case op_profile_will_call: >+ case op_profile_did_call: >+ case op_throw: >+ case op_throw_static_error: >+ case op_debug: >+ case op_ret: >+ case op_ret_object_or_this: >+ case op_jmp: >+ case op_jtrue: >+ case op_jfalse: >+ case op_jeq_null: >+ case op_jneq_null: >+ case op_jneq_ptr: >+ 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_switch_imm: >+ case op_switch_char: >+ case op_switch_string: >+ case op_put_by_id: >+ case op_put_by_id_out_of_line: >+ case op_put_by_id_replace: >+ case op_put_by_id_transition: >+ 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_put_by_id_generic: >+ case op_put_getter_setter: >+ case op_put_by_val: >+ case op_put_by_val_direct: >+ case op_put_by_index: >+ case op_del_by_val: >+#define LLINT_HELPER_OPCODES(opcode, length) case opcode: >+ FOR_EACH_LLINT_OPCODE_EXTENSION(LLINT_HELPER_OPCODES); >+#undef LLINT_HELPER_OPCODES >+ return; >+ // These all have a single destination for the first argument. >+ case op_next_pname: >+ case op_resolve_scope: >+ case op_strcat: >+ case op_tear_off_activation: >+ case op_to_primitive: >+ case op_catch: >+ case op_create_this: >+ case op_new_array: >+ case op_new_array_buffer: >+ case op_new_array_with_size: >+ case op_new_regexp: >+ case op_new_func: >+ case op_new_func_exp: >+ case op_call_varargs: >+ case op_get_from_scope: >+ case op_call: >+ case op_call_eval: >+ case op_construct: >+ case op_get_by_id: >+ case op_get_by_id_out_of_line: >+ case op_get_by_id_self: >+ case op_get_by_id_proto: >+ case op_get_by_id_chain: >+ case op_get_by_id_getter_self: >+ case op_get_by_id_getter_proto: >+ case op_get_by_id_getter_chain: >+ case op_get_by_id_custom_self: >+ case op_get_by_id_custom_proto: >+ case op_get_by_id_custom_chain: >+ case op_get_by_id_generic: >+ case op_get_array_length: >+ case op_get_string_length: >+ case op_check_has_instance: >+ case op_instanceof: >+ case op_get_by_val: >+ case op_get_argument_by_val: >+ case op_get_by_pname: >+ case op_get_arguments_length: >+ case op_typeof: >+ 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_in: >+ case op_to_number: >+ case op_negate: >+ case op_add: >+ case op_mul: >+ case op_div: >+ case op_mod: >+ case op_sub: >+ case op_lshift: >+ case op_rshift: >+ case op_urshift: >+ case op_bitand: >+ case op_bitxor: >+ case op_bitor: >+ case op_inc: >+ case op_dec: >+ case op_eq: >+ case op_neq: >+ case op_stricteq: >+ case op_nstricteq: >+ case op_less: >+ case op_lesseq: >+ case op_greater: >+ case op_greatereq: >+ case op_neq_null: >+ case op_eq_null: >+ case op_not: >+ case op_mov: >+ case op_captured_mov: >+ case op_new_object: >+ case op_to_this: >+ case op_get_callee: >+ case op_init_lazy_reg: >+ case op_create_activation: >+ case op_create_arguments: >+ case op_del_by_id: { >+ functor(codeBlock, instruction, opcodeID, instruction[1].u.operand); >+ return; >+ } >+ case op_get_pnames: { >+ functor(codeBlock, instruction, opcodeID, instruction[1].u.operand); >+ functor(codeBlock, instruction, opcodeID, instruction[3].u.operand); >+ functor(codeBlock, instruction, opcodeID, instruction[4].u.operand); >+ return; >+ } >+ case op_tear_off_arguments: { >+ functor(codeBlock, instruction, opcodeID, instruction[1].u.operand - 1); >+ return; >+ } >+ case op_enter: { >+ for (unsigned i = codeBlock->m_numVars; i--;) >+ functor(codeBlock, instruction, opcodeID, virtualRegisterForLocal(i).offset()); >+ return; >+ } } >+} >+ >+} // namespace JSC >+ >+#endif // BytecodeUseDef_h >+ >Index: Source/JavaScriptCore/bytecode/CodeBlock.cpp >=================================================================== >--- Source/JavaScriptCore/bytecode/CodeBlock.cpp (revision 159882) >+++ Source/JavaScriptCore/bytecode/CodeBlock.cpp (working copy) >@@ -759,6 +759,13 @@ void CodeBlock::dumpBytecode(PrintStream > out.printf("%s, %s", registerName(r0).data(), registerName(r1).data()); > break; > } >+ case op_captured_mov: { >+ int r0 = (++it)->u.operand; >+ int r1 = (++it)->u.operand; >+ printLocationAndOp(out, exec, location, it, "captured_mov"); >+ out.printf("%s, %s", registerName(r0).data(), registerName(r1).data()); >+ break; >+ } > case op_not: { > printUnaryOp(out, exec, location, it, "not"); > break; >@@ -2469,8 +2476,7 @@ bool CodeBlock::isCaptured(VirtualRegist > if (!symbolTable()) > return false; > >- return operand.offset() <= symbolTable()->captureStart() >- && operand.offset() > symbolTable()->captureEnd(); >+ return symbolTable()->isCaptured(operand.offset()); > } > > int CodeBlock::framePointerOffsetToGetActivationRegisters(int machineCaptureStart) >Index: Source/JavaScriptCore/bytecode/Opcode.h >=================================================================== >--- Source/JavaScriptCore/bytecode/Opcode.h (revision 159882) >+++ Source/JavaScriptCore/bytecode/Opcode.h (working copy) >@@ -54,6 +54,7 @@ namespace JSC { > macro(op_new_array_buffer, 5) \ > macro(op_new_regexp, 3) \ > macro(op_mov, 3) \ >+ macro(op_captured_mov, 3) \ > \ > macro(op_not, 3) \ > macro(op_eq, 4) \ >Index: Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp >=================================================================== >--- Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (revision 159882) >+++ Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (working copy) >@@ -1007,6 +1007,16 @@ RegisterID* BytecodeGenerator::emitMove( > return dst; > } > >+RegisterID* BytecodeGenerator::emitCapturedMove(RegisterID* dst, RegisterID* src) >+{ >+ m_staticPropertyAnalyzer.mov(dst->index(), src->index()); >+ >+ emitOpcode(op_captured_mov); >+ instructions().append(dst->index()); >+ instructions().append(src->index()); >+ return dst; >+} >+ > RegisterID* BytecodeGenerator::emitUnaryOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src) > { > emitOpcode(opcodeID); >@@ -1157,11 +1167,17 @@ RegisterID* BytecodeGenerator::emitLoadG > return m_globalObjectRegister; > } > >+bool BytecodeGenerator::isCaptured(int operand) >+{ >+ return (m_codeBlock->usesArguments() && VirtualRegister(operand).isArgument()) >+ || symbolTable().isCaptured(operand); >+} >+ > Local BytecodeGenerator::local(const Identifier& property) > { > if (property == propertyNames().thisIdentifier) >- return Local(thisRegister(), ReadOnly); >- >+ return Local(thisRegister(), ReadOnly, false); >+ > if (property == propertyNames().arguments) > createArgumentsIfNecessary(); > >@@ -1173,7 +1189,7 @@ Local BytecodeGenerator::local(const Ide > return Local(); > > RegisterID* local = createLazyRegisterIfNecessary(®isterFor(entry.getIndex())); >- return Local(local, entry.getAttributes()); >+ return Local(local, entry.getAttributes(), isCaptured(local->index())); > } > > Local BytecodeGenerator::constLocal(const Identifier& property) >@@ -1186,7 +1202,7 @@ Local BytecodeGenerator::constLocal(cons > return Local(); > > RegisterID* local = createLazyRegisterIfNecessary(®isterFor(entry.getIndex())); >- return Local(local, entry.getAttributes()); >+ return Local(local, entry.getAttributes(), isCaptured(local->index())); > } > > void BytecodeGenerator::emitCheckHasInstance(RegisterID* dst, RegisterID* value, RegisterID* base, Label* target) >Index: Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h >=================================================================== >--- Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h (revision 159882) >+++ Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h (working copy) >@@ -122,9 +122,10 @@ namespace JSC { > { > } > >- Local(RegisterID* local, unsigned attributes) >+ Local(RegisterID* local, unsigned attributes, bool isCaptured) > : m_local(local) > , m_attributes(attributes) >+ , m_isCaptured(isCaptured) > { > } > >@@ -133,10 +134,13 @@ namespace JSC { > RegisterID* get() { return m_local; } > > bool isReadOnly() { return m_attributes & ReadOnly; } >+ >+ bool isCaptured() { return m_isCaptured; } > > private: > RegisterID* m_local; > unsigned m_attributes; >+ bool m_isCaptured; > }; > > struct TryRange { >@@ -171,6 +175,8 @@ namespace JSC { > bool willResolveToArguments(const Identifier&); > RegisterID* uncheckedRegisterForArguments(); > >+ bool isCaptured(int operand); >+ > Local local(const Identifier&); > Local constLocal(const Identifier&); > >@@ -336,6 +342,7 @@ namespace JSC { > RegisterID* emitNewRegExp(RegisterID* dst, RegExp*); > > RegisterID* emitMove(RegisterID* dst, RegisterID* src); >+ RegisterID* emitCapturedMove(RegisterID* dst, RegisterID* src); > > RegisterID* emitToNumber(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_to_number, dst, src); } > RegisterID* emitInc(RegisterID* srcDst); >Index: Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp >=================================================================== >--- Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp (revision 159882) >+++ Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp (working copy) >@@ -673,11 +673,12 @@ RegisterID* PostfixNode::emitResolve(Byt > const Identifier& ident = resolve->identifier(); > > if (Local local = generator.local(ident)) { >+ RegisterID* localReg = local.get(); > if (local.isReadOnly()) { > generator.emitReadOnlyExceptionIfNeeded(); >- local = Local(generator.emitMove(generator.tempDestination(dst), local.get()), 0); >+ localReg = generator.emitMove(generator.tempDestination(dst), localReg); > } >- return emitPostIncOrDec(generator, generator.finalDestination(dst), local.get(), m_operator); >+ return emitPostIncOrDec(generator, generator.finalDestination(dst), localReg, m_operator); > } > > generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); >@@ -838,12 +839,13 @@ RegisterID* PrefixNode::emitResolve(Byte > const Identifier& ident = resolve->identifier(); > > if (Local local = generator.local(ident)) { >+ RegisterID* localReg = local.get(); > if (local.isReadOnly()) { > generator.emitReadOnlyExceptionIfNeeded(); >- local = Local(generator.emitMove(generator.tempDestination(dst), local.get()), 0); >+ localReg = generator.emitMove(generator.tempDestination(dst), localReg); > } >- emitIncOrDec(generator, local.get(), m_operator); >- return generator.moveToDestinationIfNeeded(dst, local.get()); >+ emitIncOrDec(generator, localReg, m_operator); >+ return generator.moveToDestinationIfNeeded(dst, localReg); > } > > generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); >Index: Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (revision 159882) >+++ Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (working copy) >@@ -2188,7 +2188,8 @@ bool ByteCodeParser::parseBlock(unsigned > addToGraph(Breakpoint); > NEXT_OPCODE(op_debug); > #endif >- case op_mov: { >+ case op_mov: >+ case op_captured_mov: { > Node* op = get(VirtualRegister(currentInstruction[2].u.operand)); > set(VirtualRegister(currentInstruction[1].u.operand), op); > NEXT_OPCODE(op_mov); >Index: Source/JavaScriptCore/dfg/DFGCapabilities.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGCapabilities.cpp (revision 159882) >+++ Source/JavaScriptCore/dfg/DFGCapabilities.cpp (working copy) >@@ -102,6 +102,7 @@ CapabilityLevel capabilityLevel(OpcodeID > case op_debug: > #endif > case op_mov: >+ case op_captured_mov: > case op_check_has_instance: > case op_instanceof: > case op_is_undefined: >Index: Source/JavaScriptCore/jit/JIT.cpp >=================================================================== >--- Source/JavaScriptCore/jit/JIT.cpp (revision 159882) >+++ Source/JavaScriptCore/jit/JIT.cpp (working copy) >@@ -250,6 +250,7 @@ void JIT::privateCompileMainPass() > DEFINE_OP(op_loop_hint) > DEFINE_OP(op_lshift) > DEFINE_OP(op_mod) >+ case op_captured_mov: > DEFINE_OP(op_mov) > DEFINE_OP(op_mul) > DEFINE_OP(op_negate) >Index: Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm >=================================================================== >--- Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm (revision 159882) >+++ Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm (working copy) >@@ -542,6 +542,16 @@ _llint_op_mov: > dispatch(3) > > >+_llint_op_captured_mov: >+ traceExecution() >+ loadi 8[PC], t1 >+ loadi 4[PC], t0 >+ loadConstantOrVariable(t1, t2, t3) >+ storei t2, TagOffset[cfr, t0, 8] >+ storei t3, PayloadOffset[cfr, t0, 8] >+ dispatch(3) >+ >+ > _llint_op_not: > traceExecution() > loadi 8[PC], t0 >Index: Source/JavaScriptCore/llint/LowLevelInterpreter64.asm >=================================================================== >--- Source/JavaScriptCore/llint/LowLevelInterpreter64.asm (revision 159882) >+++ Source/JavaScriptCore/llint/LowLevelInterpreter64.asm (working copy) >@@ -418,6 +418,15 @@ _llint_op_mov: > dispatch(3) > > >+_llint_op_captured_mov: >+ traceExecution() >+ loadisFromInstruction(2, t1) >+ loadisFromInstruction(1, t0) >+ loadConstantOrVariable(t1, t2) >+ storeq t2, [cfr, t0, 8] >+ dispatch(3) >+ >+ > _llint_op_not: > traceExecution() > loadisFromInstruction(2, t0) >Index: Source/JavaScriptCore/runtime/SymbolTable.h >=================================================================== >--- Source/JavaScriptCore/runtime/SymbolTable.h (revision 159882) >+++ Source/JavaScriptCore/runtime/SymbolTable.h (working copy) >@@ -453,6 +453,11 @@ public: > void setCaptureEnd(int captureEnd) { m_captureEnd = captureEnd; } > > int captureCount() const { return -(m_captureEnd - m_captureStart); } >+ >+ bool isCaptured(int operand) >+ { >+ return operand <= captureStart() && operand > captureEnd(); >+ } > > int parameterCount() { return m_parameterCountIncludingThis - 1; } > int parameterCountIncludingThis() { return m_parameterCountIncludingThis; }
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 124883
:
217863
|
218084
|
218113
|
218117
|
218119
|
218121