Beispiel #1
0
Compiler::fgWalkResult Rationalizer::RewriteNode(GenTree** useEdge, ArrayStack<GenTree*>& parentStack)
{
    assert(useEdge != nullptr);

    GenTree* node = *useEdge;
    assert(node != nullptr);

#ifdef DEBUG
    const bool isLateArg = (node->gtFlags & GTF_LATE_ARG) != 0;
#endif

    // First, remove any preceeding GT_LIST nodes, which are not otherwise visited by the tree walk.
    //
    // NOTE: GT_LIST nodes that are used by block ops and phi nodes will in fact be visited.
    for (GenTree* prev = node->gtPrev; prev != nullptr && prev->OperGet() == GT_LIST; prev = node->gtPrev)
    {
        BlockRange().Remove(prev);
    }

    // In addition, remove the current node if it is a GT_LIST node.
    if ((*useEdge)->OperGet() == GT_LIST)
    {
        BlockRange().Remove(*useEdge);
        return Compiler::WALK_CONTINUE;
    }

    LIR::Use use;
    if (parentStack.Height() < 2)
    {
        use = LIR::Use::GetDummyUse(BlockRange(), *useEdge);
    }
    else
    {
        use = LIR::Use(BlockRange(), useEdge, parentStack.Index(1));
    }

    assert(node == use.Def());
    switch (node->OperGet())
    {
        case GT_ASG:
            RewriteAssignment(use);
            break;

        case GT_BOX:
            // GT_BOX at this level just passes through so get rid of it
            use.ReplaceWith(comp, node->gtGetOp1());
            BlockRange().Remove(node);
            break;

        case GT_ADDR:
            RewriteAddress(use);
            break;

        case GT_NOP:
            // fgMorph sometimes inserts NOP nodes between defs and uses
            // supposedly 'to prevent constant folding'. In this case, remove the
            // NOP.
            if (node->gtGetOp1() != nullptr)
            {
                use.ReplaceWith(comp, node->gtGetOp1());
                BlockRange().Remove(node);
            }
            break;

        case GT_COMMA:
        {
            GenTree* op1 = node->gtGetOp1();
            if ((op1->gtFlags & GTF_ALL_EFFECT) == 0)
            {
                // The LHS has no side effects. Remove it.
                bool               isClosed    = false;
                unsigned           sideEffects = 0;
                LIR::ReadOnlyRange lhsRange    = BlockRange().GetTreeRange(op1, &isClosed, &sideEffects);

                // None of the transforms performed herein violate tree order, so these
                // should always be true.
                assert(isClosed);
                assert((sideEffects & GTF_ALL_EFFECT) == 0);

                BlockRange().Delete(comp, m_block, std::move(lhsRange));
            }

            GenTree* replacement = node->gtGetOp2();
            if (!use.IsDummyUse())
            {
                use.ReplaceWith(comp, replacement);
            }
            else
            {
                // This is a top-level comma. If the RHS has no side effects we can remove
                // it as well.
                if ((replacement->gtFlags & GTF_ALL_EFFECT) == 0)
                {
                    bool               isClosed    = false;
                    unsigned           sideEffects = 0;
                    LIR::ReadOnlyRange rhsRange    = BlockRange().GetTreeRange(replacement, &isClosed, &sideEffects);

                    // None of the transforms performed herein violate tree order, so these
                    // should always be true.
                    assert(isClosed);
                    assert((sideEffects & GTF_ALL_EFFECT) == 0);

                    BlockRange().Delete(comp, m_block, std::move(rhsRange));
                }
            }

            BlockRange().Remove(node);
        }
        break;

        case GT_ARGPLACE:
            // Remove argplace and list nodes from the execution order.
            //
            // TODO: remove phi args and phi nodes as well?
            BlockRange().Remove(node);
            break;

#ifdef _TARGET_XARCH_
        case GT_CLS_VAR:
        {
            // Class vars that are the target of an assignment will get rewritten into
            // GT_STOREIND(GT_CLS_VAR_ADDR, val) by RewriteAssignment. This check is
            // not strictly necessary--the GT_IND(GT_CLS_VAR_ADDR) pattern that would
            // otherwise be generated would also be picked up by RewriteAssignment--but
            // skipping the rewrite here saves an allocation and a bit of extra work.
            const bool isLHSOfAssignment = (use.User()->OperGet() == GT_ASG) && (use.User()->gtGetOp1() == node);
            if (!isLHSOfAssignment)
            {
                GenTree* ind = comp->gtNewOperNode(GT_IND, node->TypeGet(), node);

                node->SetOper(GT_CLS_VAR_ADDR);
                node->gtType = TYP_BYREF;

                BlockRange().InsertAfter(node, ind);
                use.ReplaceWith(comp, ind);

                // TODO: JIT dump
            }
        }
        break;
#endif // _TARGET_XARCH_

        case GT_INTRINSIC:
            // Non-target intrinsics should have already been rewritten back into user calls.
            assert(Compiler::IsTargetIntrinsic(node->gtIntrinsic.gtIntrinsicId));
            break;

#ifdef FEATURE_SIMD
        case GT_INITBLK:
            RewriteInitBlk(use);
            break;

        case GT_COPYBLK:
            RewriteCopyBlk(use);
            break;

        case GT_OBJ:
            RewriteObj(use);
            break;

        case GT_LCL_FLD:
        case GT_STORE_LCL_FLD:
            // TODO-1stClassStructs: Eliminate this.
            FixupIfSIMDLocal(node->AsLclVarCommon());
            break;

        case GT_STOREIND:
        case GT_IND:
            if (node->gtType == TYP_STRUCT)
            {
                GenTree* addr = node->AsIndir()->Addr();
                assert(addr->TypeGet() == TYP_BYREF);

                if (addr->OperIsLocal())
                {
                    LclVarDsc* varDsc = &(comp->lvaTable[addr->AsLclVarCommon()->gtLclNum]);
                    assert(varDsc->lvSIMDType);
                    unsigned simdSize = (unsigned int)roundUp(varDsc->lvExactSize, TARGET_POINTER_SIZE);
                    node->gtType      = comp->getSIMDTypeForSize(simdSize);
                }
#if DEBUG
                else
                {
                    // If the address is not a local var, assert that the user of this IND is an ADDR node.
                    assert((use.User()->OperGet() == GT_ADDR) || use.User()->OperIsLocalAddr());
                }
#endif
            }
            break;

        case GT_SIMD:
        {
            noway_assert(comp->featureSIMD);
            GenTreeSIMD* simdNode = node->AsSIMD();
            unsigned     simdSize = simdNode->gtSIMDSize;
            var_types    simdType = comp->getSIMDTypeForSize(simdSize);

            // TODO-1stClassStructs: This should be handled more generally for enregistered or promoted
            // structs that are passed or returned in a different register type than their enregistered
            // type(s).
            if (simdNode->gtType == TYP_I_IMPL && simdNode->gtSIMDSize == TARGET_POINTER_SIZE)
            {
                // This happens when it is consumed by a GT_RET_EXPR.
                // It can only be a Vector2f or Vector2i.
                assert(genTypeSize(simdNode->gtSIMDBaseType) == 4);
                simdNode->gtType = TYP_SIMD8;
            }
            else if (simdNode->gtType == TYP_STRUCT || varTypeIsSIMD(simdNode))
            {
                node->gtType = simdType;
            }

            // Certain SIMD trees require rationalizing.
            if (simdNode->gtSIMD.gtSIMDIntrinsicID == SIMDIntrinsicInitArray)
            {
                // Rewrite this as an explicit load.
                JITDUMP("Rewriting GT_SIMD array init as an explicit load:\n");
                unsigned int baseTypeSize = genTypeSize(simdNode->gtSIMDBaseType);
                GenTree*     address = new (comp, GT_LEA) GenTreeAddrMode(TYP_BYREF, simdNode->gtOp1, simdNode->gtOp2,
                                                                      baseTypeSize, offsetof(CORINFO_Array, u1Elems));
                GenTree* ind = comp->gtNewOperNode(GT_IND, simdType, address);

                BlockRange().InsertBefore(simdNode, address, ind);
                use.ReplaceWith(comp, ind);
                BlockRange().Remove(simdNode);

                DISPTREERANGE(BlockRange(), use.Def());
                JITDUMP("\n");
            }
            else
            {
                // This code depends on the fact that NONE of the SIMD intrinsics take vector operands
                // of a different width.  If that assumption changes, we will EITHER have to make these type
                // transformations during importation, and plumb the types all the way through the JIT,
                // OR add a lot of special handling here.
                GenTree* op1 = simdNode->gtGetOp1();
                if (op1 != nullptr && op1->gtType == TYP_STRUCT)
                {
                    op1->gtType = simdType;
                }

                GenTree* op2 = simdNode->gtGetOp2();
                if (op2 != nullptr && op2->gtType == TYP_STRUCT)
                {
                    op2->gtType = simdType;
                }
            }
        }
        break;
#endif // FEATURE_SIMD

        default:
            break;
    }

    // Do some extra processing on top-level nodes to remove unused local reads.
    if (use.IsDummyUse() && node->OperIsLocalRead())
    {
        assert((node->gtFlags & GTF_ALL_EFFECT) == 0);

        comp->lvaDecRefCnts(node);
        BlockRange().Remove(node);
    }

    assert(isLateArg == ((node->gtFlags & GTF_LATE_ARG) != 0));

    return Compiler::WALK_CONTINUE;
}
Beispiel #2
0
Datei: gc.c Projekt: CHYFTT/Tiger
 void Tiger_gc ()
{
  // Your code here:

  //

  printf("Tiger_gc start!\n");
  printf("heap.toStart=%d\n",(int*)heap.toStart);
  printf("heap.toNext=%d\n",(int*)heap.toNext);


  while(previous!=0)
  {
      printf("\n-------------------this is a frame----------------------\n");
    char* arguments_gc_map = *((int*)((char *)previous + 4));
    /*
     * 此处的指针使用
     * (int*)修饰是因为要对这个指针进行取地址操作。具体如何操作就是由(int*)说明。
     * 此处的意思是取地址操作以4byte进行。所以,这个位置替换成(long*),(int**),(char**)都不影响结果。
     */
    int* arguments_address=(int*)((char*)previous+8);
    int locals_gc_map=*((char*)previous+12);

    printf("arguments_gc_map is:\"%s\"\n",arguments_gc_map);
    printf("arguments_gc_map address is:0x%d\n",*arguments_address);
    printf("locals_gc_map :%d local value\n",locals_gc_map);



    void* temp=0;
    //arguments
    if(arguments_gc_map!=0)
    {
        printf("\n this is a argument_gc_map---------\n");
        int* addr=arguments_address;
        int len=strlen(arguments_gc_map);
        int i=0;

        printf("arguments_gc_map length is %d\n",len);

        for(i=0;i<len;i++)
        {

            if(arguments_gc_map[i]=='1')
            {//字符用''
                temp=*((int*)addr);
                printf("\nin arguments obj address is:0x%d\n",*(int*)temp);

                //Copy
                temp=Copy(temp);
                printf("copy finished...\n");


                addr=(char*)addr+4;


            }

        }
    }


     //locals
     if(locals_gc_map!=0)
     {
        printf("\n this is a locals_gc_map----------------------\n");
        int j=0;
        int* localStart=(int*)((char*)previous+16);
        int* localTemp=localStart;
        for(j=0;j<locals_gc_map;j++)
        {
            temp=localTemp;
            printf("\nlocals_obj address is:%d\n",*(int*)temp);

            //Copy
            temp=Copy(temp);
            printf("copy finished...\n");

            //每次向下移动一次
            localTemp=(char*)localTemp+4;

        }
     }

       previous = (*(int*)previous);
      /*
       *此处指针的用法(同上)!!!(*(long*)previous)也是可以的。
       */
       printf("-------------------------frame finished-----------------------\n");
  }
  //previous遍历结束




//修改对象内部的指针
  RewriteObj();
  //交换heap和Free
  Exchange();



	return;


}