/*
 * The contents of this file are subject to the Netscape Public
 * License Version 1.1 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of
 * the License at http://www.mozilla.org/NPL/

 * Software distributed under the License is distributed on an "AS
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * rights and limitations under the License.

 * The Original Code is Rhino code, released
 * May 6, 1999.

 * The Initial Developer of the Original Code is Netscape
 * Communications Corporation.  Portions created by Netscape are
 * Copyright (C) 1997-1999 Netscape Communications Corporation. All
 * Rights Reserved.

 * Contributor(s): 

 * Alternatively, the contents of this file may be used under the
 * terms of the GNU Public License (the "GPL"), in which case the
 * provisions of the GPL are applicable instead of those above.
 * If you wish to allow use of your version of this file only
 * under the terms of the GPL and not to allow others to use your
 * version of this file under the NPL, indicate your decision by
 * deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL.  If you do not delete
 * the provisions above, a recipient may use your version of this
 * file under either the NPL or the GPL.
 */
/*
 *  JavaScript Interpreter
 *  The JavaScript Interpreter is used for executing JavaScript programs
 *  in EWB that control user events on buttons, restrict inputs on textlines
 *  and so on.
 *
 *  Developmened by: Institute of Artificial Intelligence & Robotics
 *                 of Xi'an Jiaotong University
 *
 *  Create by:      Tian Wenqiang
 *  Last modified:  2001-11-13 19:46
 */

/*
   JavaScript Interpreter Application Programming Interface implement file
*/

#include <stdio.h>
#ifdef PERSIST
# include <limits.h>
#endif
#include "js-api.h"
#include "js-new.h"
#include "js-context.h"
#include "js-scriptruntime.h"
#include "js-nativehost.h"
#include "js-nativescript.h"
#include "js-stringreader.h"
#include "js-script.h"
#include "js-hosterrorreporter.h"
#include "js-exceptionhandler.h"
#include "js-config.h"
#include "js-interpreter.h"

#include "js-gcheap.h"
#include "ewb-mem.h"

#ifdef PERSIST
# include "js-binaryformat.h"
# include "js-binaryrandomreader.h"
# include "js-filerandomwriter.h"
#endif

#ifndef SHELL
extern int ewbCompileMemShow;
#endif

/* Check object type */
/* Procedures */
/* Type operations ***********************************************************/
jsBool_t
JS_IsObject(jsVal_t value)
{
    return JS_VAL_IS_OBJECT(value);
}
jsBool_t
JS_IsInteger(jsVal_t value)
{
    return JS_VAL_IS_INT(value);
}
jsBool_t
JS_IsDouble(jsVal_t value)
{
    return JS_VAL_IS_DOUBLE(value);
}
jsBool_t
JS_IsString(jsVal_t value)
{
    return JS_VAL_IS_STRING(value);
}
jsBool_t
JS_IsBoolean(jsVal_t value)
{
    return JS_VAL_IS_BOOLEAN(value);
}
/* Convert JS value to a specified type value */
jsBool_t
JS_ValueToBoolean(jsContext_t context, jsVal_t val)
{
    JSContext *cx = (JSContext *) context;

    return JSScriptRuntime::toBoolean(cx, val);
}
jsInt_t
JS_ValueToInteger(jsContext_t context, jsVal_t val)
{
    JSContext *cx = (JSContext *) context;

    return (jsInt_t) JSScriptRuntime::toInteger(cx, val);
}
jsString_t
JS_ValueToString(jsContext_t context, jsVal_t val)
{
    JSContext *cx = (JSContext *) context;

    if (JS_VAL_IS_STRING(val)) return JS_VAL_TO_STRING(val);

    jsString_t s = JSScriptRuntime::toString(cx, val);
    jsString_t result = JS_NewGCString(cx, s);

    JS_DeleteZoneObj(cx, s);
    return result;
}
jsDouble_t
JS_ValueToDouble(jsContext_t context, jsVal_t val)
{
    JSContext *cx = (JSContext *) context;

    return JSScriptRuntime::toNumber(cx, val);
}
jsObject_t
JS_ValueToObject(jsContext_t context, jsObject_t scope, jsVal_t val)
{
    JSContext *cx = (JSContext *) context;
    JSScriptable *_scope = (JSScriptable *) scope;

    return JSScriptRuntime::toObject(cx, _scope, val);
}

