/*
 * 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.
 */
/* Header file */
#ifdef VX
#include <string.h>
#include <taskLib.h>
#endif
#include "js-runtime.h"
#include "js-context.h"
#include "js-utils.h"
#include "js-new.h"
#include "js-api.h"
#include "ewb-sys.h"
#include "ewb-sys-if.h"
#include "ewb-mem.h" //ichino 20040513

int runtimeMemSize=0;
int runtimeMemMaxSize=0;
int runtimeMemCount=0;
static int zoneMemSize=0;
static int zoneMemMaxSize=0;
static int zoneMemCount=0;
#if __x86_64 
#define MGR_SIZE 16
#elif defined(SUNOS5) || i386
#define MGR_SIZE 8
#else
#define MGR_SIZE 4
#endif

#if defined(SUNOS5) || defined(LINUX)
int jsBytecodeMemsize = 0;
int jsBytecodeMemsizeMax = 0;
int jsGCMemsize = 0;
int jsZoneMemsize = 0;
int jsZoneMemsizeMax = 0;
int jsGCHeapSize = 30*1024*1024;
int jsByteCodeHeapSize = 10*1024*1024;
int jsZoneHeapSize = 10*1024*1024;
#endif

static void *
runtime_malloc(JSRuntime *runtime, size_t size);
extern  int ewbPrintOn;

//ichino debug
#ifndef SHELL
# include "ewb-trace.h"
# include "ewb-dbg.h"
  int count_runtime = 0;
#endif

/* Procedures */
void *
JS_NewRuntimeObj(JSRuntime *runtime, size_t size)
{
#if 1
    char* ptr_t;
    int *num;
    ptr_t = (char*)runtime_malloc(runtime,size+MGR_SIZE);
    num = (int*)ptr_t;
    *num = size;
    runtimeMemSize+=size;
    if(runtimeMemSize > runtimeMemMaxSize) runtimeMemMaxSize = runtimeMemSize;
    runtimeMemCount++;
    ptr_t += MGR_SIZE;
    return((void*)ptr_t);
#else
    return runtime->byteCodeHeap.malloc(size);
#endif
}

static void *
runtime_malloc(JSRuntime *runtime, size_t size)
{
    extern int ewbPrintOn;
    void *ptr_t = runtime->byteCodeHeap.malloc(size);
    if(ptr_t == NULL){
        JSContext *cx;
        cx = JSContext::getCurrentContext();
	if( ewbPrintOn ) {printf("Call GC. Because EWB ByteCode mem Exhaused. But, This is no problem.");}

	char jsLogbuf[128];
	memset(jsLogbuf, 0, sizeof(jsLogbuf));
	sprintf(jsLogbuf,"Call GC from BytecodePart size:%d. 1st Log is Befor GC. 2nd is after.\n",size);
	EwbSetLog(jsLogbuf);
        if ( cx != NULL ) {
            JS_GCMemFreeShow(cx, 1);
            JS_GC(cx);
            JS_GCMemFreeShow(cx, 1);
        }

	ptr_t = runtime->byteCodeHeap.malloc(size);
	if(ptr_t == NULL){
	    EwbSetLog("JS ByteCode Memory Exhaused.  Be necessary to expand JS ByteCode Memory.\n");
#ifndef SHELL
	    EwbNotifyError(EWB_ERROR_JS_MEMORY);
#endif
            #if defined(SUNOS5) || defined(LINUX)
	        exit(1);
            #elif defined(VX)
	        taskSuspend( 0 );
            #else
	        ->
            #endif
	}
    }
    return ptr_t;
}

void
JS_DeleteRuntimeObj(JSRuntime *runtime, void *ptr)
{
#if 1
    char* ptr_t = (char*)ptr;
    ptr_t -= MGR_SIZE;
    int *num = (int*)ptr_t;
    int num_t = *num;
    runtimeMemSize -= num_t;
    runtimeMemCount--;
    runtime->byteCodeHeap.free((void*)ptr_t);
#else
    runtime->byteCodeHeap.free(ptr);
#endif
}

void
JS_ShowRuntimeMem()
{
    printf("JS_InterPreterCode use Present:%d MAX:%d count:%d\n"
	 ,runtimeMemSize,runtimeMemMaxSize,runtimeMemCount);
    printf("JS_compile use Present:%d MAX:%d count:%d\n"
	 ,zoneMemSize,zoneMemMaxSize,zoneMemCount);
}

void *
JS_NewGCNormalObj(JSContext *cx, size_t size)
{
    return cx->runtime->gcHeap.newNormalObj(cx, size);
}
void *
JS_NewGCObj(JSContext *cx, size_t size)
{
    if (ewbPrintOn) {
        if(size > 1024 && cx->interpreterSourceFile != NULL){
	    printf("<warning>Object allocate %d bytes. Recommend cutdown or divide object %s\n",
	       size, cx->interpreterSourceFile);
        }
    }
        return cx->runtime->gcHeap.newObj(cx, size);
}
jsString_t
JS_NewGCString(JSContext *cx, jsString_t string)
{
#ifdef COMPACT_MEM
    jsString_t newString = cx->runtime->hasGCString(string);

    if (newString != NULL) {
        cx->addNewBorn(newString);
        return newString;
    }

    int length = strlen(string) + 1;

    newString = (jsString_t) JS_NewGCObj(cx, sizeof (*newString) * length);
    memcpy(newString, string, sizeof (*newString) * length);
    cx->runtime->setGCString(newString);
    return newString;
#else /* !COMPACT_MEM */
    jsString_t newString;
    int length = strlen(string) + 1;

    newString = (jsString_t) JS_NewGCObj(cx, sizeof (*newString) * length);
    memcpy(newString, string, sizeof (*newString) * length);
    return newString;
#endif /* COMPACT_MEM */
}
double *
JS_NewGCDouble(JSContext *cx, double d)
{
    double *dp;

    dp = (double *) JS_NewGCObj(cx, sizeof (double));
    *dp = d;
    return dp;
}
void *
_JS_NewZoneObj(JSContext *cx, size_t size)
{
    return cx->zone->malloc(cx, size, JSGCMemory::PTRFREE);
}
void
_JS_DeleteZoneObj(JSContext *cx, void *ptr)
{
    cx->zone->free(ptr);
}
jsString_t
JS_NewZoneString(JSContext *cx, jsString_t string)
{
    jsString_t newString;
    
    if(string != NULL){
	int length = strlen(string) + 1;	    
	newString = (jsString_t) JS_NewZoneObj(cx, sizeof (*newString) * length);
	memcpy(newString, string, sizeof (*newString) * length);
    }else{
	newString = (jsString_t) JS_NewZoneObj(cx, sizeof (*newString) * 1);
	strcpy(newString, " ");
    }
    return newString;
}
void
JS_ResetRuntimeMaxSize()
{
    runtimeMemMaxSize = 0;
}
