Commit 6f821c8d authored by mjs's avatar mjs
Browse files

Merged changes from LABYRINTH_KDE_3_MERGE branch.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@798 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent f54a76f3
......@@ -4,6 +4,8 @@ noinst_LIBRARIES = libkjs.o
libkjs_o_LDFLAGS = -Wl,-r -nostdlib
libkjs_o_AR = $(OBJCXXLD) $(AM_OBJCXXFLAGS) $(OBJCXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) $(libkjs_o_LDFLAGS) -o
INCLUDES = $(KWQ_INCLUDES)
libkjs_o_SOURCES = \
array_object.cpp \
array_object.h \
......@@ -21,13 +23,12 @@ libkjs_o_SOURCES = \
function.h \
function_object.cpp \
function_object.h \
global_object.cpp \
grammar.cpp \
grammar.h \
internal.cpp \
internal.h \
kjs.cpp \
kjs.h \
interpreter.cpp \
interpreter.h \
lexer.cpp \
lexer.h \
lexer.lut.h \
......@@ -46,6 +47,8 @@ libkjs_o_SOURCES = \
object_object.h \
operations.cpp \
operations.h \
property_map.cpp \
property_map.h \
regexp.cpp \
regexp.h \
regexp_object.cpp \
......@@ -56,6 +59,8 @@ libkjs_o_SOURCES = \
types.h \
ustring.cpp \
ustring.h \
value.cpp \
value.h \
$(NULL)
noinst_PROGRAMS = testkjs
......@@ -75,7 +80,29 @@ grammar-stamp: grammar.y
ln -sf grammar.cpp.h grammar.h
touch ./grammar-stamp
BUILT_SOURCES = $(GRAMMAR_FILES) grammar-stamp
LUT_FILES = math_object.lut.h lexer.lut.h array_object.lut.h date_object.lut.h string_object.lut.h number_object.lut.h
lexer.lut.h: keywords.table
./create_hash_table keywords.table -i > lexer.lut.h;
array_object.lut.h: array_object.cpp
./create_hash_table array_object.cpp -i > array_object.lut.h
math_object.lut.h: math_object.cpp
./create_hash_table math_object.cpp -i > math_object.lut.h
date_object.lut.h: date_object.cpp
./create_hash_table date_object.cpp -i > date_object.lut.h
number_object.lut.h: number_object.cpp
./create_hash_table number_object.cpp -i > number_object.lut.h
string_object.lut.h: string_object.cpp
./create_hash_table string_object.cpp -i > string_object.lut.h
BUILT_SOURCES = $(GRAMMAR_FILES) $(LUT_FILES) grammar-stamp
CLEANFILES = $(BUILT_SOURCES)
This diff is collapsed.
// -*- c-basic-offset: 2 -*-
/*
* This file is part of the KDE libraries
* Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
......@@ -15,39 +16,64 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id$
*/
#ifndef _ARRAY_OBJECT_H_
#define _ARRAY_OBJECT_H_
#include "object.h"
#include "function.h"
#include "internal.h"
#include "function_object.h"
namespace KJS {
class ArrayObject : public ConstructorImp {
class ArrayInstanceImp : public ObjectImp {
public:
ArrayObject(const Object &funcProto, const Object &arrayProto);
Completion execute(const List &);
Object construct(const List &);
ArrayInstanceImp(const Object &proto);
virtual void put(ExecState *exec, const UString &propertyName, const Value &value, int attr = None);
virtual void putDirect(ExecState *exec, const UString &propertyName, const Value &value, int attr = None);
virtual const ClassInfo *classInfo() const { return &info; }
static const ClassInfo info;
};
class ArrayPrototype : public ObjectImp {
class ArrayPrototypeImp : public ArrayInstanceImp {
public:
ArrayPrototype(const Object& proto);
virtual KJSO get(const UString &p) const;
ArrayPrototypeImp(ExecState *exec,
ObjectPrototypeImp *objProto);
Value get(ExecState *exec, const UString &p) const;
virtual const ClassInfo *classInfo() const { return &info; }
static const ClassInfo info;
};
class ArrayProtoFunc : public InternalFunctionImp {
class ArrayProtoFuncImp : public InternalFunctionImp {
public:
ArrayProtoFunc(int i) : id(i) { }
Completion execute(const List &);
ArrayProtoFuncImp(ExecState *exec, int i, int len);
virtual bool implementsCall() const;
virtual Value call(ExecState *exec, Object &thisObj, const List &args);
enum { ToString, ToLocaleString, Concat, Join, Pop, Push,
Reverse, Shift, Slice, Sort, Splice, UnShift };
private:
int id;
};
class ArrayObjectImp : public InternalFunctionImp {
public:
ArrayObjectImp(ExecState *exec,
FunctionPrototypeImp *funcProto,
ArrayPrototypeImp *arrayProto);
virtual bool implementsConstruct() const;
virtual Object construct(ExecState *exec, const List &args);
virtual bool implementsCall() const;
virtual Value call(ExecState *exec, Object &thisObj, const List &args);
};
}; // namespace
#endif
// -*- c-basic-offset: 2 -*-
/*
* This file is part of the KDE libraries
* Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
......@@ -15,89 +16,134 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "kjs.h"
#include "operations.h"
#include "value.h"
#include "object.h"
#include "types.h"
#include "interpreter.h"
#include "operations.h"
#include "bool_object.h"
#include "error_object.h"
#include <assert.h>
using namespace KJS;
BooleanObject::BooleanObject(const KJSO& funcProto, const KJSO &booleanProto)
: ConstructorImp(funcProto, 1)
// ------------------------------ BooleanInstanceImp ---------------------------
const ClassInfo BooleanInstanceImp::info = {"Boolean", 0, 0, 0};
BooleanInstanceImp::BooleanInstanceImp(const Object &proto)
: ObjectImp(proto)
{
// Boolean.prototype
setPrototypeProperty(booleanProto);
}
// ECMA 15.6.1
Completion BooleanObject::execute(const List &args)
{
Boolean b;
// ------------------------------ BooleanPrototypeImp --------------------------
if (args.isEmpty())
b = Boolean(false);
else
b = args[0].toBoolean();
// ECMA 15.6.4
BooleanPrototypeImp::BooleanPrototypeImp(ExecState *exec,
ObjectPrototypeImp *objectProto,
FunctionPrototypeImp *funcProto)
: BooleanInstanceImp(Object(objectProto))
{
Value protect(this);
// The constructor will be added later by InterpreterImp::InterpreterImp()
return Completion(ReturnValue, b);
put(exec,"toString", Object(new BooleanProtoFuncImp(exec,funcProto,BooleanProtoFuncImp::ToString,0)), DontEnum);
put(exec,"valueOf", Object(new BooleanProtoFuncImp(exec,funcProto,BooleanProtoFuncImp::ValueOf,0)), DontEnum);
setInternalValue(Boolean(false));
}
// ECMA 15.6.2
Object BooleanObject::construct(const List &args)
{
Boolean b;
if (args.size() > 0)
b = args.begin()->toBoolean();
else
b = Boolean(false);
return Object::create(BooleanClass, b);
// ------------------------------ BooleanProtoFuncImp --------------------------
BooleanProtoFuncImp::BooleanProtoFuncImp(ExecState *exec,
FunctionPrototypeImp *funcProto, int i, int len)
: InternalFunctionImp(funcProto), id(i)
{
Value protect(this);
put(exec,"length",Number(len),DontDelete|ReadOnly|DontEnum);
}
// ECMA 15.6.4
BooleanPrototype::BooleanPrototype(const Object& proto)
: ObjectImp(BooleanClass, Boolean(false), proto)
bool BooleanProtoFuncImp::implementsCall() const
{
// The constructor will be added later in BooleanObject's constructor
return true;
}
KJSO BooleanPrototype::get(const UString &p) const
// ECMA 15.6.4.2 + 15.6.4.3
Value BooleanProtoFuncImp::call(ExecState *exec, Object &thisObj, const List &/*args*/)
{
if (p == "toString")
return Function(new BooleanProtoFunc(ToString));
else if (p == "valueOf")
return Function(new BooleanProtoFunc(ValueOf));
// no generic function. "this" has to be a Boolean object
if (!thisObj.inherits(&BooleanInstanceImp::info)) {
Object err = Error::create(exec,TypeError);
exec->setException(err);
return err;
}
// execute "toString()" or "valueOf()", respectively
Value v = thisObj.internalValue();
assert(!v.isNull());
if (id == ToString)
return String(v.toString(exec));
else
return Imp::get(p);
return Boolean(v.toBoolean(exec)); /* TODO: optimize for bool case */
}
BooleanProtoFunc::BooleanProtoFunc(int i)
: id(i)
// ------------------------------ BooleanObjectImp -----------------------------
BooleanObjectImp::BooleanObjectImp(ExecState *exec, FunctionPrototypeImp *funcProto,
BooleanPrototypeImp *booleanProto)
: InternalFunctionImp(funcProto)
{
Value protect(this);
put(exec,"prototype", Object(booleanProto),DontEnum|DontDelete|ReadOnly);
// no. of arguments for constructor
put(exec,"length", Number(1), ReadOnly|DontDelete|DontEnum);
}
// ECMA 15.6.4.2 + 15.6.4.3
Completion BooleanProtoFunc::execute(const List &)
{
KJSO result;
Object thisObj = Object::dynamicCast(thisValue());
bool BooleanObjectImp::implementsConstruct() const
{
return true;
}
// no generic function. "this" has to be a Boolean object
if (thisObj.isNull() || thisObj.getClass() != BooleanClass) {
result = Error::create(TypeError);
return Completion(ReturnValue, result);
}
// ECMA 15.6.2
Object BooleanObjectImp::construct(ExecState *exec, const List &args)
{
Object proto = exec->interpreter()->builtinBooleanPrototype();
Object obj(new BooleanInstanceImp(proto));
// execute "toString()" or "valueOf()", respectively
KJSO v = thisObj.internalValue();
if (id == BooleanPrototype::ToString)
result = v.toString();
Boolean b;
if (args.size() > 0)
b = args.begin()->toBoolean(exec);
else
result = v.toBoolean();
b = Boolean(false);
obj.setInternalValue(b);
return obj;
}
bool BooleanObjectImp::implementsCall() const
{
return true;
}
return Completion(ReturnValue, result);
// ECMA 15.6.1
Value BooleanObjectImp::call(ExecState *exec, Object &/*thisObj*/, const List &args)
{
if (args.isEmpty())
return Boolean(false);
else
return Boolean(args[0].toBoolean(exec)); /* TODO: optimize for bool case */
}
// -*- c-basic-offset: 2 -*-
/*
* This file is part of the KDE libraries
* Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
......@@ -15,38 +16,76 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id$
*/
#ifndef _BOOL_OBJECT_H_
#define _BOOL_OBJECT_H_
#include "object.h"
#include "function.h"
#include "internal.h"
#include "function_object.h"
namespace KJS {
class BooleanObject : public ConstructorImp {
class BooleanInstanceImp : public ObjectImp {
public:
BooleanObject(const KJSO& funcProto, const KJSO &booleanProto);
Completion execute(const List &);
Object construct(const List &);
BooleanInstanceImp(const Object &proto);
virtual const ClassInfo *classInfo() const { return &info; }
static const ClassInfo info;
};
class BooleanPrototype : public ObjectImp {
/**
* @internal
*
* The initial value of Boolean.prototype (and thus all objects created
* with the Boolean constructor
*/
class BooleanPrototypeImp : public BooleanInstanceImp {
public:
BooleanPrototype(const Object& proto);
virtual KJSO get(const UString &p) const;
enum { ToString, ValueOf };
BooleanPrototypeImp(ExecState *exec,
ObjectPrototypeImp *objectProto,
FunctionPrototypeImp *funcProto);
};
class BooleanProtoFunc : public InternalFunctionImp {
/**
* @internal
*
* Class to implement all methods that are properties of the
* Boolean.prototype object
*/
class BooleanProtoFuncImp : public InternalFunctionImp {
public:
BooleanProtoFunc(int i);
Completion execute(const List &);
BooleanProtoFuncImp(ExecState *exec,
FunctionPrototypeImp *funcProto, int i, int len);
virtual bool implementsCall() const;
virtual Value call(ExecState *exec, Object &thisObj, const List &args);
enum { ToString, ValueOf };
private:
int id;
};
/**
* @internal
*
* The initial value of the the global variable's "Boolean" property
*/
class BooleanObjectImp : public InternalFunctionImp {
friend class BooleanProtoFuncImp;
public:
BooleanObjectImp(ExecState *exec, FunctionPrototypeImp *funcProto,
BooleanPrototypeImp *booleanProto);
virtual bool implementsConstruct() const;
virtual Object construct(ExecState *exec, const List &args);
virtual bool implementsCall() const;
virtual Value call(ExecState *exec, Object &thisObj, const List &args);
};
}; // namespace
#endif
// -*- c-basic-offset: 2 -*-
/*
* This file is part of the KDE libraries
* Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
* Copyright (C) 2001 Peter Kelly (pmk@post.com)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
......@@ -15,15 +17,19 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id$
*/
#include "collector.h"
#include "object.h"
#include "internal.h"
#include <stdio.h>
#include <string.h>
#include <assert.h>
#ifdef KJS_DEBUG_MEM
#include <typeinfo>
#endif
namespace KJS {
......@@ -61,6 +67,12 @@ CollectorBlock* Collector::root = 0L;
CollectorBlock* Collector::currentBlock = 0L;
unsigned long Collector::filled = 0;
unsigned long Collector::softLimit = KJS_MEM_INCREMENT;
unsigned long Collector::timesFilled = 0;
unsigned long Collector::increaseLimitAt = 1;
bool Collector::memLimitReached = false;
#ifdef KJS_DEBUG_MEM
bool Collector::collecting = false;
#endif
......@@ -70,18 +82,35 @@ void* Collector::allocate(size_t s)
if (s == 0)
return 0L;
// Try and deal with memory requirements in a scalable way. Simple scripts
// should only require small amounts of memory, but for complex scripts we don't
// want to end up running the garbage collector hundreds of times a second.
if (filled >= softLimit) {
timesFilled++;
collect();
if (filled >= softLimit && softLimit < KJS_MEM_LIMIT) // we are actually using all this memory
if (filled >= softLimit && softLimit < KJS_MEM_LIMIT) {
// Even after collection we are still using more than the limit, so increase
// the limit
softLimit *= 2;
}
else if (timesFilled == increaseLimitAt && increaseLimitAt < 128) {
// The allowed memory limit keeps getting reached (lots of objects created
// and deleted). Increase it a bit so GC gets run less often.
timesFilled = 0;
softLimit *= 2;
increaseLimitAt *= 2;
}
}
void *m = malloc(s);
#ifdef KJS_DEBUG_MEM
//fprintf( stderr, "allocate: size=%d valueimp=%p\n",s,m);
#endif
// hack to ensure obj is protected from GC before any constructors are run
// (prev = marked, next = gcallowed)
static_cast<Imp*>(m)->prev = 0;
static_cast<Imp*>(m)->next = 0;
// VI_CREATED and VI_GCALLOWED being unset ensure that value
// is protected from GC before any constructors are run
static_cast<ValueImp*>(m)->_flags = 0;
if (!root) {
root = new CollectorBlock(BlockSize);
......@@ -98,7 +127,7 @@ void* Collector::allocate(size_t s)
if (block->filled >= block->size) {
#ifdef KJS_DEBUG_MEM
printf("allocating new block of size %d\n", block->size);
//fprintf( stderr, "allocating new block of size %d\n", block->size);
#endif
CollectorBlock *tmp = new CollectorBlock(BlockSize);
block->next = tmp;
......@@ -115,7 +144,8 @@ void* Collector::allocate(size_t s)
block->filled++;
if (softLimit >= KJS_MEM_LIMIT) {
KJScriptImp::setException("Out of memory");
memLimitReached = true;
fprintf(stderr,"Out of memory");
}
return m;
......@@ -124,88 +154,125 @@ void* Collector::allocate(size_t s)
/**
* Mark-sweep garbage collection.
*/
void Collector::collect()
bool Collector::collect()
{
#ifdef KJS_DEBUG_MEM
printf("collecting %d objects total\n", Imp::count);
collecting = true;
fprintf(stderr,"Collector::collect()\n");
#endif
// MARK: first set all ref counts to 0 ....
bool deleted = false;
// MARK: first unmark everything
CollectorBlock *block = root;
while (block) {
#ifdef KJS_DEBUG_MEM
printf("cleaning block filled %d out of %d\n", block->filled, block->size);
#endif
Imp **r = (Imp**)block->mem;
ValueImp **r = (ValueImp**)block->mem;
assert(r);
for (int i = 0; i < block->size; i++, r++)
if (*r) {
(*r)->setMarked(false);
(*r)->_flags &= ~ValueImp::VI_MARKED;
}
block = block->next;
}
// ... increase counter for all referenced objects recursively
// mark all referenced objects recursively
// starting out from the set of root objects
if (KJScriptImp::hook) {
KJScriptImp *scr = KJScriptImp::hook;
if (InterpreterImp::s_hook) {
InterpreterImp *scr = InterpreterImp::s_hook;
do {
//fprintf( stderr, "Collector marking interpreter %p\n",(void*)scr);
scr->mark();
scr = scr->next;
} while (scr != KJScriptImp::hook);
} while (scr != InterpreterImp::s_hook);
}
// mark any other objects that we wouldn't delete anyway
block = root;
while (block) {
Imp **r = (Imp**)block->mem;
ValueImp **r = (ValueImp**)block->mem;
assert(r);
for (int i = 0; i < block->size; i++, r++)
if (*r && (*r)->created() && ((*r)->refcount || !(*r)->gcAllowed()) && !(*r)->marked())
(*r)->mark();
{
ValueImp *imp = (*r);
// Check for created=true, marked=false and (gcallowed=false or refcount>0)
if (imp &&
(imp->_flags & (ValueImp::VI_CREATED|ValueImp::VI_MARKED)) == ValueImp::VI_CREATED &&
( (imp->_flags & ValueImp::VI_GCALLOWED) == 0 || imp->refcount ) ) {
//fprintf( stderr, "Collector marking imp=%p\n",(void*)imp);
imp->mark();
}
}
block = block->next;
}
// SWEEP: delete everything with a zero refcount (garbage)