/* Convert a specified type value to JS value */
jsVal_t
JS_ObjectToValue(jsContext_t context, jsObject_t obj)
{
    return JS_OBJECT_TO_VAL(obj);
}
jsVal_t
JS_IntegerToValue(jsContext_t context, jsInt_t i)
{
    JSContext *cx = (JSContext *) context;

    return JSScriptRuntime::toValue(cx, (double) i);
}
jsVal_t
JS_BooleanToValue(jsContext_t context, jsBool_t b)
{
    return JS_BOOLEAN_TO_VAL(b);
}
jsVal_t
JS_DoubleToValue(jsContext_t context, jsDouble_t d)
{
    JSContext *cx = (JSContext *) context;

    return JSScriptRuntime::toValue(cx, d);
}

jsVal_t
JS_StringToValue(jsContext_t context, jsString_t s)
{
    JSContext *cx = (JSContext *) context;

    return JS_STRING_TO_VAL(JS_NewGCString(cx, s));
}


/* Runtime and Context *******************************************************/

/* Initialize
Initialize all modules in the JavaScript Interpreter.*/
void Initialize_JSInterpreter()
{
    Initialize_JSConfig();
}

/* Runtime
JS_NewRuntime creates a JavaScript Runtime and JS_DeleteRuntime
destroys a JavaScript Runtime.*/
jsRuntime_t
JS_NewRuntime(long maxBytes)
{
    JSRuntime *rt = new JSRuntime(maxBytes);

    return (jsRuntime_t) rt;
}
void
JS_DeleteRuntime(jsRuntime_t runtime)
{
    JSRuntime *rt = (JSRuntime *) runtime;

    delete rt;
}
void JS_CleanupContext(jsContext_t context)
{
    JSContext *cx = (JSContext *) context;

    cx->cleanup();
}

/* Context
JS_NewContext creates a JavaScript execution context and JS_DeleteContext
destroys a JavaScript execution context.*/
jsContext_t
JS_NewContext(jsRuntime_t runtime)
{
    JSRuntime *_runtime = (JSRuntime *) runtime;
    JSContext *cx = new (_runtime) JSContext(_runtime);

    return (jsContext_t) cx;
}
void JS_DeleteContext(jsContext_t context)
{
    JSContext *cx = (JSContext *) context;

    cx->destroy(cx->runtime);
}

/* Bind a thread and a context
JS_EnterContext binds a thread and a context.
User must execute this procedure before compiling or eveluating JavaScript.*/
void
JS_EnterContext(jsContext_t context)
{
    JSContext *cx = (JSContext *) context;
    //EwbJsZoneResetMax();
    JSContext::enter(cx);
}

/* JS_ExitContext unbinds a thread and a context.
User must execute this procedure after compiling and eveluating JavaScript.
Since the status that multiple contexts are binded influences starting GC,
user must execute the function as soon as possible after compiling or
eveluating JavaScript. */
void
JS_ExitContext(jsContext_t context)
{
#ifndef SHELL
    EwbJsZoneResetMax();
#endif
    JSContext::exit();
}

/* Initialize Standard objects
The function adds standard objects to scope object such as Math,
Date and so on. */
void
JS_InitStandardObjects(jsContext_t context, jsObject_t scope)
{
    JSContext *cx = (JSContext *) context;
    JSScriptable *_scope = (JSScriptable *) scope;

    cx->initStandardObjects((JSScriptableObject *) _scope);
}

/* Object ********************************************************************/
/* Object
JS_NewObject creates a new object according to arguments.
User must call JS_DefineProperties and JS_DefineFunctions functions as
necessary. */
jsObject_t
JS_NewGlobalObject(jsContext_t context, jsClass_t *clazz)
{
    JSContext *cx = (JSContext *) context;
    JSNativeHost *result = new (cx) JSNativeHost(clazz);

    return (jsObject_t) result;
}
/*JS_ConstructObject create a new object with proto object and call construct
  with args.  The proto object is created by JS_DefineClass.*/
