]> git.saurik.com Git - apple/javascriptcore.git/blame - bytecode/PreciseJumpTargets.cpp
JavaScriptCore-1218.35.tar.gz
[apple/javascriptcore.git] / bytecode / PreciseJumpTargets.cpp
CommitLineData
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
29namespace JSC {
30
31static 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
37void 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