jitirnode.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 809 行 · 第 1/2 页
C
809 行
/* * @(#)jitirnode.c 1.102 06/10/10 * * Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. * */#include "javavm/include/defs.h"#include "javavm/include/utils.h"#include "javavm/include/bcutils.h"#include "javavm/include/globals.h"#include "javavm/include/jit/jit.h"#include "javavm/include/jit/jitir.h"#include "javavm/include/jit/jitcontext.h"#include "javavm/include/jit/jitirdump.h"#include "javavm/include/jit/jitirnode.h"#include "javavm/include/jit/jitirblock.h"#include "javavm/include/jit/jitutils.h"#include "javavm/include/jit/jitstats.h"#include "javavm/include/jit/jitmemory.h"#include "javavm/include/porting/doubleword.h"#include "javavm/include/porting/jit/jit.h"#include "javavm/include/clib.h"static voidCVMJITirnodeSetTreeHasBeenEmitted(CVMJITCompilationContext *con, CVMJITIRNode *node);/* * CVMJITIRNode interface APIs */#undef MAX#define MAX(x, y) ((x > y) ? x : y)#define CVMJITirnodeInheritSideEffects0(node, operand) { \ (node)->flags |= ((operand)->flags & CVMJITIRNODE_SIDE_EFFECT_MASK); \}static voidCVMJITirnodeInheritSideEffects(CVMJITIRNode *node, CVMJITIRNode *operand) { if (!CVMJITirnodeHasBeenEvaluated(operand)) { CVMJITirnodeInheritSideEffects0(node, operand); }}static voidCVMJITirnodeBinaryInheritSideEffects(CVMJITIRNode *node, CVMJITIRNode *lhs, CVMJITIRNode *rhs){ /* If we really wanted to get clever, we could do this all with bit operations and no conditionals. */ CVMJITirnodeInheritSideEffects(node, lhs); CVMJITirnodeInheritSideEffects(node, rhs);}static CVMJITIRNode*cloneExpressionNode( CVMJITCompilationContext* con, CVMJITIRNode* node){ CVMJITIRNode *newNode; /* CVMconsolePrintf("cloneExpressionNode:\n"); CVMJITirdumpIRNode(con, node, 0, " "); CVMconsolePrintf("\n"); */ switch (CVMJITgetNodeTag(node)){ case CVMJIT_NULL_NODE << CVMJIT_SHIFT_NODETAG: newNode = CVMJITirnodeNewNull(con, node->tag); newNode->type_node.nullOp.data = node->type_node.nullOp.data; break; case CVMJIT_LOCAL_NODE << CVMJIT_SHIFT_NODETAG: newNode = CVMJITirnodeNewLocal(con, node->tag, node->type_node.local.localNo); break; case CVMJIT_UNARY_NODE << CVMJIT_SHIFT_NODETAG: newNode = CVMJITirnodeNewUnaryOp(con, node->tag, node->type_node.unOp.operand); newNode->type_node.unOp.flags = node->type_node.unOp.flags; break; case CVMJIT_BINARY_NODE << CVMJIT_SHIFT_NODETAG: newNode = CVMJITirnodeNewBinaryOp(con, node->tag, node->type_node.binOp.lhs, node->type_node.binOp.rhs); newNode->type_node.binOp.flags = node->type_node.binOp.flags; newNode->type_node.binOp.data = node->type_node.binOp.data; newNode->type_node.binOp.data2 = node->type_node.binOp.data2; break; case CVMJIT_PHI0_NODE << CVMJIT_SHIFT_NODETAG: if (CVMJITgetOpcode(node) == (CVMJIT_USED << CVMJIT_SHIFT_OPCODE)){ newNode = CVMJITirnodeNewUsedOp(con, node->tag, node->type_node.usedOp.spillLocation, node->type_node.usedOp.registerSpillOk); break; } default:#ifdef CVM_DEBUG CVMconsolePrintf(">>cloneExpressionNode: don't know about...\n"); CVMtraceJITBCTOIRExec({ CVMJITirdumpIRNodeAlways(con, node, 0, " "); CVMconsolePrintf("\n"); });#endif newNode = NULL; /* prevent compiler warning */ CVMassert(CVM_FALSE); } return newNode;}/* Purpose: Produces a node which effectively gets the value of the specified node. "Producing a node" in this case can mean several things: 1. If node is an IDENTITY, increment the reference count and return node. 2. If node is CONSTANT, increment the reference count and return node 4. If reference count on node is 0, increment the reference count and return the node 3. Else, clone node, overpaint it with an IDENTITY referencing the clone, increment reference count on node (setting clone's ref count to 1), and return src_node*/static voidCVMJITidentity( CVMJITCompilationContext *con, CVMJITIRNode *node){ CVMJITIRNode *cloneNode = NULL; CVMassert(CVMJITirnodeGetRefCount(node) == 2); CVMassert(!CVMJITirnodeIsIdentity(node)); /* Next, check if the node is a constant node: */ if (CVMJITnodeTagIs(node, CONSTANT)) { return; /* Else, create a new IDENTITY node in the place of the specified node: */ } else { CVMJITUnaryOp* unOpNode = &node->type_node.unOp; cloneNode = cloneExpressionNode(con, node); /* paint over current node with IDENTITY node. It will be unary */ node->tag = (node->tag & CVMJIT_TYPE_MASK) | CVMJIT_ENCODE_IDENTITY(0); unOpNode->operand = cloneNode; /* Just in case we turn a null-check node into an identity node */ unOpNode->flags &= CVMJITIRNODE_PARENT_THROWS_EXCEPTIONS; /* treat as a leaf */ CVMJITirnodeSetcurRootCnt(node, 1); CVMassert(CVMJITirnodeGetRefCount(node) == 2); CVMJITirnodeSetRefCount(cloneNode, 1); return; }}/* * Decorate the current IDENTITY node with an IdentityDecoration */voidCVMJITidentitySetDecoration( CVMJITCompilationContext* con, CVMJITIdentityDecoration* dec, CVMJITIRNode* expr){ dec->refCount += CVMJITirnodeGetRefCount(expr) - 1; /* * if expr->tag is an IDENTITY operator, do the occupy, else * skip it. Ensure that the EVALUATED bit is set. */ if (CVMJITirnodeIsIdentity(expr)) { CVMJITidentDecoration(expr) = (void *)dec; }}/* * Get decoration of the current IDENTITY node */CVMJITIdentityDecoration*CVMJITidentityGetDecoration( CVMJITCompilationContext* con, CVMJITIRNode* expr){ if ((expr != NULL) && CVMJITirnodeIsIdentity(expr)) { return (CVMJITIdentityDecoration*)CVMJITidentDecoration(expr); } else { return NULL; }}static CVMJITIRNode *CVMJITirnodeCreate(CVMJITCompilationContext* con, CVMUint32 size, CVMUint16 tag){ CVMJITIRNode* node; CVMUint32 nodeSize; /* make sure the allocation is large enough to repaint into * an identity operator if necessary. */ if (size < sizeof(CVMJITIdentOp)) size = sizeof(CVMJITIdentOp); nodeSize = CVMJIT_IRNODE_SIZE + size; node = (CVMJITIRNode*) CVMJITmemNew(con, JIT_ALLOC_IRGEN_NODE, nodeSize);#if defined(CVM_DEBUG) || defined(CVM_TRACE_JIT) CVMJITirnodeSetDumpTag(node, CVM_TRUE); CVMJITirnodeSetID(con, node);#endif CVMJITirnodeSetTag(node, tag); CVMJITirnodeSetRefCount(node, 0); /* Start out with no references */ CVMJITirnodeSetcurRootCnt(node, 1); node->flags = 0; /* Initialize the flags. */ node->regsRequired = 0; node->decorationType = CVMJIT_NO_DECORATION; CVMJITstatsRecordInc(con, CVMJIT_STATS_TOTAL_NUMBER_OF_NODES); return node;}/* * Assert on the allowed IR nodes before getting the first operand of IR node * in CVMJITirnodeGetLeftSubtree(). */#ifdef CVM_DEBUG_ASSERTSvoidCVMJITirnodeAssertIsGenericSubNode(CVMJITIRNode* node){ CVMassert(CVMJITirnodeIsDefineNode(node) || CVMJITirnodeIsTableSwitchNode(node) || CVMJITirnodeIsLookupSwitchNode(node) || CVMJITirnodeIsCondBranchNode(node) || CVMJITirnodeIsBinaryNode(node) || CVMJITirnodeIsUnaryNode(node));}#endif/* * Create CVMJITMapPcNode * Node used by backend to generate javaPC -> compiledPC table */CVMJITIRNode*CVMJITirnodeNewMapPcNode( CVMJITCompilationContext* con, CVMUint16 tag, CVMUint16 pc, CVMJITIRBlock* curbk){ CVMJITIRNode* node = CVMJITirnodeCreate(con, sizeof(CVMJITMapPcNode), tag); node->type_node.mapPcNode.javaPcToMap = pc; CVMJITirnodeSetHasUndefinedSideEffect(node);#ifdef CVM_DEBUG_ASSERTS if (!CVMJITirblockIsArtificial(curbk)) { CVMassert(pc >= curbk->lastOpenRange->startPC); CVMassert(pc >= con->mc->startPC - con->mc->code); CVMassert(pc < con->mc->endPC - con->mc->code); }#endif return node;}#ifdef CVM_DEBUG_ASSERTS/* Purpose: Checks if every operand with a side effect on the operand stack has been evaluated. */static CVMBoolCVMJITirnodeOperandStackSideEffectsAreFullyEvaluated( CVMJITCompilationContext *con){ CVMJITStack *operandStack = con->operandStack; CVMUint32 i; for (i = 0; i < CVMJITstackCnt(con, operandStack); i++) { CVMJITIRNode *stkNode = CVMJITstackGetElementAtIdx(con, operandStack, i); if (!CVMJITirnodeHasBeenEvaluated(stkNode) && CVMJITirnodeHasSideEffects(stkNode)) { return CVM_FALSE; } } /* end of for loop */ return CVM_TRUE;}#endif/* * Create CVMJITIRRoot * Only root node is appended into the root list within a block, * we append it right after the root node is created. */CVMJITIRRoot*CVMJITirnodeNewRoot(CVMJITCompilationContext* con, CVMJITIRBlock* curbk, CVMJITIRNode* expr){ CVMJITIRRoot* root = (CVMJITIRRoot*)CVMJITmemNew(con, JIT_ALLOC_IRGEN_OTHER, sizeof(CVMJITIRRoot)); root->next = NULL; root->prev = NULL; root->expr = expr; /* Make sure that operands on the operand stack have all been evaluated before inserting a root node: */ /* TBD: Is it possible to resolve the following so that there is no exception to the rule? */ CVMassert( (CVMJITgetOpcode(expr) == (CVMJIT_END_INLINING << CVMJIT_SHIFT_OPCODE)) || (CVMJITgetOpcode(expr) == (CVMJIT_OUTOFLINE_INVOKE << CVMJIT_SHIFT_OPCODE)) || con->operandStackIsBeingEvaluated || CVMJITirnodeOperandStackSideEffectsAreFullyEvaluated(con)); CVMJITirlistAppend(con, CVMJITirblockGetRootList(curbk), (void*)root); CVMJITstatsRecordInc(con, CVMJIT_STATS_NUMBER_OF_ROOT_NODES); if (curbk->lastOpenRange->firstRoot == NULL) { curbk->lastOpenRange->firstRoot = root; } /* Keep track of the maximum number of nodes per root node. */ if (expr->curRootCnt > con->saveRootCnt) { con->saveRootCnt = expr->curRootCnt; } CVMassert(!CVMJITirnodeHasBeenEmitted(expr)); CVMJITirnodeSetTreeHasBeenEmitted(con, expr); return root;}/* * Create CVMJITConstant */CVMJITIRNode*CVMJITirnodeNewConstant32(CVMJITCompilationContext* con, CVMUint16 tag, CVMUint32 v32){ CVMJITIRNode* node = CVMJITirnodeCreate(con, sizeof(CVMJITConstant32), tag); node->type_node.constant32.v32 = v32; /* By definition, a constant node is already evaluated from the start: */ CVMJITirnodeSetHasBeenEvaluated(node); CVMJITstatsRecordInc(con, CVMJIT_STATS_NUMBER_OF_CONST_NODES); return node;}CVMJITIRNode*CVMJITirnodeNewConstantAddr(CVMJITCompilationContext* con, CVMUint16 tag, CVMAddr vAddr){ CVMJITIRNode* node = CVMJITirnodeCreate(con, sizeof(CVMJITConstantAddr), tag); node->type_node.constantAddr.vAddr = vAddr; /* By definition, a constant node is already evaluated from the start: */ CVMJITirnodeSetHasBeenEvaluated(node); CVMJITstatsRecordInc(con, CVMJIT_STATS_NUMBER_OF_CONST_NODES); return node;}CVMJITIRNode*CVMJITirnodeNewConstant64(CVMJITCompilationContext* con, CVMUint16 tag, CVMJavaVal64* v64){ CVMJITIRNode* node = CVMJITirnodeCreate(con, sizeof(CVMJITConstant64), tag); CVMmemCopy64(node->type_node.constant64.j.v, v64->v); /* By definition, a constant node is already evaluated from the start: */ CVMJITirnodeSetHasBeenEvaluated(node); CVMJITstatsRecordInc(con, CVMJIT_STATS_NUMBER_OF_CONST_NODES); return node;}/* * Build Constant32 node for the unresolved cp index. * Build RESOLVE_REFERENCE node of one of the following types: * CVMJIT_CONST_NEW_CB_UNRESOLVED * CVMJIT_CONST_CB_UNRESOLVED * CVMJIT_CONST_ARRAY_CB_UNRESOLVED * CVMJIT_CONST_GETFIELD_FB_UNRESOLVED * CVMJIT_CONST_PUTFIELD_FB_UNRESOLVED * CVMJIT_CONST_GETSTATIC_FB_UNRESOLVED * CVMJIT_CONST_PUTSTATIC_FB_UNRESOLVED * CVMJIT_CONST_STATIC_MB_UNRESOLVED * CVMJIT_CONST_SPECIAL_MB_UNRESOLVED * CVMJIT_CONST_INTERFACE_MB_UNRESOLVED * CVMJIT_CONST_METHOD_TABLE_INDEX_UNRESOLVED * Build Root node pointing to RESOLVE_REFERENCE node at the top.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?