jsObject_t
JS_NewPlaneObject(jsContext_t context, jsObject_t scope, jsObject_t proto)
{
    JSContext *cx = (JSContext *) context;
    JSScriptable *_scope = (JSScriptable *) scope;
    JSScriptable *_proto = (JSScriptable *) proto;

    JSNativeHost *result = new (cx) JSNativeHost(_proto);

    result->setParentScope(cx, _scope);
    if (_proto != NULL) {
        result->setPrototype(cx, _proto);
    } else {
        result->setPrototype(cx,
                        JSScriptableObject::getObjectPrototype(cx, _scope));
    }
    return (jsObject_t) result;
}
/*JS_ConstructObjectByName create a new object with name, sucn as "Array",
  "Date" and call construct with args.*/
jsObject_t
JS_NewObject(jsContext_t context, jsObject_t scope, jsString_t constructor,
        int numArgs, jsVal_t *args)
{
    JSContext *cx = (JSContext *) context;
    JSScriptable *_scope = (JSScriptable *) scope;

    return cx->newObject(_scope, constructor, numArgs, args);
}

/* Define Class
   The function creates a new object with native constructor under the scope.
 The returned object is used as proto of JS_NewObject   to create new object.
*/
jsObject_t
JS_DefineClass(jsContext_t context, jsObject_t scope, jsObject_t parent_proto,
        jsClass_t *clazz, jsConstructor_t constructor, int numProperties,
        jsProperty_t *properties, int numFunctions, jsFunction_t *functions,
        int numCtorProperties, jsProperty_t *ctorProperties,
        int numCtorFunctions, jsFunction_t *ctorFunctions)

{
    JSContext *cx = (JSContext *) context;
    JSScriptable *_scope = (JSScriptable *) scope;
    JSScriptable *_parent_proto = (JSScriptable *) parent_proto;
    JSNativeHost *result = new (cx) JSNativeHost(clazz);

    cx->pushLocalVal(JS_OBJECT_TO_VAL(result)); // gc safe 20061124

    if (constructor != NULL) {
        JSScriptableObject::defineClass(cx, _scope, result, constructor);
    } else {
        result->setPrototype(cx,
                        JSScriptableObject::getObjectPrototype(cx, _scope));
        ((JSScriptableObject *) _scope)
                ->defineProperty(cx, result->getClassName(cx),
                                JS_OBJECT_TO_VAL(result), JS_PA_DontEnum);
    }
    result->defineProperties(cx, numProperties, properties); 
    result->defineFunctionProperties(cx, result->getClassName(cx),
                        numFunctions, functions);

    if (constructor != NULL) {
        JSScriptable *ctor = result->getParentScope(cx);

        ((JSScriptableObject *) ctor)->defineProperties(cx,
                                        numCtorProperties, ctorProperties); 
        ((JSScriptableObject *) ctor)->defineFunctionProperties(cx,
                                        ctor->getClassName(cx),
                                        numCtorFunctions, ctorFunctions);
    }
    if (_parent_proto != NULL) {
        result->setPrototype(cx, _parent_proto);
    }
    cx->popLocalVals(1); // gc safe 20061124
    return (jsObject_t) result;
}
/* Set object properties
JS_DefineFunctions adds function properties to an object.
JS_DefineProperties adds properties to an object.
*/
void
JS_DefineFunctions(jsContext_t context, jsObject_t object,
                int numFunctions, jsFunction_t *functions)
{
    JSContext *cx = (JSContext *) context;
    JSScriptable *_object = (JSScriptable *) object;

    ((JSScriptableObject *) _object)->defineFunctionProperties(cx,
                                _object->getClassName(cx), numFunctions,
                                functions);
}
void
JS_DefineProperties(jsContext_t context, jsObject_t object, int numProperties,
                jsProperty_t *properties)
{
    JSContext *cx = (JSContext *) context;
    JSScriptable *_object = (JSScriptable *) object;

     ((JSScriptableObject *) _object)->defineProperties(cx,
                                        numProperties, properties);
}
/* Compile and execute JavaScript
JS_CompileString compiles the string that is JavaScrit program.
JS_ExecuteScript executes the script that is compiled by JS_CompileString.
JS_EvaluateString compiles the string and executes the script.
JS_CallFunction call a function.
*/
jsScript_t
JS_CompileString(jsContext_t context, jsObject_t scope,
                jsString_t string, jsString_t sourceName, int lineno)

