]>
Commit | Line | Data |
---|---|---|
93a37866 A |
1 | /* |
2 | * Copyright (C) 2013 Apple Inc. All rights reserved. | |
3 | * | |
4 | * Redistribution and use in source and binary forms, with or without | |
5 | * modification, are permitted provided that the following conditions | |
6 | * are met: | |
7 | * 1. Redistributions of source code must retain the above copyright | |
8 | * notice, this list of conditions and the following disclaimer. | |
9 | * 2. Redistributions in binary form must reproduce the above copyright | |
10 | * notice, this list of conditions and the following disclaimer in the | |
11 | * documentation and/or other materials provided with the distribution. | |
12 | * | |
13 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY | |
14 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR | |
17 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
18 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
20 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | |
21 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
23 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | */ | |
25 | ||
26 | #include "config.h" | |
27 | #include "PreciseJumpTargets.h" | |
28 | ||
81345200 A |
29 | #include "JSCInlines.h" |
30 | ||
93a37866 A |
31 | namespace JSC { |
32 | ||
81345200 A |
33 | template <size_t vectorSize> |
34 | static void getJumpTargetsForBytecodeOffset(CodeBlock* codeBlock, Interpreter* interpreter, Instruction* instructionsBegin, unsigned bytecodeOffset, Vector<unsigned, vectorSize>& out) | |
93a37866 | 35 | { |
81345200 A |
36 | OpcodeID opcodeID = interpreter->getOpcodeID(instructionsBegin[bytecodeOffset].u.opcode); |
37 | Instruction* current = instructionsBegin + bytecodeOffset; | |
38 | switch (opcodeID) { | |
39 | case op_jmp: | |
40 | out.append(bytecodeOffset + current[1].u.operand); | |
41 | break; | |
42 | case op_jtrue: | |
43 | case op_jfalse: | |
44 | case op_jeq_null: | |
45 | case op_jneq_null: | |
46 | out.append(bytecodeOffset + current[2].u.operand); | |
47 | break; | |
48 | case op_jneq_ptr: | |
49 | case op_jless: | |
50 | case op_jlesseq: | |
51 | case op_jgreater: | |
52 | case op_jgreatereq: | |
53 | case op_jnless: | |
54 | case op_jnlesseq: | |
55 | case op_jngreater: | |
56 | case op_jngreatereq: | |
57 | out.append(bytecodeOffset + current[3].u.operand); | |
58 | break; | |
59 | case op_switch_imm: | |
60 | case op_switch_char: { | |
61 | SimpleJumpTable& table = codeBlock->switchJumpTable(current[1].u.operand); | |
62 | for (unsigned i = table.branchOffsets.size(); i--;) | |
63 | out.append(bytecodeOffset + table.branchOffsets[i]); | |
64 | out.append(bytecodeOffset + current[2].u.operand); | |
65 | break; | |
66 | } | |
67 | case op_switch_string: { | |
68 | StringJumpTable& table = codeBlock->stringSwitchJumpTable(current[1].u.operand); | |
69 | StringJumpTable::StringOffsetTable::iterator iter = table.offsetTable.begin(); | |
70 | StringJumpTable::StringOffsetTable::iterator end = table.offsetTable.end(); | |
71 | for (; iter != end; ++iter) | |
72 | out.append(bytecodeOffset + iter->value.branchOffset); | |
73 | out.append(bytecodeOffset + current[2].u.operand); | |
74 | break; | |
75 | } | |
76 | case op_get_pnames: | |
77 | out.append(bytecodeOffset + current[5].u.operand); | |
78 | break; | |
79 | case op_next_pname: | |
80 | out.append(bytecodeOffset + current[6].u.operand); | |
81 | break; | |
82 | case op_check_has_instance: | |
83 | out.append(bytecodeOffset + current[4].u.operand); | |
84 | break; | |
85 | case op_loop_hint: | |
86 | out.append(bytecodeOffset); | |
87 | break; | |
88 | default: | |
89 | break; | |
90 | } | |
93a37866 A |
91 | } |
92 | ||
93 | void computePreciseJumpTargets(CodeBlock* codeBlock, Vector<unsigned, 32>& out) | |
94 | { | |
95 | ASSERT(out.isEmpty()); | |
96 | ||
97 | // We will derive a superset of the jump targets that the code block thinks it has. | |
98 | // So, if the code block claims there are none, then we are done. | |
99 | if (!codeBlock->numberOfJumpTargets()) | |
100 | return; | |
101 | ||
102 | for (unsigned i = codeBlock->numberOfExceptionHandlers(); i--;) | |
103 | out.append(codeBlock->exceptionHandler(i).target); | |
104 | ||
105 | Interpreter* interpreter = codeBlock->vm()->interpreter; | |
106 | Instruction* instructionsBegin = codeBlock->instructions().begin(); | |
107 | unsigned instructionCount = codeBlock->instructions().size(); | |
108 | for (unsigned bytecodeOffset = 0; bytecodeOffset < instructionCount;) { | |
109 | OpcodeID opcodeID = interpreter->getOpcodeID(instructionsBegin[bytecodeOffset].u.opcode); | |
81345200 | 110 | getJumpTargetsForBytecodeOffset(codeBlock, interpreter, instructionsBegin, bytecodeOffset, out); |
93a37866 A |
111 | bytecodeOffset += opcodeLengths[opcodeID]; |
112 | } | |
113 | ||
114 | std::sort(out.begin(), out.end()); | |
115 | ||
116 | // We will have duplicates, and we must remove them. | |
117 | unsigned toIndex = 0; | |
118 | unsigned fromIndex = 0; | |
119 | unsigned lastValue = UINT_MAX; | |
120 | while (fromIndex < out.size()) { | |
121 | unsigned value = out[fromIndex++]; | |
122 | if (value == lastValue) | |
123 | continue; | |
124 | out[toIndex++] = value; | |
125 | lastValue = value; | |
126 | } | |
127 | out.resize(toIndex); | |
128 | } | |
129 | ||
81345200 A |
130 | void findJumpTargetsForBytecodeOffset(CodeBlock* codeBlock, unsigned bytecodeOffset, Vector<unsigned, 1>& out) |
131 | { | |
132 | Interpreter* interpreter = codeBlock->vm()->interpreter; | |
133 | Instruction* instructionsBegin = codeBlock->instructions().begin(); | |
134 | getJumpTargetsForBytecodeOffset(codeBlock, interpreter, instructionsBegin, bytecodeOffset, out); | |
135 | } | |
136 | ||
93a37866 A |
137 | } // namespace JSC |
138 |