NO_INLINE JsVar *jspeStatementTry() {
  // execute the try block
  JSP_ASSERT_MATCH(LEX_R_TRY);
  bool shouldExecuteBefore = JSP_SHOULD_EXECUTE;
  jspeBlock();
  bool hadException = shouldExecuteBefore && ((execInfo.execute & EXEC_EXCEPTION)!=0);

  bool hadCatch = false;
  if (lex->tk == LEX_R_CATCH) {
    JSP_ASSERT_MATCH(LEX_R_CATCH);
    hadCatch = true;
    JSP_MATCH('(');
    JsVar *scope = 0;
    JsVar *exceptionVar = 0;
    if (hadException) {
      scope = jsvNewObject();
      if (scope)
        exceptionVar = jsvFindChildFromString(scope, jslGetTokenValueAsString(lex), true);
    }
    JSP_MATCH_WITH_CLEANUP_AND_RETURN(LEX_ID,jsvUnLock2(scope,exceptionVar),0);
    JSP_MATCH_WITH_CLEANUP_AND_RETURN(')',jsvUnLock2(scope,exceptionVar),0);
    if (exceptionVar) {
      // set the exception var up properly
      JsVar *exception = jspGetException();
      if (exception) {
        jsvSetValueOfName(exceptionVar, exception);
        jsvUnLock(exception);
      }
      // Now clear the exception flag (it's handled - we hope!)
      execInfo.execute = execInfo.execute & (JsExecFlags)~(EXEC_EXCEPTION|EXEC_ERROR_LINE_REPORTED);
      jsvUnLock(exceptionVar);
    }

    if (shouldExecuteBefore && !hadException) {
      JSP_SAVE_EXECUTE();
      jspSetNoExecute();
      jspeBlock();
      JSP_RESTORE_EXECUTE();
    } else if (scope) {
      if (jspeiAddScope(scope)) {
        jspeBlock();
        jspeiRemoveScope();
      }
    }
    jsvUnLock(scope);
  }
  if (lex->tk == LEX_R_FINALLY || (!hadCatch && ((execInfo.execute&(EXEC_ERROR|EXEC_INTERRUPTED))==0))) {
    JSP_MATCH(LEX_R_FINALLY);
    // clear the exception flag - but only momentarily!
    if (hadException) execInfo.execute = execInfo.execute & (JsExecFlags)~EXEC_EXCEPTION;
    jspeBlock();
    // put the flag back!
    if (hadException && !hadCatch) execInfo.execute = execInfo.execute | EXEC_EXCEPTION;
  }
  return 0;
}
NO_INLINE JsVar *jspeStatementTry() {
   
  JSP_ASSERT_MATCH(LEX_R_TRY);
  bool shouldExecuteBefore = JSP_SHOULD_EXECUTE;
  jspeBlock();
  bool hadException = shouldExecuteBefore && ((execInfo.execute & EXEC_EXCEPTION)!=0);

  bool hadCatch = false;
  if (lex->tk == LEX_R_CATCH) {
    JSP_ASSERT_MATCH(LEX_R_CATCH);
    hadCatch = true;
    JSP_MATCH('(');
    JsVar *scope = 0;
    JsVar *exceptionVar = 0;
    if (hadException) {
      scope = jsvNewObject();
      if (scope)
        exceptionVar = jsvFindChildFromString(scope, jslGetTokenValueAsString(lex), true);
    }
    JSP_MATCH_WITH_CLEANUP_AND_RETURN(LEX_ID,jsvUnLock2(scope,exceptionVar),0);
    JSP_MATCH_WITH_CLEANUP_AND_RETURN(')',jsvUnLock2(scope,exceptionVar),0);
    if (exceptionVar) {
       
      JsVar *exception = jspGetException();
      if (exception) {
        jsvSetValueOfName(exceptionVar, exception);
        jsvUnLock(exception);
      }
       
      execInfo.execute = execInfo.execute & (JsExecFlags)~(EXEC_EXCEPTION|EXEC_ERROR_LINE_REPORTED);
      jsvUnLock(exceptionVar);
    }

    if (shouldExecuteBefore && !hadException) {
      JSP_SAVE_EXECUTE();
      jspSetNoExecute();
      jspeBlock();
      JSP_RESTORE_EXECUTE();
    } else if (scope) {
      if (jspeiAddScope(scope)) {
        jspeBlock();
        jspeiRemoveScope();
      }
    }
    jsvUnLock(scope);
  }
  if (lex->tk == LEX_R_FINALLY || (!hadCatch && ((execInfo.execute&(EXEC_ERROR|EXEC_INTERRUPTED))==0))) {
    JSP_MATCH(LEX_R_FINALLY);
     
    if (hadException) execInfo.execute = execInfo.execute & (JsExecFlags)~EXEC_EXCEPTION;
    jspeBlock();
     
    if (hadException && !hadCatch) execInfo.execute = execInfo.execute | EXEC_EXCEPTION;
  }
  return 0;
}