1/*
2 * Copyright (C) 2008, 2009, 2013, 2014 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1.  Redistributions of source code must retain the above copyright
10 *     notice, this list of conditions and the following disclaimer.
11 * 2.  Redistributions in binary form must reproduce the above copyright
12 *     notice, this list of conditions and the following disclaimer in the
13 *     documentation and/or other materials provided with the distribution.
14 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
15 *     its contributors may be used to endorse or promote products derived
16 *     from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#ifndef Opcode_h
31#define Opcode_h
32
33#include "Bytecodes.h"
34#include "LLIntOpcode.h"
35
36#include <algorithm>
37#include <string.h>
38
39#include <wtf/Assertions.h>
40
41namespace JSC {
42
43#define FOR_EACH_CORE_OPCODE_ID_WITH_EXTENSION(macro, extension__) \
44    FOR_EACH_BYTECODE_ID(macro) \
45    extension__
46
47#define FOR_EACH_CORE_OPCODE_ID(macro) \
48    FOR_EACH_CORE_OPCODE_ID_WITH_EXTENSION(macro, /* No extension */ )
49
50#define FOR_EACH_OPCODE_ID(macro) \
51    FOR_EACH_CORE_OPCODE_ID_WITH_EXTENSION( \
52        macro, \
53        FOR_EACH_LLINT_OPCODE_EXTENSION(macro) \
54    )
55
56
57#define OPCODE_ID_ENUM(opcode, length) opcode,
58    typedef enum { FOR_EACH_OPCODE_ID(OPCODE_ID_ENUM) } OpcodeID;
59#undef OPCODE_ID_ENUM
60
61const int maxOpcodeLength = 9;
62#if !ENABLE(JIT)
63const int numOpcodeIDs = NUMBER_OF_BYTECODE_IDS + NUMBER_OF_CLOOP_BYTECODE_HELPER_IDS + NUMBER_OF_BYTECODE_HELPER_IDS;
64#else
65const int numOpcodeIDs = NUMBER_OF_BYTECODE_IDS + NUMBER_OF_BYTECODE_HELPER_IDS;
66#endif
67
68#define OPCODE_ID_LENGTHS(id, length) const int id##_length = length;
69    FOR_EACH_OPCODE_ID(OPCODE_ID_LENGTHS);
70#undef OPCODE_ID_LENGTHS
71
72#define OPCODE_LENGTH(opcode) opcode##_length
73
74#define OPCODE_ID_LENGTH_MAP(opcode, length) length,
75    const int opcodeLengths[numOpcodeIDs] = { FOR_EACH_OPCODE_ID(OPCODE_ID_LENGTH_MAP) };
76#undef OPCODE_ID_LENGTH_MAP
77
78#define VERIFY_OPCODE_ID(id, size) COMPILE_ASSERT(id <= numOpcodeIDs, ASSERT_THAT_JS_OPCODE_IDS_ARE_VALID);
79    FOR_EACH_OPCODE_ID(VERIFY_OPCODE_ID);
80#undef VERIFY_OPCODE_ID
81
82#if ENABLE(COMPUTED_GOTO_OPCODES)
83typedef void* Opcode;
84#else
85typedef OpcodeID Opcode;
86#endif
87
88#define PADDING_STRING "                                "
89#define PADDING_STRING_LENGTH static_cast<unsigned>(strlen(PADDING_STRING))
90
91extern const char* const opcodeNames[];
92
93inline const char* padOpcodeName(OpcodeID op, unsigned width)
94{
95    unsigned pad = width - strlen(opcodeNames[op]);
96    pad = std::min(pad, PADDING_STRING_LENGTH);
97    return PADDING_STRING + PADDING_STRING_LENGTH - pad;
98}
99
100#undef PADDING_STRING_LENGTH
101#undef PADDING_STRING
102
103#if ENABLE(OPCODE_STATS)
104
105struct OpcodeStats {
106    OpcodeStats();
107    ~OpcodeStats();
108    static long long opcodeCounts[numOpcodeIDs];
109    static long long opcodePairCounts[numOpcodeIDs][numOpcodeIDs];
110    static int lastOpcode;
111
112    static void recordInstruction(int opcode);
113    static void resetLastInstruction();
114};
115
116#endif
117
118inline size_t opcodeLength(OpcodeID opcode)
119{
120    switch (opcode) {
121#define OPCODE_ID_LENGTHS(id, length) case id: return OPCODE_LENGTH(id);
122         FOR_EACH_OPCODE_ID(OPCODE_ID_LENGTHS)
123#undef OPCODE_ID_LENGTHS
124    }
125    RELEASE_ASSERT_NOT_REACHED();
126    return 0;
127}
128
129} // namespace JSC
130
131#endif // Opcode_h
132