/*******************************************************************************1* Copyright (c) 2001, 2019 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception20*******************************************************************************/2122/*23* Cursor.hpp24*/2526#ifndef CURSOR_HPP_27#define CURSOR_HPP_2829/* @ddr_namespace: default */30#include "j9comp.h"31#include "j9.h"32#include "SRPOffsetTable.hpp"33#include "ROMClassCreationContext.hpp"3435class Cursor36{37public:3839/*40* DataType is used to identify the type of data being written.41*/42enum DataType {43// Actual bytecodes44BYTECODE,45// Generic non-specific data46GENERIC,47// The romSize field of the J9ROMClass structure48ROM_SIZE,49// The size of debug information store in a ROMMethod50METHOD_DEBUG_SIZE,51// Self Relative Pointer (SRP) to non-specific data52SRP_TO_GENERIC,53// SRP to a UTF8 string54SRP_TO_UTF8,55// SRP to a Name and Signature structure56SRP_TO_NAME_AND_SIGNATURE,57// Class file bytes58INTERMEDIATE_CLASS_DATA,59// Class file bytes size60INTERMEDIATE_CLASS_DATA_LENGTH,61// SRP to a method debug data62SRP_TO_DEBUG_DATA,63// Optional flags for ROMClass64OPTIONAL_FLAGS,65// SRP to source debug extension information66SRP_TO_SOURCE_DEBUG_EXT,67// The length of source debug extension information68SOURCE_DEBUG_EXT_LENGTH,69// The source debug extension information70SOURCE_DEBUG_EXT_DATA,71// Optional file name information72OPTINFO_SOURCE_FILE_NAME,73// All the class modiers74ROM_CLASS_MODIFIERS,75// Line number data for a rom class method76LINE_NUMBER_DATA,77// Number of local variables78LOCAL_VARIABLE_COUNT,79//SRP to local variable data start80SRP_TO_LOCAL_VARIABLE_DATA,81// Local variable data82LOCAL_VARIABLE_DATA,83// Local variable data SRP to UTF8 data84LOCAL_VARIABLE_DATA_SRP_TO_UTF8,85// SRP to intermediate class data86SRP_TO_INTERMEDIATE_CLASS_DATA,87// SRP to UTF8 string for class names88SRP_TO_UTF8_CLASS_NAME,89// Class File Size90CLASS_FILE_SIZE91};9293/*94* Mode is used to indicate the transition from one cursor type95* to another. This feature was specifically added to enable96* the comparison of ROMClass that had debug information out of line.97*98* This was required to support the ComparingCursor and ComparingCursorHelper model.99*/100enum Mode {101// In the mainline of the ROMClass102MAIN_CURSOR,103// Writing debug information and line number data104DEBUG_INFO,105// Writing variable information106VAR_INFO107};108109Cursor(UDATA tag, SRPOffsetTable *srpOffsetTable, ROMClassCreationContext * context) :110_srpOffsetTable(srpOffsetTable),111_count(0),112_tag(tag),113_context(context),114/* assign -1 to be able to check if it was initialized or not */115_classNameIndex((U_16)-1)116{117}118119virtual UDATA getCount() { return _count; }120121/* Note: WritingCursor's versions of the methods below do not call these ones for122* performance reasons on Linux PPC (since XLC fails to inline them). If you make123* a change that needs to affect WritingCursor, you must change those versions too.124*/125virtual void writeU8(U_8 u8Value, DataType dataType) { _count += sizeof(U_8); }126virtual void writeU16(U_16 u16Value, DataType dataType) { _count += sizeof(U_16); }127virtual void writeU32(U_32 u32Value, DataType dataType) { _count += sizeof(U_32); }128virtual void writeU64(U_32 u32ValueHigh, U_32 u32ValueLow, DataType dataType) { _count += sizeof(U_64); }129virtual void writeUTF8(U_8* utf8Data, U_16 utf8Length, DataType dataType)130{131writeU16(utf8Length, Cursor::GENERIC);132writeData(utf8Data, utf8Length, Cursor::GENERIC);133/* Pad manually as it is significantly faster than using padToAlignment(). */134if (0 != (utf8Length & 1)) {135writeU8(0, Cursor::GENERIC);136}137}138virtual void writeData(U_8* bytes, UDATA length, DataType dataType) { _count += length; }139virtual void padToAlignment(UDATA byteAlignment, DataType dataType) {140/* Note: byteAlignment must be a power of 2. */141UDATA alignmentBits = (byteAlignment - 1);142UDATA adjustedCount = (_count + alignmentBits) & ~alignmentBits;143UDATA bytesToPad = adjustedCount - _count;144145if (0 != bytesToPad) {146_count += bytesToPad;147}148}149virtual void skip(UDATA byteCount, DataType dataType = Cursor::GENERIC) { _count += byteCount; }150virtual U_32 peekU32() { return 0; }151virtual void notifyDebugDataWriteStart() { /* do nothing */ }152virtual void notifyVariableTableWriteEnd() { /* do nothing */ }153virtual void notifyDebugDataWriteEnd() { /* do nothing */ }154155/*156* write(W)SRP will write a NULL SRP if srpKey has not been marked with mark(srpKey)157*/158virtual void writeSRP(UDATA srpKey, DataType dataType) { _count += sizeof(J9SRP); }159virtual void writeWSRP(UDATA srpKey, DataType dataType) { _count += sizeof(J9WSRP); }160virtual void mark(UDATA srpKey) { _srpOffsetTable->insert(srpKey, _count, _tag); }161162#ifdef J9VM_ENV_LITTLE_ENDIAN163void writeBigEndianU16(U_16 u16Value, DataType dataType) { writeU16(swapU16(u16Value), dataType); }164#else165void writeBigEndianU16(U_16 u16Value, DataType dataType) { writeU16(u16Value, dataType); }166#endif167168U_16 getClassNameIndex(void){ return _classNameIndex; }169void setClassNameIndex(U_16 classNameIndex){ _classNameIndex = classNameIndex; }170bool isSRPNull(UDATA srpKey) { return !_srpOffsetTable->isNotNull(srpKey); }171J9SRP computeSRP(UDATA key, J9SRP *srpAddr) { return _srpOffsetTable->computeSRP(key, srpAddr); }172J9WSRP computeWSRP(UDATA key, J9WSRP *wsrpAddr) { return _srpOffsetTable->computeWSRP(key, wsrpAddr); }173UDATA getOffsetForSRPKey(UDATA srpKey) { return _srpOffsetTable->get(srpKey); }174175protected:176/*177* This functionality supports the ComparingCursor/ComparingCursorHelper model.178* Allowing the helpers to be re-based with a new baseAddress, which requires the179* count to also be reset.180*/181void resetCount() { _count = 0; }182183UDATA _count;184ROMClassCreationContext * _context;185186private:187#ifdef J9VM_ENV_LITTLE_ENDIAN188static U_16 swapU16(U_16 u16) { return ((u16 & 0xff00) >> 8) | ((u16 & 0x00ff) << 8); }189#endif190191SRPOffsetTable *_srpOffsetTable;192UDATA _tag;193U_16 _classNameIndex;194};195196#endif /* CURSOR_HPP_ */197198199