void VM_OptimizeMethod::doit() {
  if (_method->is_blockMethod()) {
    //Compiler c(closure, scope);
    //return c.compile();  
    compiler_warning("can't recompile block yet");
    _nm = NULL;
    return;
  }
  Compiler c(&_key, _method);
  _nm = c.compile();
}
Beispiel #2
0
void CompiledLoop::hoistTypeTests() {
  // collect all type tests that can be hoisted out of the loop
  _loopHeader->_tests = _hoistableTests = new GrowableArray<HoistedTypeTest*>(10);
  TTHoister tth(this, _hoistableTests);
  _scope->subScopesDo(&tth);

  // add type tests to loop header for testing (avoid duplicates)
  // (currently quadratic algorithm but there should be very few)
  GrowableArray<HoistedTypeTest*>* headerTests = new GrowableArray<HoistedTypeTest*>(_hoistableTests->length());
  for (int i = _hoistableTests->length() - 1; i >= 0; i--) {
    HoistedTypeTest* t = _hoistableTests->at(i);
    PReg* tested = t->testedPR;
    for (int j = headerTests->length() - 1; j >= 0; j--) {
      if (headerTests->at(j)->testedPR == tested) {
	// already testing this PReg
	if (isEquivalentType(headerTests->at(j)->klasses, t->klasses)) {
	  // nothing to do
	} else {
	  // Whoa!  The same PReg is tested for different types in different places.
	  // Possible but rare.
	  headerTests->at(j)->invalid = t->invalid = true;
	  if (WizardMode) {
	    compiler_warning("CompiledLoop::hoistTypeTests: PReg tested for different types\n");
	    t->print();
	    headerTests->at(j)->print();
	  }
	}
	tested = NULL;    // don't add it to list
	break;
      }
    }
    if (tested) headerTests->append(t);
  }

  // now delete all hoisted type tests from loop body
  for (i = _hoistableTests->length() - 1; i >= 0; i--) {
    HoistedTypeTest* t = _hoistableTests->at(i);
    if (!t->invalid) {
      t->node->assert_preg_type(t->testedPR, t->klasses, _loopHeader);
    }
  }
  if (!_loopHeader->isActivated()) _loopHeader->activate();
}
Beispiel #3
0
void CompiledLoop::removeLoopVarOverflow() {
  // bug: should remove overflow only if increment is constant and not too large -- fix this
  Node* n = _incNode->next();
  assert(n->isBranchNode(), "must be branch");
  BranchNode* overflowCheck = (BranchNode*)n;
  assert(overflowCheck->op() == VSBranchOp, "should be overflow check");
  if (CompilerDebug || PrintLoopOpts) {
    cout(PrintLoopOpts)->print("*removing overflow check at node N%d\n", overflowCheck->id());
  }
  Node* taken = overflowCheck->next(1);	  // overflow handling code
  taken->removeUpToMerge();
  overflowCheck->removeNext(taken);	  // so overflowCheck can be eliminated
  overflowCheck->eliminate(overflowCheck->bb(), NULL, true, false);

  // since increment cannot fail anymore, directly increment loop counter if possible
  // need to search for assignment of incremented value to loop var
  Node* a = overflowCheck->next();
  while (1) {
    if (a->nPredecessors() > 1) break;	  // can't search beyond merge
    if (a->nSuccessors()   > 1) break;	  // can't search beyond branches
    if (a->isAssignNode()) {
      if (!a->deleted) {
	AssignNode* assign = (AssignNode*)a;
	if (assign->src() == _incNode->dest() && assign->dest() == _loopVar) {
	  if (CompilerDebug || PrintLoopOpts) {
	    cout(PrintLoopOpts)->print("*optimizing loopVar increment at N%d\n", _incNode->id());
	  }
	  _incNode->setDest(_incNode->bb(), _loopVar);
	  assign->eliminate(assign->bb(), NULL, true, false);
	}
      }
    } else if (!a->isTrivial()) {
      compiler_warning("unexpected nontrivial node N%d after loopVar increment\n", a->id());
    }
    a = a->next();
  }
}
Beispiel #4
0
void Compiler::computeBlockInfo() {
  FlagSetting(EliminateUnneededNodes, true);  // unused context nodes must be eliminated
  GrowableArray<InlinedScope*>* allContexts = new GrowableArray<InlinedScope*>(25);
  topScope->collectContextInfo(allContexts);
  // for now, just allocate all contexts as in interpreter
  // fix this later: collect all uplevel-accessed PRegs at same loop depth, form physical
  // contexts for these
  // also, if uplevel-read and single def --> could copy into context and keep
  // stack/register copy


  // remove all unused contexts 
  // need to iterate because removing a nested context may enable removal of a parent context
  // (could avoid iteration with topo sort, but there are few contexts anyway)
  bool changed = EliminateContexts;
  while (changed) {
    changed = false;
    for (int i = allContexts->length() - 1; i >= 0; i--) {
      InlinedScope* s = allContexts->at(i);
      if (s == NULL) continue;
      PReg* contextPR = s->context();
      assert(contextPR->isSinglyAssigned(), "should have exactly one def");
      GrowableArray<Expr*>* temps = s->contextTemporaries();
      bool noUplevelAccesses = true;
      // check if all context temps can be stack-allocated
      for (int j = temps->length() - 1; j >= 0; j--) {
	PReg* r = temps->at(j)->preg();
	if (r->uplevelR() || r->uplevelW()	    // this temp is still uplevel-accessed, so can't eliminate context
	    || (r->isBlockPReg() && !r->isUnused()) // this block still forces a context
	    ) {
	  noUplevelAccesses = false;
	  break;
	}
      }
      // TO DO: check if context is needed for NLRs
      // (noUplevelAccesses alone does not allow elimination)
      if (/*noUplevelAccesses || */contextPR->isSinglyUsed()) {
        // can eliminate context -- no uplevel-accessed vars
	// (single use is context initializer)
  	if (CompilerDebug) cout(PrintEliminateContexts)->print("%*s*eliminating context %s\n", s->depth, "", contextPR->safeName());
        contextPR->scope()->gen()->removeContextCreation();
	allContexts->at_put(i, NULL);	  // make code generator break if it tries to access this context
	changed = true;
      }
    }
  }

  // now collect all remaining contexts
  int i = allContexts->length();
  contextList = new GrowableArray<InlinedScope*>(i, i, NULL);
  while (i-- > 0) {
    // should merge several contexts into one physical context if possible
    // fix this later
    InlinedScope* s = allContexts->at(i);
    if (s == NULL) continue;
    PReg* contextPR = s->context();
    if (CompilerDebug) {
      cout(PrintEliminateContexts)->print("%*s*could not eliminate context %s in scope %s\n", 
      					  s->depth, "", contextPR->safeName(), s->key()->print_string());
    }
    reporter->report_context(s);
    contextList->at_put(i, s);
    ContextCreateNode* c = s->contextInitializer()->creator();
    c->set_contextNo(i);
    GrowableArray<Expr*>* temps = s->contextTemporaries();
    // allocate the temps in this context (but only if they're used)
    int ntemps = temps->length();
    int size = 0;
    for (int j = 0; j < ntemps; j++) {
      PReg* p = temps->at(j)->preg();
// should be:
//     if (p->isUsed() && (p->uplevelR() || p->uplevelW())) {
// but doesn't work yet (probably must fix set_self_via_context etc.)
// -Urs 6/96
      if (p->isUsed()) {
	// allocate p to context temp
	assert(p->scope() == s || p->isBlockPReg(), "oops");
	Location loc = Mapping::contextTemporary(i, size, s->scopeID());
	if (p->isBlockPReg()) {
	  // Blocks aren't actually assigned (at the PReg level) so that the inlining info
	  // isn't lost.  Thus we need to create a fake destination here if the context exists.
	  SAPReg* dest = new SAPReg(s, loc, true, true, PrologueBCI, EpilogueBCI);
	  Expr* e = new UnknownExpr(dest, NULL);
	  //contextPR->scope()->contextInitializer()->initialize(j, init);
	  temps->at_put(j, e);
	} else {
	  p->allocateTo(loc);
	}
	size++;
      }
    }
    c->set_sizeOfContext(size);
    if (size < ntemps && c->scope()->number_of_noninlined_blocks() > 0) {
      // this hasn't been exercised much 
      compiler_warning("while compiling %s: eliminated some context temps", key->print_string());
    }
  }

  // Compute the number of noninlined blocks for the nmethod and allocate 
  const int nblocks = topScope->number_of_noninlined_blocks();

  if (is_method_compile() || nblocks > 0) {
    // allocate nblocks+1 jumpTable entries
    const jumpTableID id = Universe::code->jump_table()->allocate(nblocks + 1);

    if (is_method_compile()) {
      main_jumpTable_id = id;
    } else {
      promoted_jumpTable_id = id;
    }

    // first is for nmethod itself
    int block_index = 1;
    for (int i = bbIterator->exposedBlks->length() - 1; i >= 0; i--) {
      BlockPReg* blk = bbIterator->exposedBlks->at(i);
      if (blk->isUsed()) {
        assert(block_index <= nblocks, "nblocks too small");
        blk->closure()->set_id(id.sub(block_index++));
      }
    }
    assert(nblocks + 1 == block_index, "just checking");
  }
}
Beispiel #5
0
/** Testet einen Auslöser auf Zulässigkeit. Wird eine nicht zulässige oder erreichbare
 * Konfiguration gefunden, wird je nach Situation ein fataler Fehler oder eine Compiler-Warnung
 * ausgelöst.
 * \param[in] ausloeser Auslöser, der geprüft werden soll
 * \param[in] name Name für Meldungen 
 */