{
    JSContext *cx = (JSContext *) context;
    JSScriptable *_scope = (JSScriptable *) scope;

    JSException *ex;

    cx->pushLocalVal(JS_OBJECT_TO_VAL(_scope));

    if ((ex = enterTry(cx)) == NULL) {
#ifdef PERSIST
        JSScript *script;

        if ( strncmp( string, JBFMAG, SJBFMAG ) == 0 ) {
            JSBinaryRandomReader in( string, UINT_MAX );

            script = cx->loadReader( _scope, &in );
        } else {
            JSStringReader in(string);

            script = cx->compileReader(_scope, &in, sourceName, lineno);
        }
#else
        JSStringReader in(string);
        JSScript *script = cx->compileReader(_scope, &in, sourceName, lineno);
#endif

        if (script != NULL) {
            cx->runtime->addRoot((JSNativeScript *) script);
            cx->exceptionHandler->exitTry();
            cx->popLocalVals(1);
#ifndef SHELL
            if(ewbCompileMemShow && EwbJsZoneGetMax() > 0){
              printf("compile %s used %d bytes.\n",sourceName,EwbJsZoneGetMax());
              EwbJsZoneResetMax();
            }
#endif
            return (jsScript_t) script;
        }
        cx->exceptionHandler->exitTry();
    }
    cx->popLocalVals(1);
#ifndef SHELL
    if(ewbCompileMemShow && EwbJsZoneGetMax() > 0){
      printf("compile %s used %d bytes.\n",sourceName,EwbJsZoneGetMax());
      EwbJsZoneResetMax();
    }
#endif
    return NULL;
}
jsVal_t
JS_ExecuteScript(jsContext_t context, jsObject_t scope, jsScript_t script)
{
    JSContext *cx = (JSContext *) context;
    JSScriptable *_scope = (JSScriptable *) scope;
    JSScript *_script = (JSScript *) script;
    JSException *ex;

    if ((ex = enterTry(cx)) == NULL) {
        cx->pushLocalVal(JS_OBJECT_TO_VAL(_scope));
        jsVal_t result = _script->exec(cx, _scope);
        cx->popLocalVals(1);
        cx->exceptionHandler->exitTry();
#ifndef SHELL
            if(ewbCompileMemShow && EwbJsZoneGetMax() > 0){
              printf("execute used %d bytes.\n",EwbJsZoneGetMax());
              EwbJsZoneResetMax();
            }
#endif
        return result;
    }
    cx->popLocalVals(1);
#ifndef SHELL
    if(ewbCompileMemShow && EwbJsZoneGetMax() > 0){
      printf("execute used %d bytes.\n",EwbJsZoneGetMax());
      EwbJsZoneResetMax();
    }
#endif
    return JS_VAL_NULL;
}
jsVal_t
JS_EvaluateString(jsContext_t context, jsObject_t scope,
                jsString_t string, jsString_t sourceName, int lineno)
{
    JSContext *cx = (JSContext *) context;
    JSScriptable *_scope = (JSScriptable *) scope;
#ifdef PERSIST
    jsVal_t tmp = ( strncmp( string, JBFMAG, SJBFMAG ) == 0 ) ?
                        cx->evaluateBinary(_scope, string, UINT_MAX ):
                        cx->evaluateString(_scope, string, sourceName, lineno);
#else
    jsVal_t tmp = cx->evaluateString(_scope, string, sourceName, lineno);
#endif
#ifndef SHELL
    if(ewbCompileMemShow && EwbJsZoneGetMax() > 0){
      printf("evaluate %s used %d bytes.\n",sourceName,EwbJsZoneGetMax());
      EwbJsZoneResetMax();
    }
#endif
    return tmp;

}
void JS_DeleteScript(jsContext_t context, jsScript_t script)
{
    JSContext *cx = (JSContext *) context;
    JSScript *_script = (JSScript *) script;

    cx->runtime->removeRoot((JSNativeScript *) _script);
}
jsVal_t
JS_CallFunction(jsContext_t context, jsObject_t function,
                jsObject_t thisObject, int numArgs, jsVal_t *args)
{
    JSContext *cx = (JSContext *) context;
    JSScriptable *_function = (JSScriptable *) function;
    JSScriptable *_thisObject = (JSScriptable *) thisObject;
    JSException *ex;
    jsVal_t tmp;

    if ((ex = enterTry(cx)) == NULL) { // ichino 20040519
        tmp = ((JSNativeFunction *) _function)
                ->call(cx, _function, _thisObject, numArgs, args);
#ifndef SHELL
        if(ewbCompileMemShow && EwbJsZoneGetMax() > 0){
          printf("callfunc used %d bytes.\n",EwbJsZoneGetMax());
          EwbJsZoneResetMax();
        }
#endif
        return tmp;
        cx->exceptionHandler->exitTry();
    }
    return JS_VAL_VOID;
}
/* Object property operation
JS_GetTopLevelProp returns property of top level scope.  The function traverses scope chain,
get top level scope and search property.
JS_GetPrototype returns prototype of an object.
JS_PutProperty put an object to scope as a named object.
*/
jsObject_t
JS_GetClassPrototype(jsContext_t context, jsObject_t scope,
                const jsString_t className)
{
    JSContext *cx = (JSContext *) context;
    JSScriptable *_scope = (JSScriptable *) scope;

    return (jsObject_t) JSScriptableObject::getClassPrototype(cx, _scope,
                                                        className);
}
jsVal_t
JS_GetTopLevelProp(jsContext_t context, jsObject_t scope, jsString_t id)
{
    JSContext *cx = (JSContext *) context;
    JSScriptable *_scope = (JSScriptable *) scope;
    jsVal_t v;

    (void) JSScriptRuntime::getTopLevelProp(cx, _scope, id, &v);
    return v;
}
jsObject_t
JS_GetPrototype(jsContext_t context, jsObject_t object)
{
    JSContext *cx = (JSContext *) context;
    JSScriptable *_object = (JSScriptable *) object;

    return (jsObject_t) _object->getPrototype(cx);
}
void
JS_PutProperty(jsContext_t context, jsObject_t object, jsString_t name,
        jsVal_t val)
{
    JSContext *cx = (JSContext *) context;
    JSScriptable *_object = (JSScriptable *) object;

    _object->put(cx, name, _object, val);
}
void
JS_PutPropertyById(jsContext_t context, jsObject_t object, int id,
        jsVal_t val)
{
    JSContext *cx = (JSContext *) context;
    JSScriptable *_object = (JSScriptable *) object;

    _object->put(cx, id, _object, val);
}
jsObject_t
JS_GetParentScope(jsContext_t context, jsObject_t object)
{
    JSContext *cx = (JSContext *) context;
    JSScriptable *_object = (JSScriptable *) object;

    return (jsObject_t) _object->getParentScope(cx);
}

