]>
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 | ||
29 | namespace JSC { | |
30 | ||
31 | static void addSimpleSwitchTargets(SimpleJumpTable& jumpTable, unsigned bytecodeOffset, Vector<unsigned, 32>& out) | |
32 | { | |
33 | for (unsigned i = jumpTable.branchOffsets.size(); i--;) | |
34 | out.append(bytecodeOffset + jumpTable.branchOffsets[i]); | |
35 | } | |
36 | ||
37 | void computePreciseJumpTargets(CodeBlock* codeBlock, Vector<unsigned, 32>& out) | |
38 | { | |
39 | ASSERT(out.isEmpty()); | |
40 | ||
41 | // We will derive a superset of the jump targets that the code block thinks it has. | |
42 | // So, if the code block claims there are none, then we are done. | |
43 | if (!codeBlock->numberOfJumpTargets()) | |
44 | return; | |
45 | ||
46 | for (unsigned i = codeBlock->numberOfExceptionHandlers(); i--;) | |
47 | out.append(codeBlock->exceptionHandler(i).target); | |
48 | ||
49 | Interpreter* interpreter = codeBlock->vm()->interpreter; | |
50 | Instruction* instructionsBegin = codeBlock->instructions().begin(); | |
51 | unsigned instructionCount = codeBlock->instructions().size(); | |
52 | for (unsigned bytecodeOffset = 0; bytecodeOffset < instructionCount;) { | |
53 | OpcodeID opcodeID = interpreter->getOpcodeID(instructionsBegin[bytecodeOffset].u.opcode); | |
54 | Instruction* current = instructionsBegin + bytecodeOffset; | |
55 | switch (opcodeID) { | |
56 | case op_jmp: | |
57 | out.append(bytecodeOffset + current[1].u.operand); | |
58 | break; | |
59 | case op_jtrue: | |
60 | case op_jfalse: | |
61 | case op_jeq_null: | |
62 | case op_jneq_null: | |
63 | out.append(bytecodeOffset + current[2].u.operand); | |
64 | break; | |
65 | case op_jneq_ptr: | |
66 | case op_jless: | |
67 | case op_jlesseq: | |
68 | case op_jgreater: | |
69 | case op_jgreatereq: | |
70 | case op_jnless: | |
71 | case op_jnlesseq: | |
72 | case op_jngreater: | |
73 | case op_jngreatereq: | |
74 | out.append(bytecodeOffset + current[3].u.operand); | |
75 | break; | |
76 | case op_switch_imm: | |
77 | addSimpleSwitchTargets(codeBlock->immediateSwitchJumpTable(current[1].u.operand), bytecodeOffset, out); | |
78 | out.append(bytecodeOffset + current[2].u.operand); | |
79 | break; | |
80 | case op_switch_char: | |
81 | addSimpleSwitchTargets(codeBlock->characterSwitchJumpTable(current[1].u.operand), bytecodeOffset, out); | |
82 | out.append(bytecodeOffset + current[2].u.operand); | |
83 | break; | |
84 | case op_switch_string: { | |
85 | StringJumpTable& table = codeBlock->stringSwitchJumpTable(current[1].u.operand); | |
86 | StringJumpTable::StringOffsetTable::iterator iter = table.offsetTable.begin(); | |
87 | StringJumpTable::StringOffsetTable::iterator end = table.offsetTable.end(); | |
88 | for (; iter != end; ++iter) | |
89 | out.append(bytecodeOffset + iter->value.branchOffset); | |
90 | out.append(bytecodeOffset + current[2].u.operand); | |
91 | break; | |
92 | } | |
93 | case op_get_pnames: | |
94 | out.append(bytecodeOffset + current[5].u.operand); | |
95 | break; | |
96 | case op_next_pname: | |
97 | out.append(bytecodeOffset + current[6].u.operand); | |
98 | break; | |
99 | case op_check_has_instance: | |
100 | out.append(bytecodeOffset + current[4].u.operand); | |
101 | break; | |
102 | case op_loop_hint: | |
103 | out.append(bytecodeOffset); | |
104 | break; | |
105 | default: | |
106 | break; | |
107 | } | |
108 | bytecodeOffset += opcodeLengths[opcodeID]; | |
109 | } | |
110 | ||
111 | std::sort(out.begin(), out.end()); | |
112 | ||
113 | // We will have duplicates, and we must remove them. | |
114 | unsigned toIndex = 0; | |
115 | unsigned fromIndex = 0; | |
116 | unsigned lastValue = UINT_MAX; | |
117 | while (fromIndex < out.size()) { | |
118 | unsigned value = out[fromIndex++]; | |
119 | if (value == lastValue) | |
120 | continue; | |
121 | out[toIndex++] = value; | |
122 | lastValue = value; | |
123 | } | |
124 | out.resize(toIndex); | |
125 | } | |
126 | ||
127 | } // namespace JSC | |
128 |