void check_ausloeser (struct ausloeser * ausloeser, char * name) {

          struct harmonie * help_harmonie;
          
          if (ausloeser == NULL) return;
          
          if (ausloeser->ausloeser_typ == ausloeser_harmonie_form) {
              help_harmonie = get_harmonie (ausloeser->u.ausloeser_harmonie_form.name, list_of_harmonien);
              if (help_harmonie == NULL) {
                  fatal_error (30, 
                               ausloeser->u.ausloeser_harmonie_form.name,
                               name);
              }
              if (enthalten_in_tastenliste 
                    (ausloeser->u.ausloeser_harmonie_form.vortaste, 
                     help_harmonie->tastenliste) ||
                     ausloeser->u.ausloeser_harmonie_form.vortaste
                        == -1 ) {
                /* OK */
              }
              else {
                  compiler_warning (2, name);
/* Markierung setzen, fuer unmoeglichen Ausloeser */
                  ausloeser->u.ausloeser_harmonie_form.vortaste = -2;
              }
              if (enthalten_in_tastenliste 
                    (ausloeser->u.ausloeser_harmonie_form.nachtaste, 
                     help_harmonie->tastenliste) ||
                     ausloeser->u.ausloeser_harmonie_form.nachtaste
                          == -1 ) {
                /* OK */
              }
              else {
                  compiler_warning (2, name);
/* Markierung setzen, fuer unmoeglichen Ausloeser */
                  ausloeser->u.ausloeser_harmonie_form.vortaste = -2;
              }
          }

          
          if (ausloeser->ausloeser_typ == ausloeser_harmonie) {
              help_harmonie = get_harmonie (ausloeser->u.ausloeser_harmonie.name, list_of_harmonien);
              if (help_harmonie == NULL) {
                  fatal_error (30, 
                               ausloeser->u.ausloeser_harmonie.name,
                               name);
              }
              if (enthalten_in_tastenliste 
                       (ausloeser->u.ausloeser_harmonie.vortaste, 
                        help_harmonie->tastenliste) ||
                        ausloeser->u.ausloeser_harmonie.vortaste
                            == -1 ) {
                /* OK */
              }
              else {
                  compiler_warning (2, name);
/* Markierung setzen, fuer unmoeglichen Ausloeser */
                  ausloeser->u.ausloeser_harmonie.vortaste = -2;
              }
              if (enthalten_in_tastenliste 
                       (ausloeser->u.ausloeser_harmonie.nachtaste, 
                        help_harmonie->tastenliste) ||
                        ausloeser->u.ausloeser_harmonie.nachtaste
                            == -1 ) {
                /* OK */
              }
              else {
                  compiler_warning (2, name);
/* Markierung setzen, fuer unmoeglichen Ausloeser */
                  ausloeser->u.ausloeser_harmonie.vortaste = -2;
              }
          }

          if (ausloeser->ausloeser_typ == ausloeser_midi_in) {
              struct midiliste * midi_lauf 
                   = ausloeser->u.ausloeser_midi_in.midi_code;
              if (midi_lauf -> midi_code < 128 || 
                  midi_lauf -> midi_code > 255 ) {
                    fatal_error (50, name,"Statusbyte");
              }
              if (midi_lauf -> midi_code & 0x000F ) {
                    midi_lauf -> midi_code &= 0xFFF0;
                    compiler_warning(1,name);        
              }      
              midi_lauf = midi_lauf -> next;
              while (midi_lauf) {
                  if (midi_lauf -> midi_code < 0 ||
                      midi_lauf -> midi_code > 127 ) {
                      fatal_error (50, name,"Datenbyte");
                  }
                  else 
                      midi_lauf = midi_lauf -> next;
              }
          }

}