/* Object closure
JS_GetContextClosure gets extensive data from a context.
JS_SetObjectContextClosure sets extensive data to a context.
JS_GetObjectClosure gets extensive data from an object.
JS_SetObjectClosure sets extensive data to an object.*/
void *
JS_GetContextClosure(jsContext_t context)
{
    JSContext *cx = (JSContext *) context;

    return cx->getClosure();
}
void
JS_SetContextClosure(jsContext_t context, void *closure)
{
    JSContext *cx = (JSContext *) context;

    cx->setClosure(closure);
}
void *
JS_GetObjectClosure(jsObject_t object)
{
    JSScriptable *_object = (JSScriptable *) object;

    if (_object->isInstanceOf(JSNativeHost::className)) {
        return ((JSNativeHost *) _object)->getClosure();
    }
    return NULL;
}
void
JS_SetObjectClosure(jsObject_t object, void *closure)
{
    JSScriptable *_object = (JSScriptable *) object;

    ((JSNativeHost *) _object)->setClosure(closure);
}
/* Default class
The function gets a default class.  The default class is used
in user defined class to call the default procedure. */
jsClass_t *
JS_DefaultClass()
{
    return JSNativeHost::defaultClass();
}


/* GC ************************************************************************/

/* Root object
JS_AddRoot adds an object as a root object of GC.
JS_RemoveRoot removes an object from root objects of GC.*/
void
JS_AddRoot(jsContext_t context, jsObject_t object)
{
    JSContext *cx = (JSContext *) context;
    JSScriptable *_object = (JSScriptable *) object;

    cx->runtime->addRoot(_object);
}

void
JS_RemoveRoot(jsContext_t context, jsObject_t object)
{
    JSContext *cx = (JSContext *) context;
    JSScriptable *_object = (JSScriptable *) object;

    cx->runtime->removeRoot(_object);
}
void
JS_GC(jsContext_t context)
{
    JSContext *cx = (JSContext *) context;
    cx->runtime->gcHeap.gc( cx );
}
void
JS_GCMemFreeShow(jsContext_t context, int mode)
{
    JSContext *cx = (JSContext *) context;
    cx->runtime->gcHeap.ShowGCFreeBlock(mode);
}
void
JS_GCMemFreeShowDetail(jsContext_t context, int mode)
{
    JSContext *cx = (JSContext *) context;
    cx->runtime->gcHeap.ShowGCFreeBlockDetail(mode);
}
int
JS_GCGetMemFree(jsContext_t context)
{
    JSContext *cx = (JSContext *) context;
    return cx->runtime->gcHeap.GetGCFreeBlock();
}
int
JS_GCGetMaxUse(jsContext_t context)
{
    JSContext *cx = (JSContext *) context;
    return cx->runtime->gcHeap.GetGCMaxUseBlock();
}
void
JS_GCResetMaxUse(jsContext_t context)
{
    JSContext *cx = (JSContext *) context;
    cx->runtime->gcHeap.ResetGCMaxUseBlock();
}
void
JS_ResetByteCodeMaxUse()
{
  JS_ResetRuntimeMaxSize();
}
/* Others ********************************************************************/
/* Branch callback
The function sets branch callback procedure in executing JavaScript
to prevent infinite loop.  The callback is called on backword branch. */
void
JS_SetBranchCallback(jsContext_t context, jsBranchProc_t branch)
{
#ifdef BRANCH
    JSContext *cx = (JSContext *) context;

    cx->setBranchCallback(branch);
#endif
}
/* Error callback
The function enables to define and use own error reporting mechanism in
appilications.*/
void
JS_SetErrorReporter(jsContext_t context, jsErrorReporter_t *reporter)
{
    JSContext *cx = (JSContext *) context;
    JSHostErrorReporter *errorReporter
                        = new (cx->runtime) JSHostErrorReporter(reporter);
    JSErrorReporter *result = cx->setErrorReporter(errorReporter);

    if (result != NULL) {
        result->destroy(cx->runtime);
    }
}
#ifdef MEASURMENT
void    JS_BytecodeCountShow()
{
        JSInterpreter::bytecodeCountShow();
}

void    JS_BytecodeCountReset()
{
        JSInterpreter::bytecodeCountReset();
}
#endif

#ifdef STATS
void    JS_printGCRoots( jsContext_t context )
{
    JSContext *cx = ( JSContext* ) context;
    JSRuntime *_runtime = cx->runtime->keepedRuntime;

    printf("num of GCRoots: %d\n",_runtime->numRoots);
    for (int i = 0; i < _runtime->numRoots; ++i) {
        printf("GCRoots type: %s 0x%p\n",_runtime->roots[i]->getClassName(cx),
               _runtime->roots[i] );
    }
}
#endif

void    JS_ShowICodeMemSize()
{
    JS_ShowRuntimeMem();
}

void JS_RemoveAllProperties(jsContext_t context, jsObject_t object)
{
    JSContext *cx = (JSContext *) context;
    JSScriptable *_object = (JSScriptable *) object;
    
    NOT_USED( cx );
    ((JSScriptableObject *)_object)->removeAllProperties();
}

void JS_ResetAllProperties(jsContext_t context, jsObject_t object)
{
    JSContext *cx = (JSContext *) context;
    JSScriptable *_object = (JSScriptable *) object;
    
    NOT_USED( cx );
    ((JSScriptableObject *)_object)->removeAllProperties();

    JS_InitStandardObjects(context, object);
}

int JS_SetMaxBytes(size_t size)
{
  //JSGCHeap heap_t;
  //heap_t.Allocator.setMaxBytes(size);
    return 0;
}

#if defined(SUNOS5) || defined(LINUX)
static void
showGCMemforSun(){
        //Show JS object partition size.
        printf("### JS object partition ###\n");
        printf("Partition size   = %10u\n",
               (unsigned int)jsGCHeapSize);

        //Show JBytecodeS object partition size.
        printf("### JS bytecode partition ###\n");
        printf("Partition size   = %10u\n",
               (unsigned int)jsByteCodeHeapSize);
        printf("Now Used        = %10u\n",
               (unsigned int)jsBytecodeMemsize);
        printf("MAX Used        = %10u\n",
               (unsigned int)jsBytecodeMemsizeMax);

        printf("MAX Used / Partition size = %3.1f%%\n",
               (((double)jsBytecodeMemsizeMax/(double)jsByteCodeHeapSize)*100));

        //Show compile partition size.
        printf("### JS compile partition ###\n");
        printf("Partition size   = %10u\n",
               (unsigned int)jsZoneHeapSize);
        printf("Now Used        = %10u\n",
               (unsigned int)jsZoneMemsize);
        printf("MAX Used        = %10u\n",
               (unsigned int)jsZoneMemsizeMax);

        printf("MAX Used / Partition size = %3.1f%%\n",
               (((double)jsZoneMemsizeMax/(double)jsZoneHeapSize)*100));

}

static void
changeGCMemSize(int gc, int bytecode, int compile){
  printf("### Enter JS memory size. ###\n");
  jsGCHeapSize = gc;
  jsByteCodeHeapSize = bytecode;
  jsZoneHeapSize = compile;
  printf("### JS memory size changed. ###\n");
  showGCMemforSun();
}

void
JS_ShowGCMemforSun()
{
    showGCMemforSun();
}

void
JS_ChangeGCMemSize(int gc, int bytecode, int compile)
{
    changeGCMemSize(gc, bytecode, compile);
}
#endif
#ifdef PERSIST
void
JS_SaveScript( jsContext_t context, jsObject_t scope, jsScript_t script,
                jsString_t fileName )
{
    JSContext *cx = (JSContext *) context;
    JSScriptable *_scope = (JSScriptable *) scope;
    JSScript *_script = (JSScript *) script;
    JSFileRandomWriter out( fileName );

    cx->saveWriter( _scope, _script, &out );
}
#endif
/*
   Addtional API for LCW
*/
jsBool_t
JS_GetProperty(jsContext_t context, jsObject_t object, jsString_t name,
                jsVal_t *val)
{
    JSContext *cx = (JSContext *) context;
    jsVal_t obj = JS_OBJECT_TO_VAL( (JSScriptable *) object );
    JSScriptable *scope = ( JSScriptable* ) object;

    *val = JSScriptRuntime::getProp(cx, obj, name, scope);
    return TRUE;
}
jsBool_t
JS_GetPropertyById(jsContext_t context, jsObject_t object, int id,
                jsVal_t *val)
{
    JSContext *cx = (JSContext *) context;
    JSScriptable *_object = ( JSScriptable* ) object;

    *val = JSScriptRuntime::getElem( cx, _object, id );
    return TRUE;
}
void
JS_MarkGCThing( jsContext_t context, void* thing )
{
    JSContext *cx = (JSContext *) context;
    JSGCHeap *gcHeap = &cx->runtime->gcHeap;
        
    if ( thing != NULL ) {
        int kind = gcHeap->getObjKind( thing );
    
        if ( kind == JSGCMemory::PTRFREE) {
            gcHeap->markObj(thing);
        } else {
            JSGCNew *gcObj = (JSGCNew *) thing;
    
            gcObj->mark(cx);
        }
    }
}

/* SC22477 -> */
int   
JS_PushLocalVal( jsContext_t context, jsVal_t val )
{
    if ( context == NULL ) return -1;

    JSContext *cx = (JSContext *) context;

    cx->pushLocalVal( val );
    return 0;
}
int
JS_PopLocalVals( jsContext_t context, int n )
{
    if ( context == NULL ) return -1;
    if ( n < 0 ) return -1;

    JSContext *cx = (JSContext *) context;

    cx->popLocalVals( n );
    return 0;
}
/* <- SC22477 */

