Compare commits
345 Commits
src
...
tags/furte
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a617ee3a29 | ||
|
|
52d6b91235 | ||
|
|
55dc58958a | ||
|
|
682df8db3e | ||
|
|
8ed39db9a8 | ||
|
|
33d0464867 | ||
|
|
490b91850b | ||
|
|
25da940352 | ||
|
|
f0ca36ba7d | ||
|
|
480dbe043f | ||
|
|
19b9471938 | ||
|
|
68fe0d88b6 | ||
|
|
a6fcbc6e38 | ||
|
|
a0f85cea3a | ||
|
|
3f5735fcf7 | ||
|
|
0ab0796234 | ||
|
|
0e145d79c2 | ||
|
|
3e89c252c4 | ||
|
|
6e0204a004 | ||
|
|
4b9ed1baa8 | ||
|
|
b9f4c69e12 | ||
|
|
5f6a0b9c3a | ||
|
|
f68735a6bb | ||
|
|
8616bd54f5 | ||
|
|
09e0785f68 | ||
|
|
dd8953010a | ||
|
|
a67d8ed2fe | ||
|
|
935f0e5ac8 | ||
|
|
97aa1f7699 | ||
|
|
f399e21216 | ||
|
|
823cb6e29e | ||
|
|
84e135cd01 | ||
|
|
ac3516411a | ||
|
|
db237360fa | ||
|
|
92e443d317 | ||
|
|
87c9e8ae4d | ||
|
|
3fa38c1d6a | ||
|
|
ce487f127c | ||
|
|
cc1651828e | ||
|
|
22f7fd9b4a | ||
|
|
ad72e12927 | ||
|
|
b6ada3318c | ||
|
|
82ac5c4e2f | ||
|
|
5430e4b688 | ||
|
|
33219cbcb1 | ||
|
|
e10c7eb54b | ||
|
|
70bd48b576 | ||
|
|
6bc17963c7 | ||
|
|
168c0f6f50 | ||
|
|
eef72a91bc | ||
|
|
76e06e7e4d | ||
|
|
6d03a825d3 | ||
|
|
9a0cc72a2d | ||
|
|
6139484b7e | ||
|
|
b576db0575 | ||
|
|
1858d69e49 | ||
|
|
76326b2efb | ||
|
|
06a7abeacf | ||
|
|
2ae04afc70 | ||
|
|
754415d2a7 | ||
|
|
d719a6f851 | ||
|
|
cdcef88024 | ||
|
|
34fd322859 | ||
|
|
d848312079 | ||
|
|
cdc32c49b5 | ||
|
|
93a992bb20 | ||
|
|
256ad44f6c | ||
|
|
c76f45fb75 | ||
|
|
a7a3555cc8 | ||
|
|
3140821cd1 | ||
|
|
befd55d8ba | ||
|
|
3962bfda99 | ||
|
|
faca6b626e | ||
|
|
8c1af11605 | ||
|
|
6c8f42225c | ||
|
|
847bebb065 | ||
|
|
2c9b897958 | ||
|
|
b01cc3080f | ||
|
|
9cd7750dd1 | ||
|
|
ed9c4d7ee1 | ||
|
|
ceb34941c8 | ||
|
|
f20e53875b | ||
|
|
7c8275aae3 | ||
|
|
30e0d801a7 | ||
|
|
a899984e09 | ||
|
|
54e5a64304 | ||
|
|
4016979d0d | ||
|
|
663693cafe | ||
|
|
aed4dd4310 | ||
|
|
6c7c73d822 | ||
|
|
28c93d2218 | ||
|
|
ca95b9b63a | ||
|
|
67d738630a | ||
|
|
f018a06aa7 | ||
|
|
eb89b3d136 | ||
|
|
6c156d7134 | ||
|
|
7f123a804d | ||
|
|
ec0edbcba0 | ||
|
|
2687debc8e | ||
|
|
5fb184d473 | ||
|
|
4885772ba8 | ||
|
|
3d0da2df12 | ||
|
|
030655be79 | ||
|
|
c21e3de07e | ||
|
|
f654a47a49 | ||
|
|
c11ef38890 | ||
|
|
d8f121d794 | ||
|
|
47f4088f27 | ||
|
|
9d8444be44 | ||
|
|
0bd94e4384 | ||
|
|
e0a486e300 | ||
|
|
4bf9c6a227 | ||
|
|
3277bdac18 | ||
|
|
87c868ffbe | ||
|
|
5f6bbab561 | ||
|
|
55cebfe0cb | ||
|
|
26c815ff77 | ||
|
|
facfc365cb | ||
|
|
63ace590d6 | ||
|
|
31c250eee9 | ||
|
|
60b5308f58 | ||
|
|
d2b9c6a168 | ||
|
|
b6525cde8b | ||
|
|
c4741a81fe | ||
|
|
0649a670ac | ||
|
|
d418df2eb7 | ||
|
|
e86bd6fd57 | ||
|
|
6d79b5ec64 | ||
|
|
46800959c2 | ||
|
|
e29596b37b | ||
|
|
1419ca574a | ||
|
|
e5892b8370 | ||
|
|
60fe37f18d | ||
|
|
98c0f47746 | ||
|
|
55a926e2c4 | ||
|
|
f7387ecdae | ||
|
|
ecf83e4f36 | ||
|
|
7d02cdd1c2 | ||
|
|
0bd5df16b7 | ||
|
|
145eb6f922 | ||
|
|
f98b15d6d3 | ||
|
|
da9f65325b | ||
|
|
25bbd958a9 | ||
|
|
3e8f4b2074 | ||
|
|
6547ff01ff | ||
|
|
dd55af2615 | ||
|
|
619f867c2d | ||
|
|
2ffc6eb8cf | ||
|
|
444ed356ed | ||
|
|
ad709b1cfa | ||
|
|
90dc42fec0 | ||
|
|
7b3a25dde6 | ||
|
|
3b086e1130 | ||
|
|
43ea6c73ea | ||
|
|
8b37303301 | ||
|
|
a9d4091b08 | ||
|
|
0e74fd5849 | ||
|
|
9bbc9990a2 | ||
|
|
5cea729be2 | ||
|
|
c7838f766a | ||
|
|
d6adc823ec | ||
|
|
65fea2e956 | ||
|
|
bc6d33a86b | ||
|
|
f9446c3323 | ||
|
|
f2dde02af9 | ||
|
|
41ebf8c0e0 | ||
|
|
ab971b977f | ||
|
|
9c77f182aa | ||
|
|
b25aef6c55 | ||
|
|
a82b563a25 | ||
|
|
02314c78f6 | ||
|
|
425d07341a | ||
|
|
268dfb88cb | ||
|
|
bc2ec58a7b | ||
|
|
cf373daa53 | ||
|
|
7fe8465ded | ||
|
|
37ec2963c9 | ||
|
|
5ea0bc5e25 | ||
|
|
a492c3a964 | ||
|
|
a256793772 | ||
|
|
fa7759865b | ||
|
|
7a57c4b47a | ||
|
|
a2ebae060e | ||
|
|
a8dc44aaa9 | ||
|
|
3c18b0c3ba | ||
|
|
c122de69b8 | ||
|
|
4a3d57e324 | ||
|
|
a3f846bbf0 | ||
|
|
189fd42355 | ||
|
|
63410ef469 | ||
|
|
7f25afca90 | ||
|
|
81d08cb271 | ||
|
|
deefcc6b8d | ||
|
|
e9b1c82736 | ||
|
|
27a80cf6d2 | ||
|
|
1022f9e0ce | ||
|
|
c9bb9195dd | ||
|
|
095999e32b | ||
|
|
d76a5a9080 | ||
|
|
a70e9a2aaa | ||
|
|
e359fd71fc | ||
|
|
04e1b5c3d1 | ||
|
|
fa2407ee2e | ||
|
|
49bb4bd95c | ||
|
|
3c49adc57b | ||
|
|
3f7cdf786b | ||
|
|
78fba657bd | ||
|
|
5b6a656e48 | ||
|
|
fbbe5d2674 | ||
|
|
d9d717001f | ||
|
|
1dde42d623 | ||
|
|
1ed0446da5 | ||
|
|
3fd73fdffd | ||
|
|
cfa1a86909 | ||
|
|
6b78529f1f | ||
|
|
4fd0fc55ca | ||
|
|
b1e460a74a | ||
|
|
a5a20628a0 | ||
|
|
d9eb58cdec | ||
|
|
037c43596e | ||
|
|
79b38ca130 | ||
|
|
2f59039158 | ||
|
|
d32e31eda5 | ||
|
|
ccf4b130af | ||
|
|
c66acfa187 | ||
|
|
89d32f85be | ||
|
|
0f8d890868 | ||
|
|
3c8ae5aafe | ||
|
|
f909920e91 | ||
|
|
ad73f38c85 | ||
|
|
e18fa8a56f | ||
|
|
e81b4d3657 | ||
|
|
19c49a56be | ||
|
|
3e2489f92c | ||
|
|
b9e217c7e8 | ||
|
|
940ee6966f | ||
|
|
13337f0a89 | ||
|
|
aabb8920ae | ||
|
|
bd32e33753 | ||
|
|
c68e984b99 | ||
|
|
35b4a8183d | ||
|
|
f746d5d6c5 | ||
|
|
dccd95eeaa | ||
|
|
0dc9a5a868 | ||
|
|
f46f66eea8 | ||
|
|
8ade5f78d3 | ||
|
|
58a8a3d984 | ||
|
|
e539af4e6f | ||
|
|
27e172913a | ||
|
|
b54505be31 | ||
|
|
2433dae015 | ||
|
|
c2bcde8466 | ||
|
|
90fb1dfb90 | ||
|
|
132d1f5b26 | ||
|
|
4c69c950da | ||
|
|
d5329cfd00 | ||
|
|
83cb0cf419 | ||
|
|
d3eee3f5c6 | ||
|
|
c78787a61a | ||
|
|
fd99e42a1e | ||
|
|
f536714915 | ||
|
|
16977a5881 | ||
|
|
d58d92ba30 | ||
|
|
70aa311f1a | ||
|
|
d6d4547e60 | ||
|
|
cddb4bee49 | ||
|
|
215e4f521a | ||
|
|
b374ece734 | ||
|
|
db88d15e60 | ||
|
|
17a3a3fede | ||
|
|
802ea94da2 | ||
|
|
87987c22eb | ||
|
|
92e75b047c | ||
|
|
d72d172d7a | ||
|
|
8e7b173eef | ||
|
|
d898e8430d | ||
|
|
55edce6a15 | ||
|
|
f962f59ccc | ||
|
|
75187e5e57 | ||
|
|
3522f2112e | ||
|
|
b2bc5afac7 | ||
|
|
1b857628d4 | ||
|
|
4034d6af4c | ||
|
|
1d5e647e2c | ||
|
|
2aabababd7 | ||
|
|
024311a2ab | ||
|
|
55fcddec90 | ||
|
|
0c95c94909 | ||
|
|
8da98334c6 | ||
|
|
defa10fc43 | ||
|
|
f0cdddb20c | ||
|
|
a17e03c381 | ||
|
|
595794ecfe | ||
|
|
1a0b1b8a29 | ||
|
|
670d4d69fa | ||
|
|
c5a6bb1af7 | ||
|
|
00a574acf2 | ||
|
|
68900225d1 | ||
|
|
97a1eacae2 | ||
|
|
1061a7961a | ||
|
|
95f197f31a | ||
|
|
aeb19b804e | ||
|
|
22b83ef992 | ||
|
|
cf89f9dbea | ||
|
|
b9f52d961c | ||
|
|
b9b66713eb | ||
|
|
3287009b56 | ||
|
|
d0ad9c946c | ||
|
|
b3c707fd61 | ||
|
|
03332fd3ac | ||
|
|
ef97812295 | ||
|
|
ca0614a7b6 | ||
|
|
4c1594b677 | ||
|
|
914637bd3e | ||
|
|
91dbe3c171 | ||
|
|
c3bd0c5f7d | ||
|
|
cff140c431 | ||
|
|
923990dd99 | ||
|
|
45291c870a | ||
|
|
33d0d8a72b | ||
|
|
2066c6b9ce | ||
|
|
46e77ac0e1 | ||
|
|
7507e060b5 | ||
|
|
1cc86f1b54 | ||
|
|
a4156ea8c1 | ||
|
|
4e17e7d0b6 | ||
|
|
0b9f4a6066 | ||
|
|
88e2efb86c | ||
|
|
f70c006cd2 | ||
|
|
2d43318eeb | ||
|
|
464cfb0128 | ||
|
|
ccd9fea75c | ||
|
|
adbbf081d4 | ||
|
|
087895e0d4 | ||
|
|
f53236bbe5 | ||
|
|
4525a93346 | ||
|
|
92ce8e0953 | ||
|
|
4f506cbcbc | ||
|
|
53fed9d6ad | ||
|
|
a7fb2e53b5 | ||
|
|
cddacc3fc7 | ||
|
|
6f925ed79a | ||
|
|
91ff9d9174 | ||
|
|
cb5c11135f | ||
|
|
d02f29a398 |
47
mozilla/js/src/MANIFEST
Normal file
47
mozilla/js/src/MANIFEST
Normal file
@@ -0,0 +1,47 @@
|
||||
# This file is required for the Mac client mozilla build.
|
||||
# This is a list of local files which get copied to the mozilla:dist directory
|
||||
#
|
||||
|
||||
js.msg
|
||||
jsapi.h
|
||||
jsarena.h
|
||||
jspubtd.h
|
||||
jsarray.h
|
||||
jsatom.h
|
||||
jsbool.h
|
||||
jsclist.h
|
||||
jscntxt.h
|
||||
jscompat.h
|
||||
jsconfig.h
|
||||
jscpucfg.h
|
||||
jsdate.h
|
||||
jsdbgapi.h
|
||||
jsdtoa.h
|
||||
jsemit.h
|
||||
jsfun.h
|
||||
jsgc.h
|
||||
jshash.h
|
||||
jsinterp.h
|
||||
jslock.h
|
||||
jslong.h
|
||||
jsmath.h
|
||||
jsnum.h
|
||||
jsobj.h
|
||||
jsopcode.tbl
|
||||
jsopcode.h
|
||||
jsosdep.h
|
||||
jsotypes.h
|
||||
jsparse.h
|
||||
jsprf.h
|
||||
jsprvtd.h
|
||||
jspubtd.h
|
||||
jsregexp.h
|
||||
jsscan.h
|
||||
jsscope.h
|
||||
jsscript.h
|
||||
jsstr.h
|
||||
jstypes.h
|
||||
jsutil.h
|
||||
jsxdrapi.h
|
||||
|
||||
|
||||
267
mozilla/js/src/Makefile
Normal file
267
mozilla/js/src/Makefile
Normal file
@@ -0,0 +1,267 @@
|
||||
#! gmake
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
DEPTH = ../..
|
||||
|
||||
include $(DEPTH)/config/config.mk
|
||||
|
||||
ifdef MOZ_OJI
|
||||
DIRS = liveconnect
|
||||
endif
|
||||
|
||||
LIBRARY_NAME = js
|
||||
|
||||
ifeq ($(subst /,_,$(shell uname -s)),OS2)
|
||||
ifndef XCFLAGS
|
||||
OS2_IMPLIB=1
|
||||
LIBRARY = js$(MOZ_BITS)$(VERSION_NUMBER).$(LIB_SUFFIX)
|
||||
DEF_FILE = jsos2$(VERSION_NUMBER).def
|
||||
EXTRA_LIBS = $(LIBNSPR) $(LIBNSJAVA)
|
||||
else
|
||||
EXTRA_LIBS = $(LIBNSPR) $(LIBNSJAVA) $(OBJDIR)/libjs.lib
|
||||
endif
|
||||
endif
|
||||
|
||||
MODULE = js
|
||||
|
||||
CSRCS = jsapi.c \
|
||||
jsarena.c \
|
||||
jsarray.c \
|
||||
jsatom.c \
|
||||
jsbool.c \
|
||||
jscntxt.c \
|
||||
jsdate.c \
|
||||
jsdbgapi.c \
|
||||
jsdtoa.c \
|
||||
jsemit.c \
|
||||
jsexn.c \
|
||||
jsfun.c \
|
||||
jsgc.c \
|
||||
jshash.c \
|
||||
jsinterp.c \
|
||||
jslock.c \
|
||||
jslog2.c \
|
||||
jslong.c \
|
||||
jsmath.c \
|
||||
jsnum.c \
|
||||
jsobj.c \
|
||||
jsopcode.c \
|
||||
jsparse.c \
|
||||
jsprf.c \
|
||||
jsregexp.c \
|
||||
jsscan.c \
|
||||
jsscope.c \
|
||||
jsscript.c \
|
||||
jsstr.c \
|
||||
jsutil.c \
|
||||
jsxdrapi.c \
|
||||
prmjtime.c \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = js.msg \
|
||||
jsapi.h \
|
||||
jsarray.h \
|
||||
jsarena.h \
|
||||
jsatom.h \
|
||||
jsbit.h \
|
||||
jsbool.h \
|
||||
jsclist.h \
|
||||
jscntxt.h \
|
||||
jscompat.h \
|
||||
jsconfig.h \
|
||||
jsdate.h \
|
||||
jsdbgapi.h \
|
||||
jsemit.h \
|
||||
jsfun.h \
|
||||
jsgc.h \
|
||||
jshash.h \
|
||||
jsinterp.h \
|
||||
jslock.h \
|
||||
jslong.h \
|
||||
jsmath.h \
|
||||
jsnum.h \
|
||||
jsobj.h \
|
||||
jsopcode.tbl \
|
||||
jsopcode.h \
|
||||
jsosdep.h \
|
||||
jsotypes.h \
|
||||
jsparse.h \
|
||||
jsprf.h \
|
||||
jsprvtd.h \
|
||||
jspubtd.h \
|
||||
jsregexp.h \
|
||||
jsscan.h \
|
||||
jsscope.h \
|
||||
jsscript.h \
|
||||
jsstr.h \
|
||||
jstypes.h \
|
||||
jsutil.h \
|
||||
jsxdrapi.h \
|
||||
$(NULL)
|
||||
|
||||
# when using gcc the assembly is inlined in the C-file (see jslock.c)
|
||||
ifdef NS_USE_NATIVE
|
||||
ASFILES = $(wildcard *_$(OS_ARCH).s)
|
||||
endif
|
||||
|
||||
JS_SAFE_ARENA = 1
|
||||
|
||||
ifdef JS_SAFE_ARENA
|
||||
DEFINES += -DJS_USE_SAFE_ARENA
|
||||
endif
|
||||
|
||||
include $(DEPTH)/config/rules.mk
|
||||
|
||||
ifndef BUILD_OPT
|
||||
MOCHAFILE = 1
|
||||
endif
|
||||
|
||||
ifdef JSFILE
|
||||
DEFINES += -DJSFILE
|
||||
endif
|
||||
|
||||
ifdef JS_THREADSAFE
|
||||
DEFINES += -DJS_THREADSAFE
|
||||
endif
|
||||
|
||||
ifdef JS_NO_THIN_LOCKS
|
||||
DEFINES += -DJS_USE_ONLY_NSPR_LOCKS
|
||||
endif
|
||||
|
||||
ifdef JS_VERSION
|
||||
DEFINES += -DJS_VERSION=$(JS_VERSION)
|
||||
endif
|
||||
|
||||
ifeq ($(CPU_ARCH),sparc)
|
||||
|
||||
ifndef JS_NO_ULTRA
|
||||
ULTRA_OPTIONS := -xarch=v8plus,-DULTRA_SPARC
|
||||
ULTRA_OPTIONSCC := -DULTRA_SPARC
|
||||
else
|
||||
ULTRA_OPTIONS := -xarch=v8
|
||||
ULTRA_OPTIONSCC :=
|
||||
endif
|
||||
|
||||
ifeq ($(shell uname -m),sun4u)
|
||||
ASFLAGS += -Wa,$(ULTRA_OPTIONS),-P,-L,-D_ASM,-D__STDC__=0 $(ULTRA_OPTIONSCC)
|
||||
else
|
||||
ASFLAGS += -Wa,-xarch=v8,-P,-L,-D_ASM,-D__STDC__=0
|
||||
endif
|
||||
|
||||
endif # sparc
|
||||
|
||||
INCLUDES += -I.
|
||||
|
||||
ifndef NSBUILDROOT
|
||||
JSJAVA_STUBHEADERS = -I$(DEPTH)/sun-java/include/_gen \
|
||||
-I$(DEPTH)/sun-java/netscape/javascript/_jri \
|
||||
-I$(DEPTH)/sun-java/netscape/security/_jri
|
||||
else
|
||||
JSJAVA_STUBHEADERS = -I$(JRI_GEN_DIR) -I$(JDK_GEN_DIR)
|
||||
endif
|
||||
|
||||
JSJAVA_CFLAGS = -I$(DEPTH)/sun-java/md-include \
|
||||
-I$(DEPTH)/sun-java/include \
|
||||
$(JSJAVA_STUBHEADERS)
|
||||
|
||||
# LIBNSPR abstracts nspr version, etc. nicely.
|
||||
LDFLAGS = $(LIBNSPR) -lm
|
||||
|
||||
ifeq ($(OS_ARCH), OSF1)
|
||||
LDFLAGS += -lc_r
|
||||
endif
|
||||
ifeq ($(OS_ARCH), SunOS)
|
||||
LDFLAGS += -lposix4 -ldl -lnsl -lsocket
|
||||
endif
|
||||
ifeq ($(OS_ARCH), Linux)
|
||||
LDFLAGS += -ldl
|
||||
endif
|
||||
|
||||
FDLIBM_LIBRARY = fdlibm/$(OBJDIR)/libfdm.a
|
||||
JSMATH_PRELINK = $(OBJDIR)/jsmathtemp.o
|
||||
|
||||
# special rule for jsmath.o since we want to incrementally link
|
||||
# against fdlibm to pull in only what is needed
|
||||
$(OBJDIR)/jsmath.o: $(FDLIBM_LIBRARY) $(JSMATH_PRELINK)
|
||||
@$(MAKE_OBJDIR)
|
||||
ifneq (,$(filter OS2 WINNT,$(OS_ARCH)))
|
||||
ld -r -o $@ $(JSMATH_PRELINK) $(FDLIBM_LIBRARY)
|
||||
else
|
||||
ld -r -o $@ $(JSMATH_PRELINK) $(FDLIBM_LIBRARY)
|
||||
endif
|
||||
|
||||
$(JSMATH_PRELINK): jsmath.c jslibmath.h
|
||||
@$(MAKE_OBJDIR)
|
||||
ifneq (,$(filter OS2 WINNT,$(OS_ARCH)))
|
||||
$(CC) -Fo$@ -c $(CFLAGS) $<
|
||||
else
|
||||
$(CC) -o $@ -c $(CFLAGS) $<
|
||||
endif
|
||||
|
||||
$(FDLIBM_LIBRARY):
|
||||
cd fdlibm; $(MAKE)
|
||||
|
||||
# this requires clobbering and recompiling with XCFLAGS=-DJSFILE
|
||||
js:
|
||||
$(MAKE) clobber
|
||||
$(MAKE) XCFLAGS=-DJSFILE $(OBJDIR)/js$(BIN_SUFFIX)
|
||||
|
||||
.PHONY: js$(BIN_SUFFIX)
|
||||
|
||||
ifneq ($(OS_ARCH),OS2)
|
||||
$(OBJDIR)/js$(BIN_SUFFIX): $(OBJDIR)/js.o $(LIBRARY)
|
||||
@$(MAKE_OBJDIR)
|
||||
$(CC) -o $@ $(OBJDIR)/js.o $(LIBRARY) $(LDFLAGS)
|
||||
else
|
||||
OS_CFLAGS += -tm-
|
||||
$(OBJDIR)/js$(BIN_SUFFIX): $(OBJDIR)/js.o $(LIBRARY)
|
||||
@$(MAKE_OBJDIR)
|
||||
$(LINK_EXE) -OUT:$@ $(OBJDIR)/js.o $(LIBRARIES) $(EXTRA_LIBS)
|
||||
endif
|
||||
|
||||
# hardwire dependencies on jsopcode.tbl
|
||||
jsopcode.h jsopcode.c: jsopcode.tbl
|
||||
|
||||
# Generate jsautocfg.h header
|
||||
$(OBJDIR)/jsautocfg.h: $(OBJDIR)/jscpucfg
|
||||
rm -f $@
|
||||
$(OBJDIR)/jscpucfg > $@
|
||||
|
||||
$(OBJDIR)/jscpucfg: $(OBJDIR)/jscpucfg.o
|
||||
$(CC) -o $@ $(OBJDIR)/jscpucfg.o
|
||||
|
||||
export:: $(OBJDIR)/jsautocfg.h
|
||||
$(INSTALL) -m 444 $(OBJDIR)/jsautocfg.h $(DIST)/include
|
||||
|
||||
# Add to TARGETS so clobber rule works
|
||||
TARGETS += $(OBJDIR)/jsautocfg.h $(OBJDIR)/jscpucfg $(OBJDIR)/jscpucfg.o
|
||||
|
||||
# this section was put in the merged by danda into the
|
||||
# JAVA_*_MERGE section and normally would have
|
||||
# been removed. However it looks like it shouldn't have
|
||||
# been put there in the first place, so we're leaving it
|
||||
# here until danda can confirm (we don't have OS/2 machines
|
||||
# to build on) - hshaw/sudu
|
||||
#
|
||||
ifeq ($(OS_ARCH),OS2)
|
||||
$(OBJDIR)/js.o: js.c
|
||||
@$(MAKE_OBJDIR)
|
||||
$(CC) -Fo$@ -c $(CFLAGS) $(JSJAVA_CFLAGS) js.c
|
||||
endif
|
||||
|
||||
clobber::
|
||||
rm -f $(OBJDIR)/jscpucfg $(OBJDIR)/jscpucfg.h
|
||||
|
||||
268
mozilla/js/src/Makefile.in
Normal file
268
mozilla/js/src/Makefile.in
Normal file
@@ -0,0 +1,268 @@
|
||||
#! gmake
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
DEPTH = ../..
|
||||
topsrcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
srcdir = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
ifdef MOZ_OJI
|
||||
DIRS = liveconnect
|
||||
endif
|
||||
|
||||
LIBRARY_NAME = js
|
||||
|
||||
ifeq ($(subst /,_,$(shell uname -s)),OS2)
|
||||
ifndef XCFLAGS
|
||||
OS2_IMPLIB=1
|
||||
LIBRARY = js$(MOZ_BITS)$(VERSION_NUMBER).$(LIB_SUFFIX)
|
||||
DEF_FILE = jsos2$(VERSION_NUMBER).def
|
||||
EXTRA_LIBS = $(LIBNSPR) $(LIBNSJAVA)
|
||||
else
|
||||
EXTRA_LIBS = $(LIBNSPR) $(LIBNSJAVA) $(OBJDIR)/libjs.lib
|
||||
endif
|
||||
endif
|
||||
|
||||
MODULE = js
|
||||
|
||||
CSRCS = jsapi.c \
|
||||
jsarena.c \
|
||||
jsarray.c \
|
||||
jsatom.c \
|
||||
jsbool.c \
|
||||
jscntxt.c \
|
||||
jsdate.c \
|
||||
jsdbgapi.c \
|
||||
jsdtoa.c \
|
||||
jsemit.c \
|
||||
jsexn.c \
|
||||
jsfun.c \
|
||||
jsgc.c \
|
||||
jshash.c \
|
||||
jsinterp.c \
|
||||
jslock.c \
|
||||
jslog2.c \
|
||||
jslong.c \
|
||||
jsmath.c \
|
||||
jsnum.c \
|
||||
jsobj.c \
|
||||
jsopcode.c \
|
||||
jsparse.c \
|
||||
jsprf.c \
|
||||
jsregexp.c \
|
||||
jsscan.c \
|
||||
jsscope.c \
|
||||
jsscript.c \
|
||||
jsstr.c \
|
||||
jsutil.c \
|
||||
jsxdrapi.c \
|
||||
prmjtime.c \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = js.msg \
|
||||
jsapi.h \
|
||||
jsarray.h \
|
||||
jsarena.h \
|
||||
jsatom.h \
|
||||
jsbit.h \
|
||||
jsbool.h \
|
||||
jsclist.h \
|
||||
jscntxt.h \
|
||||
jscompat.h \
|
||||
jsconfig.h \
|
||||
jsdate.h \
|
||||
jsdbgapi.h \
|
||||
jsemit.h \
|
||||
jsfun.h \
|
||||
jsgc.h \
|
||||
jshash.h \
|
||||
jsinterp.h \
|
||||
jslock.h \
|
||||
jslong.h \
|
||||
jsmath.h \
|
||||
jsnum.h \
|
||||
jsobj.h \
|
||||
jsopcode.tbl \
|
||||
jsopcode.h \
|
||||
jsosdep.h \
|
||||
jsotypes.h \
|
||||
jsparse.h \
|
||||
jsprf.h \
|
||||
jsprvtd.h \
|
||||
jspubtd.h \
|
||||
jsregexp.h \
|
||||
jsscan.h \
|
||||
jsscope.h \
|
||||
jsscript.h \
|
||||
jsstr.h \
|
||||
jstypes.h \
|
||||
jsutil.h \
|
||||
jsxdrapi.h \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
|
||||
|
||||
# when using gcc the assembly is inlined in the C-file (see jslock.c)
|
||||
ifdef NS_USE_NATIVE
|
||||
ASFILES = $(wildcard $(srcdir)/*_$(OS_ARCH).s)
|
||||
endif
|
||||
|
||||
JS_SAFE_ARENA = 1
|
||||
|
||||
ifdef JS_SAFE_ARENA
|
||||
DEFINES += -DJS_USE_SAFE_ARENA
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
ifndef BUILD_OPT
|
||||
MOCHAFILE = 1
|
||||
endif
|
||||
|
||||
ifdef JSFILE
|
||||
DEFINES += -DJSFILE
|
||||
endif
|
||||
|
||||
ifdef JS_THREADSAFE
|
||||
DEFINES += -DJS_THREADSAFE
|
||||
endif
|
||||
|
||||
ifdef JS_NO_THIN_LOCKS
|
||||
DEFINES += -DJS_USE_ONLY_NSPR_LOCKS
|
||||
endif
|
||||
|
||||
ifdef JS_VERSION
|
||||
DEFINES += -DJS_VERSION=$(JS_VERSION)
|
||||
endif
|
||||
|
||||
ifeq ($(CPU_ARCH),sparc)
|
||||
|
||||
ifndef JS_NO_ULTRA
|
||||
ULTRA_OPTIONS := -xarch=v8plus,-DULTRA_SPARC
|
||||
ULTRA_OPTIONSCC := -DULTRA_SPARC
|
||||
else
|
||||
ULTRA_OPTIONS := -xarch=v8
|
||||
ULTRA_OPTIONSCC :=
|
||||
endif
|
||||
|
||||
ifeq ($(shell uname -m),sun4u)
|
||||
ASFLAGS += -Wa,$(ULTRA_OPTIONS),-P,-L,-D_ASM,-D__STDC__=0 $(ULTRA_OPTIONSCC)
|
||||
else
|
||||
ASFLAGS += -Wa,-xarch=v8,-P,-L,-D_ASM,-D__STDC__=0
|
||||
endif
|
||||
|
||||
endif # sparc
|
||||
|
||||
INCLUDES += -I$(srcdir)
|
||||
|
||||
ifndef NSBUILDROOT
|
||||
JSJAVA_STUBHEADERS = -I$(topsrcdir)/sun-java/include/_gen \
|
||||
-I$(topsrcdir)/sun-java/netscape/javascript/_jri \
|
||||
-I$(topsrcdir)/sun-java/netscape/security/_jri
|
||||
else
|
||||
JSJAVA_STUBHEADERS = -I$(JRI_GEN_DIR) -I$(JDK_GEN_DIR)
|
||||
endif
|
||||
|
||||
JSJAVA_CFLAGS = -I$(topsrcdir)/sun-java/md-include \
|
||||
-I$(topsrcdir)/sun-java/include \
|
||||
$(JSJAVA_STUBHEADERS)
|
||||
|
||||
# LIBNSPR abstracts nspr version, etc. nicely.
|
||||
LDFLAGS = $(LIBNSPR) -lm
|
||||
|
||||
ifeq ($(OS_ARCH), OSF1)
|
||||
LDFLAGS += -lc_r
|
||||
endif
|
||||
ifeq ($(OS_ARCH), SunOS)
|
||||
LDFLAGS += -lposix4 -ldl -lnsl -lsocket
|
||||
endif
|
||||
ifeq ($(OS_ARCH), Linux)
|
||||
LDFLAGS += -ldl
|
||||
endif
|
||||
|
||||
FDLIBM_LIBRARY = fdlibm/$(OBJDIR)/libfdm.a
|
||||
JSMATH_PRELINK = $(OBJDIR)/jsmathtemp.o
|
||||
|
||||
# special rule for jsmath.o since we want to incrementally link
|
||||
# against fdlibm to pull in only what is needed
|
||||
$(OBJDIR)/jsmath.o: $(FDLIBM_LIBRARY) $(JSMATH_PRELINK)
|
||||
@$(MAKE_OBJDIR)
|
||||
ifneq (,$(filter OS2 WINNT,$(OS_ARCH)))
|
||||
ld -r -o $@ $(JSMATH_PRELINK) $(FDLIBM_LIBRARY)
|
||||
else
|
||||
ld -r -o $@ $(JSMATH_PRELINK) $(FDLIBM_LIBRARY)
|
||||
endif
|
||||
|
||||
$(JSMATH_PRELINK): jsmath.c
|
||||
@$(MAKE_OBJDIR)
|
||||
ifneq (,$(filter OS2 WINNT,$(OS_ARCH)))
|
||||
$(CC) -Fo$@ -c $(CFLAGS) $<
|
||||
else
|
||||
$(CC) -o $@ -c $(CFLAGS) $<
|
||||
endif
|
||||
|
||||
$(FDLIBM_LIBRARY):
|
||||
cd fdlibm; $(MAKE)
|
||||
|
||||
# this requires clobbering and recompiling with XCFLAGS=-DJSFILE
|
||||
js:
|
||||
$(MAKE) clobber
|
||||
$(MAKE) XCFLAGS=-DJSFILE $(OBJDIR)/js$(BIN_SUFFIX)
|
||||
|
||||
.PHONY: js$(BIN_SUFFIX)
|
||||
|
||||
ifneq ($(OS_ARCH),OS2)
|
||||
$(OBJDIR)/js$(BIN_SUFFIX): $(OBJDIR)/js.o $(LIBRARY)
|
||||
@$(MAKE_OBJDIR)
|
||||
$(CC) -o $@ $(OBJDIR)/js.o $(LIBRARY) $(LDFLAGS)
|
||||
else
|
||||
OS_CFLAGS += -tm-
|
||||
$(OBJDIR)/js$(BIN_SUFFIX): $(OBJDIR)/js.o $(LIBRARY)
|
||||
@$(MAKE_OBJDIR)
|
||||
$(LINK_EXE) -OUT:$@ $(OBJDIR)/js.o $(LIBRARIES) $(EXTRA_LIBS)
|
||||
endif
|
||||
|
||||
# hardwire dependencies on jsopcode.tbl
|
||||
jsopcode.h jsopcode.c: jsopcode.tbl
|
||||
|
||||
# Generate jsautocfg.h header
|
||||
$(OBJDIR)/jsautocfg.h: $(OBJDIR)/jscpucfg
|
||||
rm -f $@
|
||||
$(OBJDIR)/jscpucfg > $@
|
||||
|
||||
$(OBJDIR)/jscpucfg: $(OBJDIR)/jscpucfg.o
|
||||
$(CC) -o $@ $(OBJDIR)/jscpucfg.o
|
||||
|
||||
export:: $(OBJDIR)/jsautocfg.h
|
||||
$(INSTALL) -m 444 $(OBJDIR)/jsautocfg.h $(DIST)/include
|
||||
|
||||
# Add to TARGETS so clobber rule works
|
||||
TARGETS += $(OBJDIR)/jsautocfg.h $(OBJDIR)/jscpucfg $(OBJDIR)/jscpucfg.o
|
||||
|
||||
# this section was put in the merged by danda into the
|
||||
# JAVA_*_MERGE section and normally would have
|
||||
# been removed. However it looks like it shouldn't have
|
||||
# been put there in the first place, so we're leaving it
|
||||
# here until danda can confirm (we don't have OS/2 machines
|
||||
# to build on) - hshaw/sudu
|
||||
#
|
||||
ifeq ($(OS_ARCH),OS2)
|
||||
$(OBJDIR)/js.o: js.c
|
||||
@$(MAKE_OBJDIR)
|
||||
$(CC) -Fo$@ -c $(CFLAGS) $(JSJAVA_CFLAGS) js.c
|
||||
endif
|
||||
239
mozilla/js/src/Makefile.ref
Normal file
239
mozilla/js/src/Makefile.ref
Normal file
@@ -0,0 +1,239 @@
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
#
|
||||
# JSRef GNUmake makefile.
|
||||
#
|
||||
|
||||
DEPTH = .
|
||||
|
||||
include config.mk
|
||||
|
||||
#NS_USE_NATIVE = 1
|
||||
|
||||
ifdef USE_MSVC
|
||||
OTHER_LIBS += fdlibm/$(OBJDIR)/fdlibm.lib
|
||||
else
|
||||
OTHER_LIBS += -Lfdlibm/$(OBJDIR) -lfdm
|
||||
endif
|
||||
|
||||
ifdef JS_THREADSAFE
|
||||
DEFINES += -DJS_THREADSAFE
|
||||
INCLUDES += -I../../dist/$(OBJDIR)/include
|
||||
ifdef USE_MSVC
|
||||
OTHER_LIBS += ../../dist/$(OBJDIR)/lib/libnspr21.lib
|
||||
else
|
||||
OTHER_LIBS += -L../../dist/$(OBJDIR)/lib -lnspr21
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef JS_NO_THIN_LOCKS
|
||||
DEFINES += -DJS_USE_ONLY_NSPR_LOCKS
|
||||
endif
|
||||
|
||||
ifdef JS_HAS_FILE_OBJECT
|
||||
DEFINES += -DJS_HAS_FILE_OBJECT
|
||||
endif
|
||||
|
||||
#
|
||||
# XCFLAGS may be set in the environment or on the gmake command line
|
||||
#
|
||||
CFLAGS += $(OPTIMIZER) $(OS_CFLAGS) $(DEFINES) $(INCLUDES) \
|
||||
-DJSFILE $(XCFLAGS)
|
||||
LDFLAGS = -lm $(XLDFLAGS)
|
||||
|
||||
#
|
||||
# Ask perl what flags it was built with, so we can build js with similar flags
|
||||
# and link properly. Viva gmake.
|
||||
#
|
||||
ifdef JS_PERLCONNECT
|
||||
DEFINES += -DPERLCONNECT
|
||||
|
||||
PERLCFLAGS := $(shell perl -MExtUtils::Embed -e ccopts)
|
||||
PERLLDFLAGS := $(shell perl -MExtUtils::Embed -e ldopts)
|
||||
|
||||
CFLAGS += $(PERLCFLAGS)
|
||||
LDFLAGS += $(PERLLDFLAGS)
|
||||
endif
|
||||
|
||||
# For purify
|
||||
PURE_CFLAGS = -DXP_UNIX $(OPTIMIZER) $(PURE_OS_CFLAGS) $(DEFINES) \
|
||||
$(INCLUDES) $(XCFLAGS)
|
||||
|
||||
#
|
||||
# JS file lists
|
||||
#
|
||||
JS_HFILES = \
|
||||
jsarray.h \
|
||||
jsatom.h \
|
||||
jsbool.h \
|
||||
jsconfig.h \
|
||||
jscntxt.h \
|
||||
jsdate.h \
|
||||
jsemit.h \
|
||||
jsexn.h \
|
||||
jsfun.h \
|
||||
jsgc.h \
|
||||
jsinterp.h \
|
||||
jslibmath.h \
|
||||
jslock.h \
|
||||
jsmath.h \
|
||||
jsnum.h \
|
||||
jsobj.h \
|
||||
jsopcode.h \
|
||||
jsparse.h \
|
||||
jsarena.h \
|
||||
jsclist.h \
|
||||
jsdtoa.h \
|
||||
jshash.h \
|
||||
jslong.h \
|
||||
jsosdep.h \
|
||||
jstypes.h \
|
||||
jsprvtd.h \
|
||||
jspubtd.h \
|
||||
jsregexp.h \
|
||||
jsscan.h \
|
||||
jsscope.h \
|
||||
jsscript.h \
|
||||
jsstr.h \
|
||||
jsxdrapi.h \
|
||||
$(NULL)
|
||||
|
||||
API_HFILES = \
|
||||
jsapi.h \
|
||||
jsdbgapi.h \
|
||||
$(NULL)
|
||||
|
||||
HFILES = $(JS_HFILES) $(API_HFILES)
|
||||
|
||||
JS_CFILES = \
|
||||
jsapi.c \
|
||||
jsarena.c \
|
||||
jsarray.c \
|
||||
jsatom.c \
|
||||
jsbool.c \
|
||||
jscntxt.c \
|
||||
jsdate.c \
|
||||
jsdbgapi.c \
|
||||
jsdtoa.c \
|
||||
jsemit.c \
|
||||
jsexn.c \
|
||||
jsfun.c \
|
||||
jsgc.c \
|
||||
jshash.c \
|
||||
jsinterp.c \
|
||||
jslock.c \
|
||||
jslog2.c \
|
||||
jslong.c \
|
||||
jsmath.c \
|
||||
jsnum.c \
|
||||
jsobj.c \
|
||||
jsopcode.c \
|
||||
jsparse.c \
|
||||
jsprf.c \
|
||||
jsregexp.c \
|
||||
jsscan.c \
|
||||
jsscope.c \
|
||||
jsscript.c \
|
||||
jsstr.c \
|
||||
jsutil.c \
|
||||
jsxdrapi.c \
|
||||
prmjtime.c \
|
||||
$(NULL)
|
||||
|
||||
PREDIRS += fdlibm
|
||||
ifdef JS_LIVECONNECT
|
||||
DIRS += liveconnect
|
||||
endif
|
||||
|
||||
ifdef JS_PERLCONNECT
|
||||
JS_CFILES += jsperl.c
|
||||
endif
|
||||
|
||||
ifdef JS_HAS_FILE_OBJECT
|
||||
JS_CFILES += jsfile.c
|
||||
JS_HFILES += jsfile.h
|
||||
endif
|
||||
|
||||
LIB_CFILES = $(JS_CFILES)
|
||||
LIB_ASFILES := $(wildcard *_$(OS_ARCH).s)
|
||||
PROG_CFILES = js.c
|
||||
|
||||
ifdef USE_MSVC
|
||||
LIBRARY = $(OBJDIR)/js32.lib
|
||||
SHARED_LIBRARY = $(OBJDIR)/js32.dll
|
||||
PROGRAM = $(OBJDIR)/js.exe
|
||||
else
|
||||
LIBRARY = $(OBJDIR)/libjs.a
|
||||
SHARED_LIBRARY = $(OBJDIR)/libjs.so
|
||||
PROGRAM = $(OBJDIR)/js
|
||||
endif
|
||||
|
||||
ifdef USE_MSVC
|
||||
FDLIBM_LIBRARY = fdlibm.lib
|
||||
else
|
||||
FDLIBM_LIBRARY = libfdm.a
|
||||
endif
|
||||
|
||||
include rules.mk
|
||||
|
||||
MOZ_DEPTH = ../..
|
||||
include jsconfig.mk
|
||||
|
||||
nsinstall-target:
|
||||
cd ../../config; $(MAKE) OBJDIR=$(OBJDIR) OBJDIR_NAME=$(OBJDIR)
|
||||
ifdef USE_MSVC
|
||||
$(PROGRAM): $(PROG_OBJS) $(LIBRARY)
|
||||
link.exe -out:"$@" $(EXE_LINK_FLAGS) $^
|
||||
else
|
||||
$(PROGRAM): $(PROG_OBJS) $(LIBRARY)
|
||||
$(CC) -o $@ $(CFLAGS) $(PROG_OBJS) $(LIBRARY) $(LDFLAGS) $(OTHER_LIBS)
|
||||
endif
|
||||
|
||||
$(PROGRAM).pure: $(PROG_OBJS) $(LIBRARY)
|
||||
purify $(PUREFLAGS) \
|
||||
$(CC) -o $@ $(PURE_OS_CFLAGS) $(PROG_OBJS) $(LIBRARY) $(LDFLAGS) $(OTHER_LIBS)
|
||||
|
||||
ifndef PREBUILT_CPUCFG
|
||||
$(HFILES) $(CFILES): $(OBJDIR)/jsautocfg.h
|
||||
|
||||
$(OBJDIR)/jsautocfg.h: $(OBJDIR)/jscpucfg
|
||||
rm -f $@
|
||||
$(OBJDIR)/jscpucfg > $@
|
||||
|
||||
$(OBJDIR)/jscpucfg: $(OBJDIR)/jscpucfg.o
|
||||
$(CC) -o $@ $(OBJDIR)/jscpucfg.o
|
||||
|
||||
# Look in OBJDIR to find jsautocfg.h
|
||||
INCLUDES += -I$(OBJDIR)
|
||||
|
||||
# Add to TARGETS for clobber rule
|
||||
TARGETS += $(OBJDIR)/jsautocfg.h $(OBJDIR)/jscpucfg $(OBJDIR)/jscpucfg.o
|
||||
endif
|
||||
|
||||
#
|
||||
# Hardwire dependencies on jsopcode.tbl
|
||||
#
|
||||
jsopcode.h jsopcode.c: jsopcode.tbl
|
||||
|
||||
-include $(DEPENDENCIES)
|
||||
|
||||
TARNAME = jsref.tar
|
||||
TARFILES = files `cat files`
|
||||
|
||||
SUFFIXES: .i
|
||||
%.i: %.c
|
||||
$(CC) -C -E $(CFLAGS) $< > $*.i
|
||||
755
mozilla/js/src/README.html
Normal file
755
mozilla/js/src/README.html
Normal file
@@ -0,0 +1,755 @@
|
||||
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="GENERATOR" content="Mozilla/4.5 [en] (WinNT; I) [Netscape]">
|
||||
<title>JavaScript Reference Implementation (JSRef) README</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h2>
|
||||
Table of Contents</h2>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<a href="#Introduction">Introduction</a></li>
|
||||
|
||||
<li>
|
||||
<a href="#Build">Build conventions (standalone JS engine and shell)</a></li>
|
||||
|
||||
<li>
|
||||
<a href="#Debugging">Debugging notes</a></li>
|
||||
|
||||
<li>
|
||||
<a href="#Conventions">Naming and coding conventions</a></li>
|
||||
|
||||
<li>
|
||||
<a href="#JSAPI">Using the JS API</a></li>
|
||||
|
||||
<li>
|
||||
<a href="#Design">Design walk-through</a></li>
|
||||
</ul>
|
||||
|
||||
<h2>
|
||||
<a NAME="Introduction"></a>Introduction</h2>
|
||||
This is the README file for the <span CLASS=LXRSHORTDESC>JavaScript
|
||||
Reference (JSRef) implementation.</span> It consists of build conventions
|
||||
and instructions, source code conventions, a design walk-through, and a
|
||||
brief file-by-file description of the source.
|
||||
<p><span CLASS=LXRLONGDESC>JSRef builds a library or DLL containing the
|
||||
JavaScript runtime (compiler, interpreter, decompiler, garbage collector,
|
||||
atom manager, standard classes). It then compiles a small "shell" program
|
||||
and links that with the library to make an interpreter that can be used
|
||||
interactively and with test .js files to run scripts. The code has
|
||||
no dependencies on the Navigator code.</span>
|
||||
<p><i>Quick start tip</i>: skip to "Using the JS API" below, build the
|
||||
js shell, and play with the object named "it" (start by setting 'it.noisy
|
||||
= true').
|
||||
<h2>
|
||||
<a NAME="Build"></a>Build conventions (standalone JS engine and shell)</h2>
|
||||
These build directions refer only to building the standalone JavaScript
|
||||
engine and shell. To build within the browser, refer to the <a href="http://www.mozilla.org/docs/">build
|
||||
directions</a> on the mozilla.org website.
|
||||
<p>By default, all platforms build a version of the JS engine that is <i>not</i>
|
||||
threadsafe. If you require thread-safety, you must also populate
|
||||
the <tt>mozilla/dist</tt> directory with <a href="http://www.mozilla.org/docs/tplist/catCode/nsprdesc.htm">NSPR</a>
|
||||
headers and libraries. (NSPR implements a portable threading library,
|
||||
among other things. The source is downloadable via <a href="http://www.mozilla.org/cvs.html">CVS</a>
|
||||
from <tt><a href="http://cvs-mirror.mozilla.org/webtools/lxr/source/nsprpub">mozilla/nsprpub</a></tt>.)
|
||||
Next, you must define <tt>JS_THREADSAFE</tt> when building the JS engine,
|
||||
either on the command-line (gmake/nmake) or in a universal header file.
|
||||
<h3>
|
||||
Windows</h3>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
Use MSVC 4.2 or 5.0.</li>
|
||||
|
||||
<li>
|
||||
For building from the IDE use <tt>js/src/js.mdp</tt>. (<tt>js.mdp</tt>
|
||||
is an MSVC4.2 project file, but if you load it into MSVC5, it will be converted
|
||||
to the newer project file format.) <font color="#CC0000">NOTE: makefile.win
|
||||
is an nmake file used only for building the JS-engine in the Mozilla browser.
|
||||
Don't attempt to use it to build the standalone JS-engine.</font></li>
|
||||
|
||||
<li>
|
||||
If you prefer to build from the command-line, use '<tt>nmake -f js.mak</tt>'</li>
|
||||
|
||||
<li>
|
||||
Executable shell <tt>js.exe</tt> and runtime library <tt>js32.dll</tt>
|
||||
are created in either <tt>js/src/Debug</tt> or <tt>js/src/Release</tt>.</li>
|
||||
</ul>
|
||||
|
||||
<h3>
|
||||
Macintosh</h3>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
Use CodeWarrior 3.x</li>
|
||||
|
||||
<li>
|
||||
Load the project file <tt>js:src:macbuild:JSRef.mcp </tt>and select "Make"
|
||||
from the menu.</li>
|
||||
</ul>
|
||||
|
||||
<h3>
|
||||
Unix</h3>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
Use '<tt>gmake -f Makefile.ref</tt>' to build. To compile optimized code,
|
||||
pass <tt>BUILD_OPT=1</tt> on the gmake command line or preset it in the
|
||||
environment or <tt>Makefile.ref</tt>. <font color="#CC0000">NOTE:
|
||||
Do not attempt to use Makefile to build the standalone JavaScript engine.
|
||||
This file is used only for building the JS-engine in the Mozilla browser.</font></li>
|
||||
|
||||
<li>
|
||||
<font color="#000000">Each platform on which JS is built must have a <tt>*.mk</tt>
|
||||
configuration file in the <tt>js/src/config</tt> directory. The configuration
|
||||
file specifies the compiler/linker to be used and allows for customization
|
||||
of command-line options. To date, the build system has been tested
|
||||
on Solaris, AIX, HP/UX, OSF, IRIX, x86 Linux and Windows NT.</font></li>
|
||||
|
||||
<li>
|
||||
<font color="#000000">Most platforms will work with either the vendor compiler
|
||||
</font>or
|
||||
<a href="ftp://prep.ai.mit.edu/pub/gnu">gcc</a>.
|
||||
(Except that HP builds only work using the native compiler. gcc won't
|
||||
link correctly with shared libraries on that platform. If someone
|
||||
knows a way to fix this, <a href="mailto:wynholds@netscape.com">let us
|
||||
know</a>.)</li>
|
||||
|
||||
<li>
|
||||
<font color="#000000">If you define <tt>JS_LIVECONNECT</tt>, gmake will
|
||||
descend into the liveconnect directory and build <a href="http://cvs-mirror.mozilla.org/webtools/lxr/source/js/src/liveconnect/README.html">LiveConnect</a>
|
||||
after building the JS engine.</font></li>
|
||||
|
||||
<li>
|
||||
To build a binary drop (a zip'ed up file of headers, libraries, binaries),
|
||||
check out <tt>mozilla/config</tt> and <tt>mozilla/nsprpub/config</tt>.
|
||||
Use '<tt>gmake -f Makefile.ref nsinstall-target all export ship</tt>'</li>
|
||||
</ul>
|
||||
|
||||
<h2>
|
||||
<a NAME="Debugging"></a>Debugging notes</h2>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
To turn on GC instrumentation, define <tt>JS_GCMETER</tt>.</li>
|
||||
|
||||
<li>
|
||||
To turn on the arena package's instrumentation, define <tt>JS_ARENAMETER</tt>.</li>
|
||||
|
||||
<li>
|
||||
To turn on the hash table package's metering, define <tt>JS_HASHMETER</tt>.</li>
|
||||
</ul>
|
||||
|
||||
<h2>
|
||||
<a NAME="Conventions"></a>Naming and coding conventions</h2>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
Public function names begin with <tt>JS_</tt> followed by capitalized "intercaps",
|
||||
e.g. <tt>JS_NewObject</tt>.</li>
|
||||
|
||||
<li>
|
||||
Extern but library-private function names use a <tt>js_</tt> prefix and
|
||||
mixed case, e.g. <tt>js_LookupSymbol</tt>.</li>
|
||||
|
||||
<li>
|
||||
Most static function names have unprefixed, mixed-case names: <tt>GetChar</tt>.</li>
|
||||
|
||||
<li>
|
||||
But static native methods of JS objects have lowercase, underscore-separated
|
||||
or intercaps names, e.g., <tt>str_indexOf</tt>.</li>
|
||||
|
||||
<li>
|
||||
And library-private and static data use underscores, not intercaps (but
|
||||
library-private data do use a <tt>js_</tt> prefix).</li>
|
||||
|
||||
<li>
|
||||
Scalar type names are lowercase and js-prefixed: <tt>jsdouble</tt>.</li>
|
||||
|
||||
<li>
|
||||
Aggregate type names are JS-prefixed and mixed-case: <tt>JSObject.</tt></li>
|
||||
|
||||
<li>
|
||||
Macros are generally <tt>ALL_CAPS </tt>and underscored, to call out potential
|
||||
side effects, multiple uses of a formal argument, etc. - Four spaces of
|
||||
indentation per statement nesting level.</li>
|
||||
|
||||
<li>
|
||||
Tabs are taken to be eight spaces, and an Emacs magic comment at the top
|
||||
of each file tries to help. If you're using MSVC or similar, you'll want
|
||||
to set tab width to 8, or convert these files to be space-filled.</li>
|
||||
|
||||
<li>
|
||||
DLL entry points have their return type expanded within a <tt>JS_PUBLIC_API()</tt>
|
||||
macro call, to get the right Windows secret type qualifiers in the right
|
||||
places for both 16- and 32-bit builds.</li>
|
||||
|
||||
<li>
|
||||
Callback functions that might be called from a DLL are similarly macroized
|
||||
with <tt>JS_STATIC_DLL_CALLBACK</tt> (if the function otherwise would be
|
||||
static to hide its name) or <tt>JS_DLL_CALLBACK</tt> (this macro takes
|
||||
no type argument; it should be used after the return type and before the
|
||||
function name).</li>
|
||||
</ul>
|
||||
|
||||
<h2>
|
||||
<a NAME="JSAPI"></a>Using the JS API</h2>
|
||||
|
||||
<h4>
|
||||
Starting up</h4>
|
||||
|
||||
<pre><tt> /*
|
||||
* Tune this to avoid wasting space for shallow stacks, while saving on
|
||||
* malloc overhead/fragmentation for deep or highly-variable stacks.
|
||||
*/
|
||||
#define STACK_CHUNK_SIZE 8192
|
||||
|
||||
JSRuntime *rt;
|
||||
JSContext *cx;
|
||||
|
||||
/* You need a runtime and one or more contexts to do anything with JS. */
|
||||
rt = JS_Init(1000000L);
|
||||
if (!rt)
|
||||
fail("can't create JavaScript runtime");
|
||||
cx = JS_NewContext(rt, STACK_CHUNK_SIZE);
|
||||
if (!cx)
|
||||
fail("can't create JavaScript context");
|
||||
|
||||
/*
|
||||
* The context definitely wants a global object, in order to have standard
|
||||
* classes and functions like Date and parseInt. See below for details on
|
||||
* JS_NewObject.
|
||||
*/
|
||||
JSObject *globalObj;
|
||||
|
||||
globalObj = JS_NewObject(cx, &my_global_class, 0, 0);
|
||||
JS_InitStandardClasses(cx, globalObj);</tt></pre>
|
||||
|
||||
<h4>
|
||||
Defining objects and properties</h4>
|
||||
|
||||
<pre><tt> /* Statically initialize a class to make "one-off" objects. */
|
||||
JSClass my_class = {
|
||||
"MyClass",
|
||||
|
||||
/* All of these can be replaced with the corresponding JS_*Stub
|
||||
function pointers. */
|
||||
my_addProperty, my_delProperty, my_getProperty, my_setProperty,
|
||||
my_enumerate, my_resolve, my_convert, my_finalize
|
||||
};
|
||||
|
||||
JSObject *obj;
|
||||
|
||||
/*
|
||||
* Define an object named in the global scope that can be enumerated by
|
||||
* for/in loops. The parent object is passed as the second argument, as
|
||||
* with all other API calls that take an object/name pair. The prototype
|
||||
* passed in is null, so the default object prototype will be used.
|
||||
*/
|
||||
obj = JS_DefineObject(cx, globalObj, "myObject", &my_class, 0,
|
||||
JSPROP_ENUMERATE);
|
||||
|
||||
/*
|
||||
* Define a bunch of properties with a JSPropertySpec array statically
|
||||
* initialized and terminated with a null-name entry. Besides its name,
|
||||
* each property has a "tiny" identifier (MY_COLOR, e.g.) that can be used
|
||||
* in switch statements (in a common my_getProperty function, for example).
|
||||
*/
|
||||
enum my_tinyid {
|
||||
MY_COLOR, MY_HEIGHT, MY_WIDTH, MY_FUNNY, MY_ARRAY, MY_RDONLY
|
||||
};
|
||||
|
||||
static JSPropertySpec my_props[] = {
|
||||
{"color", MY_COLOR, JSPROP_ENUMERATE},
|
||||
{"height", MY_HEIGHT, JSPROP_ENUMERATE},
|
||||
{"width", MY_WIDTH, JSPROP_ENUMERATE},
|
||||
{"funny", MY_FUNNY, JSPROP_ENUMERATE},
|
||||
{"array", MY_ARRAY, JSPROP_ENUMERATE},
|
||||
{"rdonly", MY_RDONLY, JSPROP_READONLY},
|
||||
{0}
|
||||
};
|
||||
|
||||
JS_DefineProperties(cx, obj, my_props);
|
||||
|
||||
/*
|
||||
* Given the above definitions and call to JS_DefineProperties, obj will
|
||||
* need this sort of "getter" method in its class (my_class, above). See
|
||||
* the example for the "It" class in js.c.
|
||||
*/
|
||||
static JSBool
|
||||
my_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
{
|
||||
if (JSVAL_IS_INT(id)) {
|
||||
switch (JSVAL_TO_INT(id)) {
|
||||
case MY_COLOR: *vp = . . .; break;
|
||||
case MY_HEIGHT: *vp = . . .; break;
|
||||
case MY_WIDTH: *vp = . . .; break;
|
||||
case MY_FUNNY: *vp = . . .; break;
|
||||
case MY_ARRAY: *vp = . . .; break;
|
||||
case MY_RDONLY: *vp = . . .; break;
|
||||
}
|
||||
}
|
||||
return JS_TRUE;
|
||||
}</tt></pre>
|
||||
|
||||
<h4>
|
||||
Defining functions</h4>
|
||||
|
||||
<pre><tt> /* Define a bunch of native functions first: */
|
||||
static JSBool
|
||||
my_abs(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
jsdouble x, z;
|
||||
|
||||
if (!JS_ValueToNumber(cx, argv[0], &x))
|
||||
return JS_FALSE;
|
||||
z = (x < 0) ? -x : x;
|
||||
return JS_NewDoubleValue(cx, z, rval);
|
||||
}
|
||||
|
||||
. . .
|
||||
|
||||
/*
|
||||
* Use a JSFunctionSpec array terminated with a null name to define a
|
||||
* bunch of native functions.
|
||||
*/
|
||||
static JSFunctionSpec my_functions[] = {
|
||||
/* name native nargs */
|
||||
{"abs", my_abs, 1},
|
||||
{"acos", my_acos, 1},
|
||||
{"asin", my_asin, 1},
|
||||
. . .
|
||||
{0}
|
||||
};
|
||||
|
||||
/*
|
||||
* Pass a particular object to define methods for it alone. If you pass
|
||||
* a prototype object, the methods will apply to all instances past and
|
||||
* future of the prototype's class (see below for classes).
|
||||
*/
|
||||
JS_DefineFunctions(cx, globalObj, my_functions);</tt></pre>
|
||||
|
||||
<h4>
|
||||
Defining classes</h4>
|
||||
|
||||
<pre><tt> /*
|
||||
* This pulls together the above API elements by defining a constructor
|
||||
* function, a prototype object, and properties of the prototype and of
|
||||
* the constructor, all with one API call.
|
||||
*
|
||||
* Initialize a class by defining its constructor function, prototype, and
|
||||
* per-instance and per-class properties. The latter are called "static"
|
||||
* below by analogy to Java. They are defined in the constructor object's
|
||||
* scope, so that 'MyClass.myStaticProp' works along with 'new MyClass()'.
|
||||
*
|
||||
* JS_InitClass takes a lot of arguments, but you can pass null for any of
|
||||
* the last four if there are no such properties or methods.
|
||||
*
|
||||
* Note that you do not need to call JS_InitClass to make a new instance of
|
||||
* that class -- otherwise there would be a chicken-and-egg problem making
|
||||
* the global object -- but you should call JS_InitClass if you require a
|
||||
* constructor function for script authors to call via new, and/or a class
|
||||
* prototype object ('MyClass.prototype') for authors to extend with new
|
||||
* properties at run-time.
|
||||
*/
|
||||
protoObj = JS_InitClass(cx, globalObj, &my_class,
|
||||
|
||||
/* native constructor function and min arg count */
|
||||
MyClass, 0,
|
||||
|
||||
/* prototype object properties and methods -- these
|
||||
will be "inherited" by all instances through
|
||||
delegation up the instance's prototype link. */
|
||||
my_props, my_methods,
|
||||
|
||||
/* class constructor properties and methods */
|
||||
my_static_props, my_static_methods);</tt></pre>
|
||||
|
||||
<h4>
|
||||
Running scripts</h4>
|
||||
|
||||
<pre><tt> /* These should indicate source location for diagnostics. */
|
||||
char *filename;
|
||||
uintN lineno;
|
||||
|
||||
/*
|
||||
* The return value comes back here -- if it could be a GC thing, you must
|
||||
* add it to the GC's "root set" with JS_AddRoot(cx, &thing) where thing
|
||||
* is a JSString *, JSObject *, or jsdouble *, and remove the root before
|
||||
* rval goes out of scope, or when rval is no longer needed.
|
||||
*/
|
||||
jsval rval;
|
||||
JSBool ok;
|
||||
|
||||
/*
|
||||
* Some example source in a C string. Larger, non-null-terminated buffers
|
||||
* can be used, if you pass the buffer length to JS_EvaluateScript.
|
||||
*/
|
||||
char *source = "x * f(y)";
|
||||
|
||||
ok = JS_EvaluateScript(cx, globalObj, source, strlen(source),
|
||||
filename, lineno, &rval);
|
||||
|
||||
if (ok) {
|
||||
/* Should get a number back from the example source. */
|
||||
jsdouble d;
|
||||
|
||||
ok = JS_ValueToNumber(cx, rval, &d);
|
||||
. . .
|
||||
}</tt></pre>
|
||||
|
||||
<h4>
|
||||
Calling functions</h4>
|
||||
|
||||
<pre><tt> /* Call a global function named "foo" that takes no arguments. */
|
||||
ok = JS_CallFunctionName(cx, globalObj, "foo", 0, 0, &rval);
|
||||
|
||||
jsval argv[2];
|
||||
|
||||
/* Call a function in obj's scope named "method", passing two arguments. */
|
||||
argv[0] = . . .;
|
||||
argv[1] = . . .;
|
||||
ok = JS_CallFunctionName(cx, obj, "method", 2, argv, &rval);</tt></pre>
|
||||
|
||||
<h4>
|
||||
Shutting down</h4>
|
||||
|
||||
<pre><tt> /* For each context you've created: */
|
||||
JS_DestroyContext(cx);
|
||||
|
||||
/* And finally: */
|
||||
JS_Finish(rt);</tt></pre>
|
||||
|
||||
<h4>
|
||||
Debugging API</h4>
|
||||
See the<tt> trap, untrap, watch, unwatch, line2pc</tt>, and <tt>pc2line</tt>
|
||||
commands in <tt>js.c</tt>. Also the (scant) comments in <i>jsdbgapi.h</i>.
|
||||
<h2>
|
||||
<a NAME="Design"></a>Design walk-through</h2>
|
||||
This section must be brief for now -- it could easily turn into a book.
|
||||
<h4>
|
||||
JS "JavaScript Proper"</h4>
|
||||
JS modules declare and implement the JavaScript compiler, interpreter,
|
||||
decompiler, GC and atom manager, and standard classes.
|
||||
<p>JavaScript uses untyped bytecode and runtime type tagging of data values.
|
||||
The <tt>jsval</tt> type is a signed machine word that contains either a
|
||||
signed integer value (if the low bit is set), or a type-tagged pointer
|
||||
or boolean value (if the low bit is clear). Tagged pointers all refer to
|
||||
8-byte-aligned things in the GC heap.
|
||||
<p>Objects consist of a possibly shared structural description, called
|
||||
the map or scope; and unshared property values in a vector, called the
|
||||
slots. Object properties are associated with nonnegative integers stored
|
||||
in <tt>jsval</tt>'s, or with atoms (unique string descriptors) if named
|
||||
by an identifier or a non-integral index expression.
|
||||
<p>Scripts contain bytecode, source annotations, and a pool of string,
|
||||
number, and identifier literals. Functions are objects that extend scripts
|
||||
or native functions with formal parameters, a literal syntax, and a distinct
|
||||
primitive type ("function").
|
||||
<p>The compiler consists of a recursive-descent parser and a random-logic
|
||||
rather than table-driven lexical scanner. Semantic and lexical feedback
|
||||
are used to disambiguate hard cases such as missing semicolons, assignable
|
||||
expressions ("lvalues" in C parlance), etc. The parser generates bytecode
|
||||
as it parses, using fixup lists for downward branches and code buffering
|
||||
and rewriting for exceptional cases such as for loops. It attempts no error
|
||||
recovery. The interpreter executes the bytecode of top-level scripts, and
|
||||
calls itself indirectly to interpret function bodies (which are also scripts).
|
||||
All state associated with an interpreter instance is passed through formal
|
||||
parameters to the interpreter entry point; most implicit state is collected
|
||||
in a type named JSContext. Therefore, all API and almost all other functions
|
||||
in JSRef take a JSContext pointer as their first argument.
|
||||
<p>The decompiler translates postfix bytecode into infix source by consulting
|
||||
a separate byte-sized code, called source notes, to disambiguate bytecodes
|
||||
that result from more than one grammatical production.
|
||||
<p>The GC is a mark-and-sweep, non-conservative (perfect) collector. It
|
||||
can allocate only fixed-sized things -- the current size is two machine
|
||||
words. It is used to hold JS object and string descriptors (but not property
|
||||
lists or string bytes), and double-precision floating point numbers. It
|
||||
runs automatically only when maxbytes (as passed to <tt>JS_Init()</tt>)
|
||||
bytes of GC things have been allocated and another thing-allocation request
|
||||
is made. JS API users should call <tt>JS_GC()</tt> or <tt>JS_MaybeGC()</tt>
|
||||
between script executions or from the branch callback, as often as necessary.
|
||||
<p>An important point about the GC's "perfection": you must add roots for
|
||||
new objects created by your native methods if you store references to them
|
||||
into a non-JS structure in the malloc heap or in static data. Also, if
|
||||
you make a new object in a native method, but do not store it through the
|
||||
<tt>rval</tt>
|
||||
result parameter (see math_abs in the "Using the JS API" section above)
|
||||
so that it is in a known root, the object is guaranteed to survive only
|
||||
until another new object is created. Either lock the first new object when
|
||||
making two in a row, or store it in a root you've added, or store it via
|
||||
rval.
|
||||
<p>The atom manager consists of a hash table associating strings uniquely
|
||||
with scanner/parser information such as keyword type, index in script or
|
||||
function literal pool, etc. Atoms play three roles in JSRef: as literals
|
||||
referred to by unaligned 16-bit immediate bytecode operands, as unique
|
||||
string descriptors for efficient property name hashing, and as members
|
||||
of the root GC set for perfect GC. This design therefore requires atoms
|
||||
to be manually reference counted, from script literal pools (<tt>JSAtomMap</tt>)
|
||||
and object symbol (<tt>JSSymbol</tt>) entry keys.
|
||||
<p>Native objects and methods for arrays, booleans, dates, functions, numbers,
|
||||
and strings are implemented using the JS API and certain internal interfaces
|
||||
used as "fast paths".
|
||||
<p>In general, errors are signaled by false or unoverloaded-null return
|
||||
values, and are reported using <tt>JS_ReportError()</tt> or one of its
|
||||
variants by the lowest level in order to provide the most detail. Client
|
||||
code can substitute its own error reporting function and suppress errors,
|
||||
or reflect them into Java or some other runtime system as exceptions, GUI
|
||||
dialogs, etc..
|
||||
<h2>
|
||||
File walk-through (BADLY OUT OF DATE!)</h2>
|
||||
|
||||
<h4>
|
||||
jsapi.c, jsapi.h</h4>
|
||||
The public API to be used by almost all client code. If your client
|
||||
code can't make do with <tt>jsapi.h</tt>, and must reach into a friend
|
||||
or private js* file, please let us know so we can extend <tt>jsapi.h</tt>
|
||||
to include what you need in a fashion that we can support over the long
|
||||
run.
|
||||
<h4>
|
||||
jspubtd.h, jsprvtd.h</h4>
|
||||
These files exist to group struct and scalar typedefs so they can be used
|
||||
everywhere without dragging in struct definitions from N different files.
|
||||
The <tt>jspubtd.h</tt> file contains public typedefs, and is included by
|
||||
<tt>jsapi.h</tt>.
|
||||
The <tt>jsprvtd.h</tt> file contains private typedefs and is included by
|
||||
various .h files that need type names, but not type sizes or declarations.
|
||||
<h4>
|
||||
jsdbgapi.c, jsdbgapi.h</h4>
|
||||
The Debugging API, still very much under development. Provided so far:
|
||||
<ul>
|
||||
<li>
|
||||
Traps, with which breakpoints, single-stepping, step over, step out, and
|
||||
so on can be implemented. The debugger will have to consult jsopcode.def
|
||||
on its own to figure out where to plant trap instructions to implement
|
||||
functions like step out, but a future jsdbgapi.h will provide convenience
|
||||
interfaces to do these things. At most one trap per bytecode can be set.
|
||||
When a script (<tt>JSScript</tt>) is destroyed, all traps set in its bytecode
|
||||
are cleared.</li>
|
||||
|
||||
<li>
|
||||
Watchpoints, for intercepting set operations on properties and running
|
||||
a debugger-supplied function that receives the old value and a pointer
|
||||
to the new one, which it can use to modify the new value being set.</li>
|
||||
|
||||
<li>
|
||||
Line number to PC and back mapping functions. The line-to-PC direction
|
||||
"rounds" toward the next bytecode generated from a line greater than or
|
||||
equal to the input line, and may return the PC of a for-loop update part,
|
||||
if given the line number of the loop body's closing brace. Any line after
|
||||
the last one in a script or function maps to a PC one byte beyond the last
|
||||
bytecode in the script. An example, from perfect.js:</li>
|
||||
|
||||
<pre><tt>14 function perfect(n)
|
||||
15 {
|
||||
16 print("The perfect numbers up to " + n + " are:");
|
||||
17
|
||||
18 // We build sumOfDivisors[i] to hold a string expression for
|
||||
19 // the sum of the divisors of i, excluding i itself.
|
||||
20 var sumOfDivisors = new ExprArray(n+1,1);
|
||||
21 for (var divisor = 2; divisor <= n; divisor++) {
|
||||
22 for (var j = divisor + divisor; j <= n; j += divisor) {
|
||||
23 sumOfDivisors[j] += " + " + divisor;
|
||||
24 }
|
||||
25 // At this point everything up to 'divisor' has its sumOfDivisors
|
||||
26 // expression calculated, so we can determine whether it's perfect
|
||||
27 // already by evaluating.
|
||||
28 if (eval(sumOfDivisors[divisor]) == divisor) {
|
||||
29 print("" + divisor + " = " + sumOfDivisors[divisor]);
|
||||
30 }
|
||||
31 }
|
||||
32 delete sumOfDivisors;
|
||||
33 print("That's all.");
|
||||
34 }</tt></pre>
|
||||
The line number to PC and back mappings can be tested using the js program
|
||||
with the following script:
|
||||
<pre><tt> load("perfect.js")
|
||||
print(perfect)
|
||||
dis(perfect)
|
||||
|
||||
print()
|
||||
for (var ln = 0; ln <= 40; ln++) {
|
||||
var pc = line2pc(perfect,ln)
|
||||
var ln2 = pc2line(perfect,pc)
|
||||
print("\tline " + ln + " => pc " + pc + " => line " + ln2)
|
||||
}</tt></pre>
|
||||
The result of the for loop over lines 0 to 40 inclusive is:
|
||||
<pre><tt> line 0 => pc 0 => line 16
|
||||
line 1 => pc 0 => line 16
|
||||
line 2 => pc 0 => line 16
|
||||
line 3 => pc 0 => line 16
|
||||
line 4 => pc 0 => line 16
|
||||
line 5 => pc 0 => line 16
|
||||
line 6 => pc 0 => line 16
|
||||
line 7 => pc 0 => line 16
|
||||
line 8 => pc 0 => line 16
|
||||
line 9 => pc 0 => line 16
|
||||
line 10 => pc 0 => line 16
|
||||
line 11 => pc 0 => line 16
|
||||
line 12 => pc 0 => line 16
|
||||
line 13 => pc 0 => line 16
|
||||
line 14 => pc 0 => line 16
|
||||
line 15 => pc 0 => line 16
|
||||
line 16 => pc 0 => line 16
|
||||
line 17 => pc 19 => line 20
|
||||
line 18 => pc 19 => line 20
|
||||
line 19 => pc 19 => line 20
|
||||
line 20 => pc 19 => line 20
|
||||
line 21 => pc 36 => line 21
|
||||
line 22 => pc 53 => line 22
|
||||
line 23 => pc 74 => line 23
|
||||
line 24 => pc 92 => line 22
|
||||
line 25 => pc 106 => line 28
|
||||
line 26 => pc 106 => line 28
|
||||
line 27 => pc 106 => line 28
|
||||
line 28 => pc 106 => line 28
|
||||
line 29 => pc 127 => line 29
|
||||
line 30 => pc 154 => line 21
|
||||
line 31 => pc 154 => line 21
|
||||
line 32 => pc 161 => line 32
|
||||
line 33 => pc 172 => line 33
|
||||
line 34 => pc 172 => line 33
|
||||
line 35 => pc 172 => line 33
|
||||
line 36 => pc 172 => line 33
|
||||
line 37 => pc 172 => line 33
|
||||
line 38 => pc 172 => line 33
|
||||
line 39 => pc 172 => line 33
|
||||
line 40 => pc 172 => line 33</tt></pre>
|
||||
</ul>
|
||||
|
||||
<h4>
|
||||
jsconfig.h</h4>
|
||||
Various configuration macros defined as 0 or 1 depending on how <tt>JS_VERSION</tt>
|
||||
is defined (as 10 for JavaScript 1.0, 11 for JavaScript 1.1, etc.). Not
|
||||
all macros are tested around related code yet. In particular, JS 1.0 support
|
||||
is missing from JSRef. JS 1.2 support will appear in a future JSRef release.
|
||||
<br>
|
||||
<h4>
|
||||
js.c</h4>
|
||||
The "JS shell", a simple interpreter program that uses the JS API and more
|
||||
than a few internal interfaces (some of these internal interfaces could
|
||||
be replaced by <tt>jsapi.h</tt> calls). The js program built from this
|
||||
source provides a test vehicle for evaluating scripts and calling functions,
|
||||
trying out new debugger primitives, etc.
|
||||
<h4>
|
||||
jsarray.*, jsbool.*, jdsdate.*, jsfun.*, jsmath.*, jsnum.*, jsstr.*</h4>
|
||||
These file pairs implement the standard classes and (where they exist)
|
||||
their underlying primitive types. They have similar structure, generally
|
||||
starting with class definitions and continuing with internal constructors,
|
||||
finalizers, and helper functions.
|
||||
<h4>
|
||||
jsobj.*, jsscope.*</h4>
|
||||
These two pairs declare and implement the JS object system. All of the
|
||||
following happen here:
|
||||
<ul>
|
||||
<li>
|
||||
creating objects by class and prototype, and finalizing objects;</li>
|
||||
|
||||
<li>
|
||||
defining, looking up, getting, setting, and deleting properties;</li>
|
||||
|
||||
<li>
|
||||
creating and destroying properties and binding names to them.</li>
|
||||
</ul>
|
||||
The details of an object map (scope) are mostly hidden in <tt>jsscope.[ch]</tt>,
|
||||
where scopes start out as linked lists of symbols, and grow after some
|
||||
threshold into PR hash tables.
|
||||
<h4>
|
||||
jsatom.c, jsatom.h</h4>
|
||||
The atom manager. Contains well-known string constants, their atoms, the
|
||||
global atom hash table and related state, the js_Atomize() function that
|
||||
turns a counted string of bytes into an atom, and literal pool (<tt>JSAtomMap</tt>)
|
||||
methods.
|
||||
<h4>
|
||||
jsgc.c, jsgc.h</h4>
|
||||
[TBD]
|
||||
<h4>
|
||||
jsinterp.*, jscntxt.*</h4>
|
||||
The bytecode interpreter, and related functions such as Call and AllocStack,
|
||||
live in <i>jsinterp.c</i>. The JSContext constructor and destructor are
|
||||
factored out into <i>jscntxt.c</i> for minimal linking when the compiler
|
||||
part of JS is split from the interpreter part into a separate program.
|
||||
<h4>
|
||||
jsemit.*, jsopcode.tbl, jsopcode.*, jsparse.*, jsscan.*, jsscript.*</h4>
|
||||
Compiler and decompiler modules. The <i>jsopcode.tbl</i> file is a C preprocessor
|
||||
source that defines almost everything there is to know about JS bytecodes.
|
||||
See its major comment for how to use it. For now, a debugger will use it
|
||||
and its dependents such as <i>jsopcode.h</i> directly, but over time we
|
||||
intend to extend <i>jsdbgapi.h</i> to hide uninteresting details and provide
|
||||
conveniences. The code generator is split across paragraphs of code in
|
||||
<i>jsparse.c</i>,
|
||||
and the utility methods called on <tt>JSCodeGenerator</tt> appear in <i>jsemit.c</i>.
|
||||
Source notes generated by <i>jsparse.c</i> and
|
||||
<i>jsemit.c</i> are used
|
||||
in <i>jsscript.c</i> to map line number to program counter and back.
|
||||
<h4>
|
||||
jstypes.h, jslog2.c</h4>
|
||||
Fundamental representation types and utility macros. This file alone among
|
||||
all .h files in JSRef must be included first by .c files. It is not nested
|
||||
in .h files, as other prerequisite .h files generally are, since it is
|
||||
also a direct dependency of most .c files and would be over-included if
|
||||
nested in addition to being directly included. The one "not-quite-a-macro
|
||||
macro" is the <tt>JS_CeilingLog2()</tt> function in <i>jslog2.c</i>.
|
||||
<h4>
|
||||
jsarena.c, jsarena.h</h4>
|
||||
Last-In-First-Out allocation macros that amortize malloc costs and allow
|
||||
for en-masse freeing. See the paper mentioned in prarena.h's major comment.
|
||||
<h4>
|
||||
jsutil.c, jsutil.h</h4>
|
||||
The <tt>JS_ASSERT</tt> macro is used throughout JSRef source as a proof
|
||||
device to make invariants and preconditions clear to the reader, and to
|
||||
hold the line during maintenance and evolution against regressions or violations
|
||||
of assumptions that it would be too expensive to test unconditionally at
|
||||
run-time. Certain assertions are followed by run-time tests that cope with
|
||||
assertion failure, but only where I'm too smart or paranoid to believe
|
||||
the assertion will never fail...
|
||||
<h4>
|
||||
jsclist.h</h4>
|
||||
Doubly-linked circular list struct and macros.
|
||||
<h4>
|
||||
jscpucfg.c</h4>
|
||||
This standalone program generates <i>jscpucfg.h</i>, a header file containing
|
||||
bytes per word and other constants that depend on CPU architecture and
|
||||
C compiler type model. It tries to discover most of these constants by
|
||||
running its own experiments on the build host, so if you are cross-compiling,
|
||||
beware.
|
||||
<h4>
|
||||
prdtoa.c, prdtoa.h</h4>
|
||||
David Gay's portable double-precision floating point to string conversion
|
||||
code, with Permission To Use notice included.
|
||||
<h4>
|
||||
prhash.c, prhash.h</h4>
|
||||
Portable, extensible hash tables. These use multiplicative hash for strength
|
||||
reduction over division hash, yet with very good key distribution over
|
||||
power of two table sizes. Collisions resolve via chaining, so each entry
|
||||
burns a malloc and can fragment the heap.
|
||||
<h4>
|
||||
prlong.c, prlong.h</h4>
|
||||
64-bit integer emulation, and compatible macros that use C's long long
|
||||
type where it exists (my last company mapped long long to a 128-bit type,
|
||||
but no real architecture does 128-bit ints yet).
|
||||
<h4>
|
||||
jsosdep.h</h4>
|
||||
Annoying OS dependencies rationalized into a few "feature-test" macros
|
||||
such as <tt>JS_HAVE_LONG_LONG</tt>.
|
||||
<h4>
|
||||
jsprf.*</h4>
|
||||
Portable, buffer-overrun-resistant sprintf and friends. For no good reason
|
||||
save lack of time, the %e, %f, and %g formats cause your system's native
|
||||
sprintf, rather than <tt>JS_dtoa()</tt>, to be used. This bug doesn't affect
|
||||
JSRef, because it uses its own <tt>JS_dtoa()</tt> call in <i>jsnum.c</i>
|
||||
to convert from double to string, but it's a bug that we'll fix later,
|
||||
and one you should be aware of if you intend to use a <tt>JS_*printf()</tt>
|
||||
function with your own floating type arguments - various vendor sprintf's
|
||||
mishandle NaN, +/-Inf, and some even print normal floating values inaccurately.
|
||||
<h4>
|
||||
prmjtime.c, prmjtime.h</h4>
|
||||
Time functions. These interfaces are named in a way that makes local vs.
|
||||
universal time confusion likely. Caveat emptor, and we're working on it.
|
||||
To make matters worse, Java (and therefore JavaScript) uses "local" time
|
||||
numbers (offsets from the epoch) in its Date class.
|
||||
</body>
|
||||
</html>
|
||||
12
mozilla/js/src/SpiderMonkey.rsp
Normal file
12
mozilla/js/src/SpiderMonkey.rsp
Normal file
@@ -0,0 +1,12 @@
|
||||
mozilla/js/src/*
|
||||
mozilla/js/src/config/*
|
||||
mozilla/js/src/fdlibm/*
|
||||
mozilla/js/src/liveconnect/*
|
||||
mozilla/js/src/liveconnect/_jni/*
|
||||
mozilla/js/src/liveconnect/classes/*
|
||||
mozilla/js/src/liveconnect/classes/netscape/*
|
||||
mozilla/js/src/liveconnect/classes/netscape/javascript/*
|
||||
mozilla/js/src/liveconnect/config/*
|
||||
mozilla/js/src/liveconnect/macbuild/*
|
||||
mozilla/js/src/liveconnect/macbuild/JavaSession/*
|
||||
mozilla/js/src/macbuild/*
|
||||
65
mozilla/js/src/config.mk
Normal file
65
mozilla/js/src/config.mk
Normal file
@@ -0,0 +1,65 @@
|
||||
ifdef JS_DIST
|
||||
DIST = $(JS_DIST)
|
||||
else
|
||||
DIST = $(DEPTH)/../../dist/$(OBJDIR)
|
||||
endif
|
||||
|
||||
# Set os+release dependent make variables
|
||||
OS_ARCH := $(subst /,_,$(shell uname -s))
|
||||
|
||||
# Attempt to differentiate between SunOS 5.4 and x86 5.4
|
||||
OS_CPUARCH := $(shell uname -m)
|
||||
ifeq ($(OS_CPUARCH),i86pc)
|
||||
OS_RELEASE := $(shell uname -r)_$(OS_CPUARCH)
|
||||
else
|
||||
ifeq ($(OS_ARCH),AIX)
|
||||
OS_RELEASE := $(shell uname -v).$(shell uname -r)
|
||||
else
|
||||
OS_RELEASE := $(shell uname -r)
|
||||
endif
|
||||
endif
|
||||
|
||||
# Virtually all Linux versions are identical.
|
||||
# Any distinctions are handled in linux.h
|
||||
ifeq ($(OS_ARCH),Linux)
|
||||
OS_CONFIG := Linux_All
|
||||
else
|
||||
ifeq ($(OS_ARCH),dgux)
|
||||
OS_CONFIG := dgux
|
||||
else
|
||||
OS_CONFIG := $(OS_ARCH)$(OS_OBJTYPE)$(OS_RELEASE)
|
||||
endif
|
||||
endif
|
||||
|
||||
ASFLAGS =
|
||||
DEFINES =
|
||||
|
||||
ifeq ($(OS_ARCH), WINNT)
|
||||
INSTALL = nsinstall
|
||||
else
|
||||
INSTALL = $(DEPTH)/../../dist/$(OBJDIR)/bin/nsinstall
|
||||
endif
|
||||
|
||||
ifdef BUILD_OPT
|
||||
OPTIMIZER = -O
|
||||
DEFINES += -UDEBUG -DNDEBUG -UDEBUG_$(shell whoami)
|
||||
OBJDIR_TAG = _OPT
|
||||
else
|
||||
ifdef USE_MSVC
|
||||
OPTIMIZER = -Zi
|
||||
else
|
||||
OPTIMIZER = -g
|
||||
endif
|
||||
DEFINES += -DDEBUG -DDEBUG_$(shell whoami)
|
||||
OBJDIR_TAG = _DBG
|
||||
endif
|
||||
|
||||
include $(DEPTH)/config/$(OS_CONFIG).mk
|
||||
|
||||
# Name of the binary code directories
|
||||
OBJDIR = $(OS_CONFIG)$(OBJDIR_TAG).OBJ
|
||||
VPATH = $(OBJDIR)
|
||||
|
||||
# Automatic make dependencies file
|
||||
DEPENDENCIES = $(OBJDIR)/.md
|
||||
|
||||
1609
mozilla/js/src/js.c
Normal file
1609
mozilla/js/src/js.c
Normal file
File diff suppressed because it is too large
Load Diff
4027
mozilla/js/src/js.mak
Normal file
4027
mozilla/js/src/js.mak
Normal file
File diff suppressed because it is too large
Load Diff
BIN
mozilla/js/src/js.mdp
Normal file
BIN
mozilla/js/src/js.mdp
Normal file
Binary file not shown.
206
mozilla/js/src/js.msg
Normal file
206
mozilla/js/src/js.msg
Normal file
@@ -0,0 +1,206 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
This is the JavaScript error message file.
|
||||
|
||||
The format for each JS error message is:
|
||||
|
||||
MSG_DEF(<SYMBOLIC_NAME>, <ERROR_NUMBER>, <ARGUMENT_COUNT>, <EXCEPTION_NAME>,
|
||||
<FORMAT_STRING>)
|
||||
|
||||
where ;
|
||||
<SYMBOLIC_NAME> is a legal C identifer that will be used in the
|
||||
JS engine source.
|
||||
|
||||
<ERROR_NUMBER> is an unique integral value identifying this error.
|
||||
|
||||
<ARGUMENT_COUNT> is an integer literal specifying the total number of
|
||||
replaceable arguments in the following format string.
|
||||
|
||||
<EXCEPTION_NAME> is an exception index from the enum in jsexn.c;
|
||||
JSEXN_NONE for none. The given exception index will be raised by the
|
||||
engine when the corresponding error occurs.
|
||||
|
||||
<FORMAT_STRING> is a string literal, optionally containing sequences
|
||||
{X} where X is an integer representing the argument number that will
|
||||
be replaced with a string value when the error is reported.
|
||||
|
||||
e.g.
|
||||
|
||||
MSG_DEF(JSMSG_NOT_A_SUBSPECIES, 73, JSEXN_NONE, 2,
|
||||
"{0} is not a member of the {1} family")
|
||||
|
||||
can be used :
|
||||
|
||||
JS_ReportErrorNumber(JSMSG_NOT_A_SUBSPECIES, "Rhino", "Monkey");
|
||||
|
||||
to report :
|
||||
|
||||
"Rhino is not a member of the Monkey family"
|
||||
|
||||
*/
|
||||
|
||||
MSG_DEF(JSMSG_NOT_AN_ERROR, 0, 0, JSEXN_NONE, "<Error #0 is reserved>")
|
||||
MSG_DEF(JSMSG_NOT_DEFINED, 1, 1, JSEXN_REFERENCEERR, "{0} is not defined")
|
||||
MSG_DEF(JSMSG_NO_REG_EXPS, 2, 1, JSEXN_INTERNALERR, "sorry, regular expression are not supported")
|
||||
MSG_DEF(JSMSG_MORE_ARGS_NEEDED, 3, 3, JSEXN_NONE, "{0} requires more than {1} argument{2}")
|
||||
MSG_DEF(JSMSG_BAD_CHAR, 4, 1, JSEXN_NONE, "invalid format character {0}")
|
||||
MSG_DEF(JSMSG_BAD_TYPE, 5, 1, JSEXN_NONE, "unknown type {0}")
|
||||
MSG_DEF(JSMSG_CANT_LOCK, 6, 0, JSEXN_NONE, "can't lock memory")
|
||||
MSG_DEF(JSMSG_CANT_UNLOCK, 7, 0, JSEXN_NONE, "can't unlock memory")
|
||||
MSG_DEF(JSMSG_INCOMPATIBLE_PROTO, 8, 3, JSEXN_TARGETERR, "{0}.prototype.{1} called on incompatible {2}")
|
||||
MSG_DEF(JSMSG_NO_CONSTRUCTOR, 9, 1, JSEXN_NONE, "{0} has no constructor")
|
||||
MSG_DEF(JSMSG_CANT_ALIAS, 10, 3, JSEXN_NONE, "can't alias {0} to {1} in class {2}")
|
||||
MSG_DEF(JSMSG_NO_PROTO, 11, 1, JSEXN_INTERNALERR, "sorry, Array.prototype.{0} is not yet implemented")
|
||||
MSG_DEF(JSMSG_BAD_SORT_ARG, 12, 0, JSEXN_ARRAYERR, "invalid Array.prototype.sort argument")
|
||||
MSG_DEF(JSMSG_BAD_ATOMIC_NUMBER, 13, 1, JSEXN_INTERNALERR, "internal error: no index for atom {0}")
|
||||
MSG_DEF(JSMSG_TOO_MANY_LITERALS, 14, 0, JSEXN_INTERNALERR, "too many literals")
|
||||
MSG_DEF(JSMSG_CANT_WATCH, 15, 1, JSEXN_NONE, "can't watch non-native objects of class {0}")
|
||||
MSG_DEF(JSMSG_STACK_UNDERFLOW, 16, 2, JSEXN_INTERNALERR, "internal error compiling {0}: stack underflow at pc {1}")
|
||||
MSG_DEF(JSMSG_NEED_DIET, 17, 1, JSEXN_SYNTAXERR, "{0} too large")
|
||||
MSG_DEF(JSMSG_BAD_CASE, 18, 2, JSEXN_SYNTAXERR, "{0}, line {1}: invalid case expression")
|
||||
MSG_DEF(JSMSG_READ_ONLY, 19, 1, JSEXN_ERR, "{0} is read-only")
|
||||
MSG_DEF(JSMSG_BAD_FORMAL, 20, 0, JSEXN_SYNTAXERR, "malformed formal parameter")
|
||||
MSG_DEF(JSMSG_SAME_FORMAL, 21, 1, JSEXN_NONE, "duplicate formal argument {0}")
|
||||
MSG_DEF(JSMSG_NOT_FUNCTION, 22, 1, JSEXN_CALLERR, "{0} is not a function")
|
||||
MSG_DEF(JSMSG_NOT_CONSTRUCTOR, 23, 1, JSEXN_CONSTRUCTORERR, "{0} is not a constructor")
|
||||
MSG_DEF(JSMSG_STACK_OVERFLOW, 24, 1, JSEXN_NONE, "stack overflow in {0}")
|
||||
MSG_DEF(JSMSG_NOT_EXPORTED, 25, 1, JSEXN_NONE, "{0} is not exported")
|
||||
MSG_DEF(JSMSG_OVER_RECURSED, 26, 0, JSEXN_NONE, "too much recursion")
|
||||
MSG_DEF(JSMSG_IN_NOT_OBJECT, 27, 0, JSEXN_ERR, "target of 'in' operator must be an object")
|
||||
MSG_DEF(JSMSG_BAD_NEW_RESULT, 28, 1, JSEXN_NONE, "invalid new expression result {0}")
|
||||
MSG_DEF(JSMSG_BAD_SHARP_DEF, 29, 1, JSEXN_ERR, "invalid sharp variable definition #{0}=")
|
||||
MSG_DEF(JSMSG_BAD_SHARP_USE, 30, 1, JSEXN_ERR, "invalid sharp variable use #{0}#")
|
||||
MSG_DEF(JSMSG_BAD_INSTANCEOF_RHS, 31, 1, JSEXN_ERR, "invalid instanceof operand {0}")
|
||||
MSG_DEF(JSMSG_BAD_BYTECODE, 32, 1, JSEXN_INTERNALERR, "unimplemented JavaScript bytecode {0}")
|
||||
MSG_DEF(JSMSG_BAD_RADIX, 33, 1, JSEXN_ERR, "illegal radix {0}")
|
||||
MSG_DEF(JSMSG_NAN, 34, 1, JSEXN_ERR, "{0} is not a number")
|
||||
MSG_DEF(JSMSG_CANT_CONVERT, 35, 1, JSEXN_TOPRIMITIVEERR, "can't convert {0} to an integer")
|
||||
MSG_DEF(JSMSG_CYCLIC_VALUE, 36, 1, JSEXN_ERR, "cyclic {0} value")
|
||||
MSG_DEF(JSMSG_PERMANENT, 37, 1, JSEXN_ERR, "{0} is permanent")
|
||||
MSG_DEF(JSMSG_CANT_CONVERT_TO, 38, 2, JSEXN_DEFAULTVALUEERR, "can't convert {0} to {1}")
|
||||
MSG_DEF(JSMSG_NO_PROPERTIES, 39, 1, JSEXN_TOOBJECTERR, "{0} has no properties")
|
||||
MSG_DEF(JSMSG_CANT_FIND_CLASS, 40, 1, JSEXN_NONE, "can't find class id {0}")
|
||||
MSG_DEF(JSMSG_CANT_XDR_CLASS, 41, 1, JSEXN_NONE, "can't XDR class {0}")
|
||||
MSG_DEF(JSMSG_BYTECODE_TOO_BIG, 42, 2, JSEXN_INTERNALERR, "bytecode {0} too large (limit {1})")
|
||||
MSG_DEF(JSMSG_UNKNOWN_FORMAT, 43, 1, JSEXN_INTERNALERR, "unknown bytecode format {0}")
|
||||
MSG_DEF(JSMSG_TOO_MANY_CON_ARGS, 44, 0, JSEXN_SYNTAXERR, "too many constructor arguments")
|
||||
MSG_DEF(JSMSG_TOO_MANY_FUN_ARGS, 45, 0, JSEXN_SYNTAXERR, "too many function arguments")
|
||||
MSG_DEF(JSMSG_BAD_QUANTIFIER, 46, 1, JSEXN_SYNTAXERR, "invalid quantifier {0}")
|
||||
MSG_DEF(JSMSG_MIN_TOO_BIG, 47, 1, JSEXN_SYNTAXERR, "overlarge minimum {0}")
|
||||
MSG_DEF(JSMSG_MAX_TOO_BIG, 48, 1, JSEXN_SYNTAXERR, "overlarge maximum {0}")
|
||||
MSG_DEF(JSMSG_OUT_OF_ORDER, 49, 1, JSEXN_SYNTAXERR, "maximum {0} less than minimum")
|
||||
MSG_DEF(JSMSG_ZERO_QUANTIFIER, 50, 1, JSEXN_SYNTAXERR, "zero quantifier {0}")
|
||||
MSG_DEF(JSMSG_UNTERM_QUANTIFIER, 51, 1, JSEXN_SYNTAXERR, "unterminated quantifier {0}")
|
||||
MSG_DEF(JSMSG_EMPTY_BEFORE_STAR, 52, 0, JSEXN_SYNTAXERR, "regular expression before * could be empty")
|
||||
MSG_DEF(JSMSG_EMPTY_BEFORE_PLUS, 53, 0, JSEXN_SYNTAXERR, "regular expression before + could be empty")
|
||||
MSG_DEF(JSMSG_MISSING_PAREN, 54, 1, JSEXN_SYNTAXERR, "unterminated parenthetical {0}")
|
||||
MSG_DEF(JSMSG_UNTERM_CLASS, 55, 1, JSEXN_SYNTAXERR, "unterminated character class {0}")
|
||||
MSG_DEF(JSMSG_TRAILING_SLASH, 56, 0, JSEXN_SYNTAXERR, "trailing \\ in regular expression")
|
||||
MSG_DEF(JSMSG_BAD_CLASS_RANGE, 57, 0, JSEXN_SYNTAXERR, "invalid range in character class")
|
||||
MSG_DEF(JSMSG_BAD_FLAG, 58, 1, JSEXN_SYNTAXERR, "invalid regular expression flag {0}")
|
||||
MSG_DEF(JSMSG_NO_INPUT, 59, 3, JSEXN_SYNTAXERR, "no input for /{0}/{1}{2}")
|
||||
MSG_DEF(JSMSG_CANT_OPEN, 60, 2, JSEXN_NONE, "can't open {0}: {1}")
|
||||
MSG_DEF(JSMSG_BAD_STRING_MASK, 61, 1, JSEXN_ERR, "invalid string escape mask {0}")
|
||||
MSG_DEF(JSMSG_NO_STRING_PROTO, 62, 1, JSEXN_INTERNALERR, "sorry, String.prototype.{0} is not yet implemented")
|
||||
MSG_DEF(JSMSG_END_OF_DATA, 63, 0, JSEXN_NONE, "unexpected end of data")
|
||||
MSG_DEF(JSMSG_SEEK_BEYOND_START, 64, 0, JSEXN_NONE, "illegal seek beyond start")
|
||||
MSG_DEF(JSMSG_SEEK_BEYOND_END, 65, 0, JSEXN_NONE, "illegal seek beyond end")
|
||||
MSG_DEF(JSMSG_END_SEEK, 66, 0, JSEXN_NONE, "illegal end-based seek")
|
||||
MSG_DEF(JSMSG_WHITHER_WHENCE, 67, 1, JSEXN_NONE, "unknown seek whence: {0}")
|
||||
MSG_DEF(JSMSG_BAD_JVAL_TYPE, 68, 1, JSEXN_NONE, "unknown jsval type {0} for XDR")
|
||||
MSG_DEF(JSMSG_PAREN_BEFORE_FORMAL, 69, 0, JSEXN_SYNTAXERR, "missing ( before formal parameters")
|
||||
MSG_DEF(JSMSG_MISSING_FORMAL, 70, 0, JSEXN_SYNTAXERR, "missing formal parameter")
|
||||
MSG_DEF(JSMSG_PAREN_AFTER_FORMAL, 71, 0, JSEXN_SYNTAXERR, "missing ) after formal parameters")
|
||||
MSG_DEF(JSMSG_CURLY_BEFORE_BODY, 72, 0, JSEXN_SYNTAXERR, "missing { before function body")
|
||||
MSG_DEF(JSMSG_CURLY_AFTER_BODY, 73, 0, JSEXN_SYNTAXERR, "missing } after function body")
|
||||
MSG_DEF(JSMSG_PAREN_BEFORE_COND, 74, 0, JSEXN_SYNTAXERR, "missing ( before condition")
|
||||
MSG_DEF(JSMSG_PAREN_AFTER_COND, 75, 0, JSEXN_SYNTAXERR, "missing ) after condition")
|
||||
MSG_DEF(JSMSG_NO_IMPORT_NAME, 76, 0, JSEXN_SYNTAXERR, "missing name in import statement")
|
||||
MSG_DEF(JSMSG_NAME_AFTER_DOT, 77, 0, JSEXN_SYNTAXERR, "missing name after . operator")
|
||||
MSG_DEF(JSMSG_BRACKET_IN_INDEX, 78, 0, JSEXN_SYNTAXERR, "missing ] in index expression")
|
||||
MSG_DEF(JSMSG_NO_EXPORT_NAME, 79, 0, JSEXN_SYNTAXERR, "missing name in export statement")
|
||||
MSG_DEF(JSMSG_PAREN_BEFORE_SWITCH, 80, 0, JSEXN_SYNTAXERR, "missing ( before switch expression")
|
||||
MSG_DEF(JSMSG_PAREN_AFTER_SWITCH, 81, 0, JSEXN_SYNTAXERR, "missing ) after switch expression")
|
||||
MSG_DEF(JSMSG_CURLY_BEFORE_SWITCH, 82, 0, JSEXN_SYNTAXERR, "missing { before switch body")
|
||||
MSG_DEF(JSMSG_COLON_AFTER_CASE, 83, 0, JSEXN_SYNTAXERR, "missing : after case label")
|
||||
MSG_DEF(JSMSG_WHILE_AFTER_DO, 84, 0, JSEXN_SYNTAXERR, "missing while after do-loop body")
|
||||
MSG_DEF(JSMSG_PAREN_AFTER_FOR, 85, 0, JSEXN_SYNTAXERR, "missing ( after for")
|
||||
MSG_DEF(JSMSG_SEMI_AFTER_FOR_INIT, 86, 0, JSEXN_SYNTAXERR, "missing ; after for-loop initializer")
|
||||
MSG_DEF(JSMSG_SEMI_AFTER_FOR_COND, 87, 0, JSEXN_SYNTAXERR, "missing ; after for-loop condition")
|
||||
MSG_DEF(JSMSG_PAREN_AFTER_FOR_CTRL, 88, 0, JSEXN_SYNTAXERR, "missing ) after for-loop control")
|
||||
MSG_DEF(JSMSG_CURLY_BEFORE_TRY, 89, 0, JSEXN_SYNTAXERR, "missing { before try block")
|
||||
MSG_DEF(JSMSG_CURLY_AFTER_TRY, 90, 0, JSEXN_SYNTAXERR, "missing } after try block")
|
||||
MSG_DEF(JSMSG_PAREN_BEFORE_CATCH, 91, 0, JSEXN_SYNTAXERR, "missing ( before catch")
|
||||
MSG_DEF(JSMSG_CATCH_IDENTIFIER, 92, 0, JSEXN_SYNTAXERR, "missing identifier in catch")
|
||||
MSG_DEF(JSMSG_PAREN_AFTER_CATCH, 93, 0, JSEXN_SYNTAXERR, "missing ) after catch")
|
||||
MSG_DEF(JSMSG_CURLY_BEFORE_CATCH, 94, 0, JSEXN_SYNTAXERR, "missing { before catch block")
|
||||
MSG_DEF(JSMSG_CURLY_AFTER_CATCH, 95, 0, JSEXN_SYNTAXERR, "missing } after catch block")
|
||||
MSG_DEF(JSMSG_CURLY_BEFORE_FINALLY, 96, 0, JSEXN_SYNTAXERR, "missing { before finally block")
|
||||
MSG_DEF(JSMSG_CURLY_AFTER_FINALLY, 97, 0, JSEXN_SYNTAXERR, "missing } after finally block")
|
||||
MSG_DEF(JSMSG_CATCH_OR_FINALLY, 98, 0, JSEXN_SYNTAXERR, "missing catch or finally after try")
|
||||
MSG_DEF(JSMSG_PAREN_BEFORE_WITH, 99, 0, JSEXN_SYNTAXERR, "missing ( before with-statement object")
|
||||
MSG_DEF(JSMSG_PAREN_AFTER_WITH, 100, 0, JSEXN_SYNTAXERR, "missing ) after with-statement object")
|
||||
MSG_DEF(JSMSG_CURLY_IN_COMPOUND, 101, 0, JSEXN_SYNTAXERR, "missing } in compound statement")
|
||||
MSG_DEF(JSMSG_NO_VARIABLE_NAME, 102, 0, JSEXN_SYNTAXERR, "missing variable name")
|
||||
MSG_DEF(JSMSG_COLON_IN_COND, 103, 0, JSEXN_SYNTAXERR, "missing : in conditional expression")
|
||||
MSG_DEF(JSMSG_PAREN_AFTER_ARGS, 104, 0, JSEXN_SYNTAXERR, "missing ) after argument list")
|
||||
MSG_DEF(JSMSG_BRACKET_AFTER_LIST, 105, 0, JSEXN_SYNTAXERR, "missing ] after element list")
|
||||
MSG_DEF(JSMSG_COLON_AFTER_ID, 106, 0, JSEXN_SYNTAXERR, "missing : after property id")
|
||||
MSG_DEF(JSMSG_CURLY_AFTER_LIST, 107, 0, JSEXN_SYNTAXERR, "missing } after property list")
|
||||
MSG_DEF(JSMSG_PAREN_IN_PAREN, 108, 0, JSEXN_SYNTAXERR, "missing ) in parenthetical")
|
||||
MSG_DEF(JSMSG_SEMI_BEFORE_STMNT, 109, 0, JSEXN_SYNTAXERR, "missing ; before statement")
|
||||
MSG_DEF(JSMSG_NO_RETURN_VALUE, 110, 0, JSEXN_NONE, "function does not always return a value")
|
||||
MSG_DEF(JSMSG_DUPLICATE_FORMAL, 111, 1, JSEXN_NONE, "duplicate formal argument {0}")
|
||||
MSG_DEF(JSMSG_EQUAL_AS_ASSIGN, 112, 1, JSEXN_NONE, "test for equality (==) mistyped as assignment (=)?{0}")
|
||||
MSG_DEF(JSMSG_BAD_IMPORT, 113, 0, JSEXN_SYNTAXERR, "invalid import expression")
|
||||
MSG_DEF(JSMSG_TOO_MANY_DEFAULTS, 114, 0, JSEXN_SYNTAXERR, "more than one switch default")
|
||||
MSG_DEF(JSMSG_TOO_MANY_CASES, 115, 0, JSEXN_INTERNALERR, "too many switch cases")
|
||||
MSG_DEF(JSMSG_BAD_SWITCH, 116, 0, JSEXN_SYNTAXERR, "invalid switch statement")
|
||||
MSG_DEF(JSMSG_BAD_FOR_LEFTSIDE, 117, 0, JSEXN_SYNTAXERR, "invalid for/in left-hand side")
|
||||
MSG_DEF(JSMSG_CATCH_AFTER_GENERAL, 118, 0, JSEXN_NONE, "catch clause after general catch")
|
||||
MSG_DEF(JSMSG_CATCH_WITHOUT_TRY, 119, 0, JSEXN_SYNTAXERR, "catch without try")
|
||||
MSG_DEF(JSMSG_FINALLY_WITHOUT_TRY, 120, 0, JSEXN_SYNTAXERR, "finally without try")
|
||||
MSG_DEF(JSMSG_LABEL_NOT_FOUND, 121, 0, JSEXN_SYNTAXERR, "label not found")
|
||||
MSG_DEF(JSMSG_TOUGH_BREAK, 122, 0, JSEXN_SYNTAXERR, "invalid break")
|
||||
MSG_DEF(JSMSG_BAD_CONTINUE, 123, 0, JSEXN_SYNTAXERR, "invalid continue")
|
||||
MSG_DEF(JSMSG_BAD_RETURN, 124, 0, JSEXN_SYNTAXERR, "invalid return")
|
||||
MSG_DEF(JSMSG_BAD_LABEL, 125, 0, JSEXN_SYNTAXERR, "invalid label")
|
||||
MSG_DEF(JSMSG_DUPLICATE_LABEL, 126, 0, JSEXN_SYNTAXERR, "duplicate label")
|
||||
MSG_DEF(JSMSG_VAR_HIDES_ARG, 127, 1, JSEXN_NONE, "variable {0} hides argument")
|
||||
MSG_DEF(JSMSG_BAD_VAR_INIT, 128, 0, JSEXN_SYNTAXERR, "invalid variable initialization")
|
||||
MSG_DEF(JSMSG_BAD_LEFTSIDE_OF_ASS, 129, 0, JSEXN_SYNTAXERR, "invalid assignment left-hand side")
|
||||
MSG_DEF(JSMSG_BAD_OPERAND, 130, 1, JSEXN_SYNTAXERR, "invalid {0} operand")
|
||||
MSG_DEF(JSMSG_BAD_PROP_ID, 131, 0, JSEXN_SYNTAXERR, "invalid property id")
|
||||
MSG_DEF(JSMSG_RESERVED_ID, 132, 1, JSEXN_SYNTAXERR, "{0} is a reserved identifier")
|
||||
MSG_DEF(JSMSG_SYNTAX_ERROR, 133, 0, JSEXN_SYNTAXERR, "syntax error")
|
||||
MSG_DEF(JSMSG_BAD_SHARP_VAR_DEF, 134, 0, JSEXN_SYNTAXERR, "invalid sharp variable definition")
|
||||
MSG_DEF(JSMSG_BAD_PROTOTYPE, 135, 1, JSEXN_ERR, "'prototype' property of {0} is not an object")
|
||||
MSG_DEF(JSMSG_MISSING_EXPONENT, 136, 0, JSEXN_SYNTAXERR, "missing exponent")
|
||||
MSG_DEF(JSMSG_OUT_OF_MEMORY, 137, 0, JSEXN_ERR, "out of memory")
|
||||
MSG_DEF(JSMSG_UNTERMINATED_STRING, 138, 0, JSEXN_SYNTAXERR, "unterminated string literal")
|
||||
MSG_DEF(JSMSG_NESTED_COMMENT, 139, 0, JSEXN_SYNTAXERR, "nested comment")
|
||||
MSG_DEF(JSMSG_UNTERMINATED_COMMENT, 140, 0, JSEXN_SYNTAXERR, "unterminated comment")
|
||||
MSG_DEF(JSMSG_UNTERMINATED_REGEXP, 141, 0, JSEXN_SYNTAXERR, "unterminated regular expression literal")
|
||||
MSG_DEF(JSMSG_BAD_REGEXP_FLAG, 142, 0, JSEXN_SYNTAXERR, "invalid flag after regular expression")
|
||||
MSG_DEF(JSMSG_SHARPVAR_TOO_BIG, 143, 0, JSEXN_SYNTAXERR, "overlarge sharp variable number")
|
||||
MSG_DEF(JSMSG_ILLEGAL_CHARACTER, 144, 0, JSEXN_SYNTAXERR, "illegal character")
|
||||
MSG_DEF(JSMSG_BAD_OCTAL, 145, 1, JSEXN_NONE, "{0} is not a legal ECMA-262 numeric constant")
|
||||
MSG_DEF(JSMSG_BAD_INDIRECT_CALL, 146, 1, JSEXN_CALLERR, "function {0} must be called directly, and not by way of a function of another name.")
|
||||
MSG_DEF(JSMSG_UNCAUGHT_EXCEPTION, 147, 1, JSEXN_NONE, "uncaught exception: {0}")
|
||||
79
mozilla/js/src/js3240.rc
Normal file
79
mozilla/js/src/js3240.rc
Normal file
@@ -0,0 +1,79 @@
|
||||
//Microsoft Developer Studio generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "winver.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 4,0,0,0
|
||||
PRODUCTVERSION 4,0,0,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x10004L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904e4"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Netscape Communications Corporation\0"
|
||||
VALUE "FileDescription", "Netscape 32-bit JavaScript Module\0"
|
||||
VALUE "FileVersion", "4.0\0"
|
||||
VALUE "InternalName", "JS3240\0"
|
||||
VALUE "LegalCopyright", "Copyright Netscape Communications. 1994-96\0"
|
||||
VALUE "LegalTrademarks", "Netscape, Mozilla\0"
|
||||
VALUE "OriginalFilename", "js3240.dll\0"
|
||||
VALUE "ProductName", "NETSCAPE\0"
|
||||
VALUE "ProductVersion", "4.0\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1252
|
||||
END
|
||||
END
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"#include ""winver.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
623
mozilla/js/src/jsOS240.def
Normal file
623
mozilla/js/src/jsOS240.def
Normal file
@@ -0,0 +1,623 @@
|
||||
; The contents of this file are subject to the Netscape Public License
|
||||
; Version 1.0 (the "NPL"); you may not use this file except in
|
||||
; compliance with the NPL. You may obtain a copy of the NPL at
|
||||
; http://www.mozilla.org/NPL/
|
||||
;
|
||||
; Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
; WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
; for the specific language governing rights and limitations under the
|
||||
; NPL.
|
||||
;
|
||||
; The Initial Developer of this code under the NPL is Netscape
|
||||
; Communications Corporation. Portions created by Netscape are
|
||||
; Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
; Reserved.
|
||||
|
||||
LIBRARY JS3240 INITINSTANCE TERMINSTANCE
|
||||
PROTMODE
|
||||
|
||||
DESCRIPTION 'Netscape OS/2 JavaScript Library'
|
||||
|
||||
|
||||
CODE LOADONCALL MOVEABLE DISCARDABLE
|
||||
DATA PRELOAD MOVEABLE MULTIPLE NONSHARED
|
||||
|
||||
|
||||
EXPORTS
|
||||
;====================== win16 exports these at least... ===========
|
||||
; JS_Init = JS_Init @2
|
||||
; JS_Finish = JS_Finish @3
|
||||
; JS_GetNaNValue
|
||||
; JS_GetNegativeInfinityValue
|
||||
; JS_GetPositiveInfinityValue
|
||||
; JS_GetEmptyStringValue
|
||||
; JS_ConvertValue
|
||||
; JS_ValueToObject
|
||||
; JS_ValueToFunction
|
||||
; JS_ValueToString
|
||||
; JS_ValueToNumber
|
||||
; JS_ValueToBoolean
|
||||
; JS_TypeOfValue
|
||||
; JS_GetTypeName
|
||||
; JS_Lock
|
||||
; JS_Unlock
|
||||
; JS_NewContext
|
||||
; JS_DestroyContext
|
||||
; JS_ContextIterator
|
||||
; JS_GetGlobalObject
|
||||
; JS_SetGlobalObject
|
||||
; JS_InitStandardClasses
|
||||
;; JS_GetStaticLink
|
||||
; JS_malloc
|
||||
; JS_realloc
|
||||
; JS_free
|
||||
; JS_strdup
|
||||
; JS_NewDouble
|
||||
; JS_NewDoubleValue
|
||||
; JS_AddRoot
|
||||
; JS_RemoveRoot
|
||||
; JS_LockGCThing
|
||||
; JS_UnlockGCThing
|
||||
; JS_GC
|
||||
; JS_PropertyStub
|
||||
; JS_EnumerateStub
|
||||
; JS_ResolveStub
|
||||
; JS_ConvertStub
|
||||
; JS_FinalizeStub
|
||||
; JS_InitClass
|
||||
; JS_GetClass
|
||||
; JS_InstanceOf
|
||||
; JS_GetPrivate
|
||||
; JS_SetPrivate
|
||||
; JS_GetInstancePrivate
|
||||
; JS_GetPrototype
|
||||
; JS_GetParent
|
||||
; JS_SetParent
|
||||
; JS_GetConstructor
|
||||
; JS_NewObject
|
||||
; JS_DefineObject
|
||||
; JS_DefineConstDoubles
|
||||
; JS_DefineProperties
|
||||
; JS_DefineProperty
|
||||
; JS_DefinePropertyWithTinyId
|
||||
; JS_AliasProperty
|
||||
; JS_LookupProperty
|
||||
; JS_GetProperty
|
||||
; JS_SetProperty
|
||||
; JS_DeleteProperty
|
||||
; JS_NewArrayObject
|
||||
; JS_DefineElement
|
||||
; JS_AliasElement
|
||||
; JS_LookupElement
|
||||
; JS_GetElement
|
||||
; JS_SetElement
|
||||
; JS_DeleteElement
|
||||
; JS_ClearScope
|
||||
; JS_NewFunction
|
||||
; JS_GetFunctionObject
|
||||
; JS_GetFunctionName
|
||||
; JS_DefineFunctions
|
||||
; JS_DefineFunction
|
||||
; JS_CompileScript
|
||||
; JS_DestroyScript
|
||||
; JS_CompileFunction
|
||||
; JS_DecompileScript
|
||||
; JS_DecompileFunction
|
||||
; JS_DecompileFunctionBody
|
||||
; JS_ExecuteScript
|
||||
; JS_EvaluateScript
|
||||
; JS_CallFunction
|
||||
; JS_CallFunctionName
|
||||
; JS_CallFunctionValue
|
||||
; JS_SetBranchCallback
|
||||
; JS_IsRunning
|
||||
; JS_NewString
|
||||
; JS_NewStringCopyN
|
||||
; JS_NewStringCopyZ
|
||||
; JS_InternString
|
||||
; JS_GetStringBytes
|
||||
; JS_GetStringLength
|
||||
; JS_CompareStrings
|
||||
; JS_ReportError
|
||||
; JS_ReportOutOfMemory
|
||||
; JS_SetErrorReporter
|
||||
; JS_NewRegExpObject
|
||||
; JS_SetRegExpInput
|
||||
; JS_ClearRegExpStatics
|
||||
;=================================================
|
||||
|
||||
|
||||
;00001:jsstr (OFFSET:0x00002e17, SIZE:0x0000ae17):
|
||||
; - Public Definitions:
|
||||
; js_EmptySubString
|
||||
; js_CompareStrings
|
||||
; js_HashString
|
||||
; js_ValueToString
|
||||
; js_StringToObject
|
||||
; js_FinalizeString
|
||||
; js_NewStringCopyZ
|
||||
; js_NewString
|
||||
; js_InitStringClass
|
||||
; js_NewStringCopyN
|
||||
; js_BoyerMooreHorspool
|
||||
;
|
||||
;
|
||||
;00002:jsscript (OFFSET:0x0000dc2e, SIZE:0x00003abb):
|
||||
; - Public Definitions:
|
||||
; js_LineNumberToPC
|
||||
; js_PCToLineNumber
|
||||
; js_GetSrcNote
|
||||
; js_DestroyScript
|
||||
; js_NewScript
|
||||
;
|
||||
;
|
||||
;00003:jsscope (OFFSET:0x000116e9, SIZE:0x00004f82):
|
||||
; - Public Definitions:
|
||||
; js_hash_scope_ops
|
||||
; js_list_scope_ops
|
||||
; js_DestroyProperty
|
||||
; js_NewProperty
|
||||
; js_IdToValue
|
||||
; js_HashValue
|
||||
; js_DestroyScope
|
||||
; js_MutateScope
|
||||
; js_DropScope
|
||||
; js_HoldScope
|
||||
; js_NewScope
|
||||
; js_GetMutableScope
|
||||
; js_HoldProperty
|
||||
; js_DropProperty
|
||||
;
|
||||
;
|
||||
;00004:jsscan (OFFSET:0x0001666b, SIZE:0x00008890):
|
||||
; - Public Definitions:
|
||||
; js_MatchToken
|
||||
; js_FlushNewlines
|
||||
; js_PeekTokenSameLine
|
||||
; js_UngetToken
|
||||
; js_GetToken
|
||||
; js_PeekToken
|
||||
; js_ReportCompileError
|
||||
js_CloseTokenStream
|
||||
js_NewBufferTokenStream
|
||||
; js_NewTokenStream
|
||||
; js_InitScanner
|
||||
;
|
||||
;
|
||||
;00005:jsregexp (OFFSET:0x0001eefb, SIZE:0x0000eee4):
|
||||
; - Public Definitions:
|
||||
; js_RegExpClass
|
||||
; reopsize
|
||||
; js_NewRegExpObject
|
||||
; js_InitRegExpClass
|
||||
; js_FreeRegExpStatics
|
||||
; js_InitRegExpStatics
|
||||
; js_ExecuteRegExp
|
||||
; js_NewRegExpOpt
|
||||
; js_DestroyRegExp
|
||||
; js_NewRegExp
|
||||
;
|
||||
;
|
||||
;00006:jsparse (OFFSET:0x0002dddf, SIZE:0x00010b71):
|
||||
; - Public Definitions:
|
||||
; js_ParseFunctionBody
|
||||
js_Parse
|
||||
;
|
||||
;
|
||||
;00007:jsopcode (OFFSET:0x0003e950, SIZE:0x0000d362):
|
||||
; - Public Definitions:
|
||||
; js_EscapeMap
|
||||
; js_NumCodeSpecs
|
||||
; js_CodeSpec
|
||||
; js_incop_str
|
||||
; js_true_str
|
||||
; js_false_str
|
||||
; js_this_str
|
||||
; js_null_str
|
||||
; js_void_str
|
||||
; js_typeof_str
|
||||
; js_delete_str
|
||||
; js_new_str
|
||||
; js_ValueToSource
|
||||
; js_DecompileScript
|
||||
; js_DecompileCode
|
||||
; js_DecompileFunction
|
||||
; js_puts
|
||||
; js_printf
|
||||
; js_GetPrinterOutput
|
||||
; js_DestroyPrinter
|
||||
; js_NewPrinter
|
||||
; js_EscapeString
|
||||
; js_Disassemble1
|
||||
; js_Disassemble
|
||||
;
|
||||
;00008:jsobj (OFFSET:0x0004bcb2, SIZE:0x000090a4):
|
||||
; - Public Definitions:
|
||||
; js_WithClass
|
||||
; js_ObjectClass
|
||||
; js_TryValueOf
|
||||
; js_ValueToNonNullObject
|
||||
; js_TryMethod
|
||||
; js_ObjectToString
|
||||
; js_SetClassPrototype
|
||||
; js_DeleteProperty2
|
||||
; js_DeleteProperty
|
||||
; js_SetProperty
|
||||
; js_GetProperty
|
||||
; js_FindVariableScope
|
||||
; js_FindVariable
|
||||
; js_FindProperty
|
||||
; js_LookupProperty
|
||||
; js_DefineProperty
|
||||
; js_FreeSlot
|
||||
; js_AllocSlot
|
||||
; js_FinalizeObject
|
||||
; js_GetClassPrototype
|
||||
; js_NewObject
|
||||
; js_InitObjectClass
|
||||
; js_ValueToObject
|
||||
; js_obj_toString
|
||||
; js_SetSlot
|
||||
; js_GetSlot
|
||||
;
|
||||
;
|
||||
;00009:jsnum (OFFSET:0x00054d56, SIZE:0x00004f29):
|
||||
; - Public Definitions:
|
||||
; js_ValueToInt32
|
||||
; js_NumberToObject
|
||||
; js_FinalizeDouble
|
||||
; js_InitNumberClass
|
||||
; js_NumberToString
|
||||
; js_NewDoubleValue
|
||||
; js_NewDouble
|
||||
; js_ValueToNumber
|
||||
;
|
||||
;
|
||||
;00010:jsmath (OFFSET:0x00059c7f, SIZE:0x000054b6):
|
||||
; - Public Definitions:
|
||||
; js_InitMathClass
|
||||
;
|
||||
;
|
||||
;00011:jsjava (OFFSET:0x0005f135, SIZE:0x00022aad):
|
||||
; - Public Definitions:
|
||||
; js_Hooks
|
||||
; MojaSrcLog
|
||||
; finalizeTask
|
||||
JSJ_FindCurrentJSContext
|
||||
; JSJ_GetPrincipals
|
||||
JSJ_IsSafeMethod
|
||||
JSJ_InitContext
|
||||
JSJ_Init
|
||||
js_JSErrorToJException
|
||||
js_JavaErrorReporter
|
||||
js_RemoveReflection
|
||||
js_ReflectJObjectToJSObject
|
||||
js_convertJObjectToJSValue
|
||||
js_convertJSValueToJObject
|
||||
js_ReflectJSObjectToJObject
|
||||
; js_ReflectJClassToJSObject
|
||||
JSJ_ExitJS
|
||||
JSJ_EnterJS
|
||||
JSJ_CurrentContext
|
||||
JSJ_IsEnabled
|
||||
;added in GA code - DSR70297
|
||||
JSJ_Finish
|
||||
JSJ_IsCalledFromJava
|
||||
js_GetJSPrincipalsFromJavaCaller
|
||||
|
||||
;
|
||||
;
|
||||
;00012:jsinterp (OFFSET:0x00081be2, SIZE:0x00012274):
|
||||
; - Public Definitions:
|
||||
; js_Call
|
||||
; js_Interpret
|
||||
; js_SetLocalVariable
|
||||
; js_GetLocalVariable
|
||||
; js_SetArgument
|
||||
; js_GetArgument
|
||||
; js_FlushPropertyCacheByProp
|
||||
; js_FlushPropertyCache
|
||||
;
|
||||
;
|
||||
;00013:jsgc (OFFSET:0x00093e56, SIZE:0x00004f8d):
|
||||
; - Public Definitions:
|
||||
; js_ForceGC
|
||||
; js_UnlockGCThing
|
||||
; js_LockGCThing
|
||||
; js_GC
|
||||
; js_AllocGCThing
|
||||
; js_RemoveRoot
|
||||
; js_AddRoot
|
||||
; js_FinishGC
|
||||
; js_InitGC
|
||||
;
|
||||
;
|
||||
;00014:jsfun (OFFSET:0x00098de3, SIZE:0x0000977c):
|
||||
; - Public Definitions:
|
||||
; js_FunctionClass
|
||||
; js_ClosureClass
|
||||
; js_CallClass
|
||||
; js_DefineFunction
|
||||
; js_NewFunction
|
||||
; js_InitCallAndClosureClasses
|
||||
; js_InitFunctionClass
|
||||
; js_ValueToFunction
|
||||
; js_SetCallVariable
|
||||
; js_GetCallVariable
|
||||
; js_PutCallObject
|
||||
; js_GetCallObject
|
||||
;
|
||||
;
|
||||
;00015:jsemit (OFFSET:0x000a255f, SIZE:0x000077be):
|
||||
; - Public Definitions:
|
||||
; js_SrcNoteName
|
||||
; js_SrcNoteArity
|
||||
js_FinishTakingSrcNotes
|
||||
; js_MoveSrcNotes
|
||||
; js_GetSrcNoteOffset
|
||||
; js_BumpSrcNoteDelta
|
||||
; js_NewSrcNote3
|
||||
; js_NewSrcNote2
|
||||
; js_PopStatement
|
||||
; js_EmitContinue
|
||||
; js_EmitBreak
|
||||
; js_SetSrcNoteOffset
|
||||
; js_NewSrcNote
|
||||
; js_PushStatement
|
||||
; js_MoveCode
|
||||
; js_SetJumpOffset
|
||||
; js_Emit3
|
||||
; js_Emit2
|
||||
; js_Emit1
|
||||
; js_UpdateDepth
|
||||
; js_SrcNoteLength
|
||||
; js_CancelLastOpcode
|
||||
js_InitCodeGenerator
|
||||
;
|
||||
;
|
||||
;00016:jsdbgapi (OFFSET:0x000a9d1d, SIZE:0x000057db):
|
||||
; - Public Definitions:
|
||||
; js_watchpoint_list
|
||||
; js_trap_list
|
||||
; JS_SetAnnotationInFrame
|
||||
; JS_GetAnnotationFromFrame
|
||||
; JS_GetJSPrincipalArrayFromFrame
|
||||
; JS_NextJSFrame
|
||||
; JS_InitJSFrameIterator
|
||||
JS_LineNumberToPC
|
||||
JS_PCToLineNumber
|
||||
JS_ClearAllWatchPoints
|
||||
JS_ClearWatchPoint
|
||||
JS_SetWatchPoint
|
||||
JS_HandleTrap
|
||||
JS_ClearAllTraps
|
||||
JS_ClearScriptTraps
|
||||
JS_ClearTrap
|
||||
JS_GetTrapOpcode
|
||||
JS_SetTrap
|
||||
;DSR070297 - added in GA code
|
||||
JS_FrameIterator
|
||||
JS_GetFrameAnnotation
|
||||
JS_GetFramePrincipalArray
|
||||
JS_GetFrameScript
|
||||
JS_GetScriptFilename
|
||||
JS_SetFrameAnnotation
|
||||
JS_GetFramePC
|
||||
JS_GetFunctionScript
|
||||
|
||||
;
|
||||
;
|
||||
;00017:jsdate (OFFSET:0x000af4f8, SIZE:0x00009a8e):
|
||||
; - Public Definitions:
|
||||
js_DateGetSeconds
|
||||
js_DateGetMinutes
|
||||
js_DateGetHours
|
||||
js_DateGetDate
|
||||
js_DateGetMonth
|
||||
js_DateGetYear
|
||||
js_NewDateObject
|
||||
; js_InitDateClass
|
||||
;
|
||||
;
|
||||
;00018:jscntxt (OFFSET:0x000b8f86, SIZE:0x00003732):
|
||||
; - Public Definitions:
|
||||
; js_InterpreterHooks
|
||||
; js_ReportIsNotDefined
|
||||
; js_ReportErrorAgain
|
||||
; js_ReportErrorVA
|
||||
; js_ContextIterator
|
||||
; js_DestroyContext
|
||||
; js_NewContext
|
||||
; js_SetInterpreterHooks
|
||||
;
|
||||
;
|
||||
;00019:jsbool (OFFSET:0x000bc6b8, SIZE:0x00003375):
|
||||
; - Public Definitions:
|
||||
; js_BooleanToString
|
||||
; js_BooleanToObject
|
||||
; js_InitBooleanClass
|
||||
; js_ValueToBoolean
|
||||
;
|
||||
;
|
||||
;00020:jsatom (OFFSET:0x000bfa2d, SIZE:0x000058d0):
|
||||
; - Public Definitions:
|
||||
; js_valueOf_str
|
||||
; js_toString_str
|
||||
; js_length_str
|
||||
; js_eval_str
|
||||
; js_constructor_str
|
||||
; js_class_prototype_str
|
||||
; js_assign_str
|
||||
; js_anonymous_str
|
||||
; js_Object_str
|
||||
; js_Array_str
|
||||
; js_type_str
|
||||
; js_DropUnmappedAtoms
|
||||
js_FreeAtomMap
|
||||
js_InitAtomMap
|
||||
; js_GetAtom
|
||||
; js_DropAtom
|
||||
; js_IndexAtom
|
||||
; js_ValueToStringAtom
|
||||
; js_AtomizeString
|
||||
; js_AtomizeDouble
|
||||
; js_AtomizeInt
|
||||
; js_AtomizeBoolean
|
||||
; js_AtomizeObject
|
||||
; js_HoldAtom
|
||||
; js_MarkAtomState
|
||||
; js_FreeAtomState
|
||||
; js_Atomize
|
||||
; js_InitAtomState
|
||||
;
|
||||
;
|
||||
;00021:jsarray (OFFSET:0x000c52fd, SIZE:0x00007c86):
|
||||
; - Public Definitions:
|
||||
; js_ArrayClass
|
||||
; js_SetArrayLength
|
||||
; js_GetArrayLength
|
||||
; js_InitArrayClass
|
||||
; js_NewArrayObject
|
||||
; PR_qsort
|
||||
;
|
||||
;
|
||||
;00022:jsapi (OFFSET:0x000ccf83, SIZE:0x0000de8c):
|
||||
; - Public Definitions:
|
||||
JS_ClearRegExpStatics
|
||||
JS_SetRegExpInput
|
||||
JS_NewRegExpObject
|
||||
JS_SetErrorReporter
|
||||
JS_CompareStrings
|
||||
JS_GetStringLength
|
||||
JS_GetStringBytes
|
||||
JS_InternString
|
||||
JS_NewStringCopyZ
|
||||
JS_NewStringCopyN
|
||||
JS_NewString
|
||||
JS_IsRunning
|
||||
JS_SetBranchCallback
|
||||
JS_CallFunctionValue
|
||||
JS_CallFunctionName
|
||||
JS_CallFunction
|
||||
JS_EvaluateScriptForPrincipals
|
||||
JS_EvaluateScript
|
||||
JS_ExecuteScript
|
||||
JS_DecompileFunctionBody
|
||||
JS_DecompileFunction
|
||||
JS_DecompileScript
|
||||
JS_CompileFunctionForPrincipals
|
||||
JS_CompileFunction
|
||||
JS_DestroyScript
|
||||
JS_CompileScriptForPrincipals
|
||||
JS_CompileScript
|
||||
JS_DefineFunction
|
||||
JS_GetFunctionName
|
||||
JS_GetFunctionObject
|
||||
JS_NewFunction
|
||||
JS_ClearScope
|
||||
JS_DeleteElement
|
||||
JS_SetElement
|
||||
JS_GetElement
|
||||
JS_LookupElement
|
||||
JS_AliasElement
|
||||
JS_DefineElement
|
||||
JS_SetArrayLength
|
||||
JS_GetArrayLength
|
||||
JS_NewArrayObject
|
||||
JS_DeleteProperty
|
||||
JS_SetProperty
|
||||
JS_GetProperty
|
||||
JS_LookupProperty
|
||||
JS_AliasProperty
|
||||
JS_DefinePropertyWithTinyId
|
||||
JS_DefineProperty
|
||||
JS_DefineConstDoubles
|
||||
JS_DefineObject
|
||||
JS_NewObject
|
||||
JS_GetConstructor
|
||||
JS_SetParent
|
||||
JS_GetParent
|
||||
JS_SetPrototype
|
||||
JS_GetPrototype
|
||||
JS_GetInstancePrivate
|
||||
JS_SetPrivate
|
||||
JS_GetPrivate
|
||||
JS_InstanceOf
|
||||
JS_GetClass
|
||||
JS_DefineFunctions
|
||||
JS_DefineProperties
|
||||
JS_InitClass
|
||||
JS_FinalizeStub
|
||||
JS_ConvertStub
|
||||
JS_ResolveStub
|
||||
JS_EnumerateStub
|
||||
JS_PropertyStub
|
||||
JS_GC
|
||||
JS_UnlockGCThing
|
||||
JS_LockGCThing
|
||||
JS_RemoveRoot
|
||||
JS_AddRoot
|
||||
JS_NewDoubleValue
|
||||
JS_NewDouble
|
||||
JS_strdup
|
||||
JS_free
|
||||
JS_realloc
|
||||
JS_ReportOutOfMemory
|
||||
JS_malloc
|
||||
JS_GetScopeChain
|
||||
JS_InitStandardClasses
|
||||
JS_SetGlobalObject
|
||||
JS_GetGlobalObject
|
||||
JS_SetVersion
|
||||
JS_GetVersion
|
||||
JS_ContextIterator
|
||||
JS_GetTaskState
|
||||
JS_DestroyContext
|
||||
JS_NewContext
|
||||
JS_Unlock
|
||||
JS_Lock
|
||||
JS_Finish
|
||||
JS_Init
|
||||
JS_GetTypeName
|
||||
JS_TypeOfValue
|
||||
JS_ValueToBoolean
|
||||
JS_ValueToInt32
|
||||
JS_ValueToNumber
|
||||
JS_ValueToString
|
||||
JS_ValueToFunction
|
||||
JS_ValueToObject
|
||||
JS_ReportError
|
||||
JS_ConvertValue
|
||||
JS_GetEmptyStringValue
|
||||
JS_GetPositiveInfinityValue
|
||||
JS_GetNegativeInfinityValue
|
||||
JS_GetNaNValue
|
||||
;DSR062897 - added for GA code
|
||||
JS_MaybeGC
|
||||
JS_GetScriptPrincipals
|
||||
JS_IsAssigning
|
||||
JS_SetCharSetInfo
|
||||
;
|
||||
;
|
||||
;00023:prmjtime (OFFSET:0x000dae0f, SIZE:0x00008986):
|
||||
; - Public Definitions:
|
||||
PRMJ_FormatTimeUSEnglish
|
||||
PRMJ_gmtime
|
||||
PRMJ_FormatTime
|
||||
PRMJ_mktime
|
||||
PRMJ_ComputeTime
|
||||
PRMJ_localtime
|
||||
PRMJ_ExplodeTime
|
||||
PRMJ_ToLocal
|
||||
PRMJ_ToGMT
|
||||
PRMJ_NowLocal
|
||||
PRMJ_DSTOffset
|
||||
PRMJ_NowS
|
||||
PRMJ_NowMS
|
||||
PRMJ_Now
|
||||
PRMJ_ToExtendedTime
|
||||
PRMJ_ToBaseTime
|
||||
PRMJ_setDST
|
||||
PRMJ_LocalGMTDifference
|
||||
|
||||
|
||||
42
mozilla/js/src/jsaddr.c
Normal file
42
mozilla/js/src/jsaddr.c
Normal file
@@ -0,0 +1,42 @@
|
||||
/* -*- Mode: C; tab-width: 8 -*-
|
||||
* Copyright © 1996 Netscape Communications Corporation, All Rights Reserved.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jsinterp.h"
|
||||
|
||||
/* These functions are needed to get the addresses of certain functions
|
||||
* in the JS module. On WIN32 especially, these symbols have a different
|
||||
* address from the actual address of these functions in the JS module.
|
||||
* This is because on WIN32, import function address fixups are done only
|
||||
* at load time and function calls are made by indirection - that is by
|
||||
* using a couple extra instructions to lookup the actual function address
|
||||
* in the importing module's import address table.
|
||||
*/
|
||||
|
||||
JS_EXPORT_API(JSPropertyOp)
|
||||
js_GetArgumentAddress()
|
||||
{
|
||||
return ((void *)js_GetArgument);
|
||||
}
|
||||
|
||||
JS_EXPORT_API(JSPropertyOp)
|
||||
js_SetArgumentAddress()
|
||||
{
|
||||
return ((void *)js_SetArgument);
|
||||
}
|
||||
|
||||
JS_EXPORT_API(JSPropertyOp)
|
||||
js_GetLocalVariableAddress()
|
||||
{
|
||||
return ((void *)js_GetLocalVariable);
|
||||
}
|
||||
|
||||
JS_EXPORT_API(JSPropertyOp)
|
||||
js_SetLocalVariableAddress()
|
||||
{
|
||||
return ((void *)js_SetLocalVariable);
|
||||
}
|
||||
20
mozilla/js/src/jsaddr.h
Normal file
20
mozilla/js/src/jsaddr.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/* -*- Mode: C; tab-width: 8 -*-
|
||||
* Copyright © 1996 Netscape Communications Corporation, All Rights Reserved.
|
||||
*/
|
||||
|
||||
#ifndef jsaddr_h___
|
||||
#define jsaddr_h___
|
||||
|
||||
JS_EXTERN_API(JSPropertyOp)
|
||||
js_GetArgumentAddress();
|
||||
|
||||
JS_EXTERN_API(JSPropertyOp)
|
||||
js_SetArgumentAddress();
|
||||
|
||||
JS_EXTERN_API(JSPropertyOp)
|
||||
js_GetLocalVariableAddress();
|
||||
|
||||
JS_EXTERN_API(JSPropertyOp)
|
||||
js_SetLocalVariableAddress();
|
||||
|
||||
#endif /* jsaddr_h___ */
|
||||
2864
mozilla/js/src/jsapi.c
Normal file
2864
mozilla/js/src/jsapi.c
Normal file
File diff suppressed because it is too large
Load Diff
1087
mozilla/js/src/jsapi.h
Normal file
1087
mozilla/js/src/jsapi.h
Normal file
File diff suppressed because it is too large
Load Diff
336
mozilla/js/src/jsarena.c
Normal file
336
mozilla/js/src/jsarena.c
Normal file
@@ -0,0 +1,336 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Lifetime-based fast allocation, inspired by much prior art, including
|
||||
* "Fast Allocation and Deallocation of Memory Based on Object Lifetimes"
|
||||
* David R. Hanson, Software -- Practice and Experience, Vol. 20(1).
|
||||
*/
|
||||
#include "jsstddef.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "jstypes.h"
|
||||
#include "jsbit.h"
|
||||
#include "jsarena.h" /* Added by JSIFY */
|
||||
#include "jsutil.h" /* Added by JSIFY */
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
extern js_CompareAndSwap(jsword *, jsword, jsword);
|
||||
#endif
|
||||
|
||||
static JSArena *arena_freelist;
|
||||
|
||||
#ifdef JS_ARENAMETER
|
||||
static JSArenaStats *arena_stats_list;
|
||||
|
||||
#define COUNT(pool,what) (pool)->stats.what++
|
||||
#else
|
||||
#define COUNT(pool,what) /* nothing */
|
||||
#endif
|
||||
|
||||
#define JS_ARENA_DEFAULT_ALIGN sizeof(double)
|
||||
|
||||
JS_EXPORT_API(void)
|
||||
JS_InitArenaPool(JSArenaPool *pool, const char *name, JSUint32 size, JSUint32 align)
|
||||
{
|
||||
if (align == 0)
|
||||
align = JS_ARENA_DEFAULT_ALIGN;
|
||||
pool->mask = JS_BITMASK(JS_CeilingLog2(align));
|
||||
pool->first.next = NULL;
|
||||
pool->first.base = pool->first.avail = pool->first.limit =
|
||||
(jsuword)JS_ARENA_ALIGN(pool, &pool->first + 1);
|
||||
pool->current = &pool->first;
|
||||
pool->arenasize = size;
|
||||
#ifdef JS_ARENAMETER
|
||||
memset(&pool->stats, 0, sizeof pool->stats);
|
||||
pool->stats.name = strdup(name);
|
||||
pool->stats.next = arena_stats_list;
|
||||
arena_stats_list = &pool->stats;
|
||||
#endif
|
||||
}
|
||||
|
||||
JS_EXPORT_API(void *)
|
||||
JS_ArenaAllocate(JSArenaPool *pool, JSUint32 nb)
|
||||
{
|
||||
JSArena **ap, *a, *b;
|
||||
#ifdef JS_THREADSAFE
|
||||
JSArena *c;
|
||||
#endif
|
||||
JSUint32 sz;
|
||||
void *p;
|
||||
|
||||
JS_ASSERT((nb & pool->mask) == 0);
|
||||
#if defined(XP_PC) && !defined(_WIN32)
|
||||
if (nb >= 60000U)
|
||||
return 0;
|
||||
#endif /* WIN16 */
|
||||
ap = &arena_freelist;
|
||||
for (a = pool->current; a->avail + nb > a->limit; pool->current = a) {
|
||||
if (a->next) { /* move to next arena */
|
||||
a = a->next;
|
||||
continue;
|
||||
}
|
||||
while ((b = *ap) != NULL) { /* reclaim a free arena */
|
||||
if (b->limit - b->base == pool->arenasize) {
|
||||
#ifdef JS_THREADSAFE
|
||||
do {
|
||||
b = *ap;
|
||||
c = b->next;
|
||||
} while (!js_CompareAndSwap((jsword *)ap,(jsword)b,(jsword)c));
|
||||
#else
|
||||
*ap = b->next;
|
||||
#endif
|
||||
b->next = NULL;
|
||||
a = a->next = b;
|
||||
COUNT(pool, nreclaims);
|
||||
goto claim;
|
||||
}
|
||||
ap = &b->next;
|
||||
}
|
||||
sz = JS_MAX(pool->arenasize, nb); /* allocate a new arena */
|
||||
sz += sizeof *a + pool->mask; /* header and alignment slop */
|
||||
b = malloc(sz);
|
||||
if (!b)
|
||||
return 0;
|
||||
a = a->next = b;
|
||||
a->next = NULL;
|
||||
a->limit = (jsuword)a + sz;
|
||||
JS_COUNT_ARENA(pool,++);
|
||||
COUNT(pool, nmallocs);
|
||||
claim:
|
||||
a->base = a->avail = (jsuword)JS_ARENA_ALIGN(pool, a + 1);
|
||||
}
|
||||
p = (void *)a->avail;
|
||||
a->avail += nb;
|
||||
return p;
|
||||
}
|
||||
|
||||
JS_EXPORT_API(void *)
|
||||
JS_ArenaGrow(JSArenaPool *pool, void *p, JSUint32 size, JSUint32 incr)
|
||||
{
|
||||
void *newp;
|
||||
|
||||
JS_ARENA_ALLOCATE(newp, pool, size + incr);
|
||||
memcpy(newp, p, size);
|
||||
return newp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free tail arenas linked after head, which may not be the true list head.
|
||||
* Reset pool->current to point to head in case it pointed at a tail arena.
|
||||
*/
|
||||
static void
|
||||
FreeArenaList(JSArenaPool *pool, JSArena *head, JSBool reallyFree)
|
||||
{
|
||||
JSArena **ap, *a;
|
||||
#ifdef JS_THREADSAFE
|
||||
JSArena *b;
|
||||
#endif
|
||||
|
||||
ap = &head->next;
|
||||
a = *ap;
|
||||
if (!a)
|
||||
return;
|
||||
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
JS_ASSERT(a->base <= a->avail && a->avail <= a->limit);
|
||||
a->avail = a->base;
|
||||
JS_CLEAR_UNUSED(a);
|
||||
} while ((a = a->next) != NULL);
|
||||
a = *ap;
|
||||
#endif
|
||||
|
||||
if (reallyFree) {
|
||||
do {
|
||||
*ap = a->next;
|
||||
JS_CLEAR_ARENA(a);
|
||||
JS_COUNT_ARENA(pool,--);
|
||||
free(a);
|
||||
} while ((a = *ap) != NULL);
|
||||
} else {
|
||||
/* Insert the whole arena chain at the front of the freelist. */
|
||||
do {
|
||||
ap = &(*ap)->next;
|
||||
} while (*ap);
|
||||
#ifdef JS_THREADSAFE
|
||||
do {
|
||||
*ap = b = arena_freelist;
|
||||
} while (!js_CompareAndSwap((jsword*)&arena_freelist,(jsword)b,(jsword)a));
|
||||
#else
|
||||
*ap = arena_freelist;
|
||||
arena_freelist = a;
|
||||
#endif
|
||||
head->next = NULL;
|
||||
}
|
||||
|
||||
pool->current = head;
|
||||
}
|
||||
|
||||
JS_EXPORT_API(void)
|
||||
JS_ArenaRelease(JSArenaPool *pool, char *mark)
|
||||
{
|
||||
JSArena *a;
|
||||
|
||||
for (a = pool->first.next; a; a = a->next) {
|
||||
if (JS_UPTRDIFF(mark, a) < JS_UPTRDIFF(a->avail, a)) {
|
||||
a->avail = (jsuword)JS_ARENA_ALIGN(pool, mark);
|
||||
FreeArenaList(pool, a, JS_TRUE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JS_EXPORT_API(void)
|
||||
JS_FreeArenaPool(JSArenaPool *pool)
|
||||
{
|
||||
FreeArenaList(pool, &pool->first, JS_FALSE);
|
||||
COUNT(pool, ndeallocs);
|
||||
}
|
||||
|
||||
JS_EXPORT_API(void)
|
||||
JS_FinishArenaPool(JSArenaPool *pool)
|
||||
{
|
||||
FreeArenaList(pool, &pool->first, JS_TRUE);
|
||||
#ifdef JS_ARENAMETER
|
||||
{
|
||||
JSArenaStats *stats, **statsp;
|
||||
|
||||
if (pool->stats.name)
|
||||
free(pool->stats.name);
|
||||
for (statsp = &arena_stats_list; (stats = *statsp) != 0;
|
||||
statsp = &stats->next) {
|
||||
if (stats == &pool->stats) {
|
||||
*statsp = stats->next;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
JS_EXPORT_API(void)
|
||||
JS_CompactArenaPool(JSArenaPool *pool)
|
||||
{
|
||||
#if 0 /* XP_MAC */
|
||||
JSArena *a = pool->first.next;
|
||||
|
||||
while (a) {
|
||||
reallocSmaller(a, a->avail - (jsuword)a);
|
||||
a->limit = a->avail;
|
||||
a = a->next;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
JS_EXPORT_API(void)
|
||||
JS_ArenaFinish()
|
||||
{
|
||||
JSArena *a, *next;
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
while (arena_freelist) {
|
||||
a = arena_freelist;
|
||||
next = a->next;
|
||||
if (js_CompareAndSwap((jsword*)&arena_freelist,(jsword)a,(jsword)next))
|
||||
free(a);
|
||||
}
|
||||
#else
|
||||
for (a = arena_freelist; a; a = next) {
|
||||
next = a->next;
|
||||
free(a);
|
||||
}
|
||||
arena_freelist = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef JS_ARENAMETER
|
||||
JS_EXPORT_API(void)
|
||||
JS_ArenaCountAllocation(JSArenaPool *pool, JSUint32 nb)
|
||||
{
|
||||
pool->stats.nallocs++;
|
||||
pool->stats.nbytes += nb;
|
||||
if (nb > pool->stats.maxalloc)
|
||||
pool->stats.maxalloc = nb;
|
||||
pool->stats.variance += nb * nb;
|
||||
}
|
||||
|
||||
JS_EXPORT_API(void)
|
||||
JS_ArenaCountInplaceGrowth(JSArenaPool *pool, JSUint32 size, JSUint32 incr)
|
||||
{
|
||||
pool->stats.ninplace++;
|
||||
}
|
||||
|
||||
JS_EXPORT_API(void)
|
||||
JS_ArenaCountGrowth(JSArenaPool *pool, JSUint32 size, JSUint32 incr)
|
||||
{
|
||||
pool->stats.ngrows++;
|
||||
pool->stats.nbytes += incr;
|
||||
pool->stats.variance -= size * size;
|
||||
size += incr;
|
||||
if (size > pool->stats.maxalloc)
|
||||
pool->stats.maxalloc = size;
|
||||
pool->stats.variance += size * size;
|
||||
}
|
||||
|
||||
JS_EXPORT_API(void)
|
||||
JS_ArenaCountRelease(JSArenaPool *pool, char *mark)
|
||||
{
|
||||
pool->stats.nreleases++;
|
||||
}
|
||||
|
||||
JS_EXPORT_API(void)
|
||||
JS_ArenaCountRetract(JSArenaPool *pool, char *mark)
|
||||
{
|
||||
pool->stats.nfastrels++;
|
||||
}
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
JS_EXPORT_API(void)
|
||||
JS_DumpArenaStats(FILE *fp)
|
||||
{
|
||||
JSArenaStats *stats;
|
||||
double mean, variance;
|
||||
|
||||
for (stats = arena_stats_list; stats; stats = stats->next) {
|
||||
if (stats->nallocs != 0) {
|
||||
mean = (double)stats->nbytes / stats->nallocs;
|
||||
variance = fabs(stats->variance / stats->nallocs - mean * mean);
|
||||
} else {
|
||||
mean = variance = 0;
|
||||
}
|
||||
|
||||
fprintf(fp, "\n%s allocation statistics:\n", stats->name);
|
||||
fprintf(fp, " number of arenas: %u\n", stats->narenas);
|
||||
fprintf(fp, " number of allocations: %u\n", stats->nallocs);
|
||||
fprintf(fp, " number of free arena reclaims: %u\n", stats->nreclaims);
|
||||
fprintf(fp, " number of malloc calls: %u\n", stats->nmallocs);
|
||||
fprintf(fp, " number of deallocations: %u\n", stats->ndeallocs);
|
||||
fprintf(fp, " number of allocation growths: %u\n", stats->ngrows);
|
||||
fprintf(fp, " number of in-place growths: %u\n", stats->ninplace);
|
||||
fprintf(fp, "number of released allocations: %u\n", stats->nreleases);
|
||||
fprintf(fp, " number of fast releases: %u\n", stats->nfastrels);
|
||||
fprintf(fp, " total bytes allocated: %u\n", stats->nbytes);
|
||||
fprintf(fp, " mean allocation size: %g\n", mean);
|
||||
fprintf(fp, " standard deviation: %g\n", sqrt(variance));
|
||||
fprintf(fp, " maximum allocation size: %u\n", stats->maxalloc);
|
||||
}
|
||||
}
|
||||
#endif /* JS_ARENAMETER */
|
||||
246
mozilla/js/src/jsarena.h
Normal file
246
mozilla/js/src/jsarena.h
Normal file
@@ -0,0 +1,246 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef jsarena_h___
|
||||
#define jsarena_h___
|
||||
/*
|
||||
* Lifetime-based fast allocation, inspired by much prior art, including
|
||||
* "Fast Allocation and Deallocation of Memory Based on Object Lifetimes"
|
||||
* David R. Hanson, Software -- Practice and Experience, Vol. 20(1).
|
||||
*
|
||||
* Also supports LIFO allocation (JS_ARENA_MARK/JS_ARENA_RELEASE).
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "jstypes.h"
|
||||
#include "jscompat.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
typedef struct JSArena JSArena;
|
||||
typedef struct JSArenaPool JSArenaPool;
|
||||
|
||||
struct JSArena {
|
||||
JSArena *next; /* next arena for this lifetime */
|
||||
jsuword base; /* aligned base address, follows this header */
|
||||
jsuword limit; /* one beyond last byte in arena */
|
||||
jsuword avail; /* points to next available byte */
|
||||
};
|
||||
|
||||
#ifdef JS_ARENAMETER
|
||||
typedef struct JSArenaStats JSArenaStats;
|
||||
|
||||
struct JSArenaStats {
|
||||
JSArenaStats *next; /* next in arenaStats list */
|
||||
char *name; /* name for debugging */
|
||||
uint32 narenas; /* number of arenas in pool */
|
||||
uint32 nallocs; /* number of JS_ARENA_ALLOCATE() calls */
|
||||
uint32 nreclaims; /* number of reclaims from freeArenas */
|
||||
uint32 nmallocs; /* number of malloc() calls */
|
||||
uint32 ndeallocs; /* number of lifetime deallocations */
|
||||
uint32 ngrows; /* number of JS_ARENA_GROW() calls */
|
||||
uint32 ninplace; /* number of in-place growths */
|
||||
uint32 nreleases; /* number of JS_ARENA_RELEASE() calls */
|
||||
uint32 nfastrels; /* number of "fast path" releases */
|
||||
size_t nbytes; /* total bytes allocated */
|
||||
size_t maxalloc; /* maximum allocation size in bytes */
|
||||
double variance; /* size variance accumulator */
|
||||
};
|
||||
#endif
|
||||
|
||||
struct JSArenaPool {
|
||||
JSArena first; /* first arena in pool list */
|
||||
JSArena *current; /* arena from which to allocate space */
|
||||
size_t arenasize; /* net exact size of a new arena */
|
||||
jsuword mask; /* alignment mask (power-of-2 - 1) */
|
||||
#ifdef JS_ARENAMETER
|
||||
JSArenaStats stats;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* If the including .c file uses only one power-of-2 alignment, it may define
|
||||
* JS_ARENA_CONST_ALIGN_MASK to the alignment mask and save a few instructions
|
||||
* per ALLOCATE and GROW.
|
||||
*/
|
||||
#ifdef JS_ARENA_CONST_ALIGN_MASK
|
||||
#define JS_ARENA_ALIGN(pool, n) (((jsuword)(n) + JS_ARENA_CONST_ALIGN_MASK) \
|
||||
& ~JS_ARENA_CONST_ALIGN_MASK)
|
||||
|
||||
#define JS_INIT_ARENA_POOL(pool, name, size) \
|
||||
JS_InitArenaPool(pool, name, size, JS_ARENA_CONST_ALIGN_MASK + 1)
|
||||
#else
|
||||
#define JS_ARENA_ALIGN(pool, n) (((jsuword)(n) + (pool)->mask) & ~(pool)->mask)
|
||||
#endif
|
||||
|
||||
#define JS_ARENA_ALLOCATE(p, pool, nb) \
|
||||
JS_BEGIN_MACRO \
|
||||
JSArena *_a = (pool)->current; \
|
||||
size_t _nb = JS_ARENA_ALIGN(pool, nb); \
|
||||
jsuword _p = _a->avail; \
|
||||
jsuword _q = _p + _nb; \
|
||||
if (_q > _a->limit) \
|
||||
_p = (jsuword)JS_ArenaAllocate(pool, _nb); \
|
||||
else \
|
||||
_a->avail = _q; \
|
||||
p = (void *)_p; \
|
||||
JS_ArenaCountAllocation(pool, nb); \
|
||||
JS_END_MACRO
|
||||
|
||||
#define JS_ARENA_GROW(p, pool, size, incr) \
|
||||
JS_BEGIN_MACRO \
|
||||
JSArena *_a = (pool)->current; \
|
||||
size_t _incr = JS_ARENA_ALIGN(pool, incr); \
|
||||
jsuword _p = _a->avail; \
|
||||
jsuword _q = _p + _incr; \
|
||||
if (_p == (jsuword)(p) + JS_ARENA_ALIGN(pool, size) && \
|
||||
_q <= _a->limit) { \
|
||||
_a->avail = _q; \
|
||||
JS_ArenaCountInplaceGrowth(pool, size, incr); \
|
||||
} else { \
|
||||
p = JS_ArenaGrow(pool, p, size, incr); \
|
||||
} \
|
||||
JS_ArenaCountGrowth(pool, size, incr); \
|
||||
JS_END_MACRO
|
||||
|
||||
#define JS_ARENA_MARK(pool) ((void *) (pool)->current->avail)
|
||||
#define JS_UPTRDIFF(p,q) ((jsuword)(p) - (jsuword)(q))
|
||||
|
||||
#ifdef DEBUG
|
||||
#define free_PATTERN 0xDA
|
||||
#define JS_CLEAR_UNUSED(a) (JS_ASSERT((a)->avail <= (a)->limit), \
|
||||
memset((void*)(a)->avail, free_PATTERN, \
|
||||
(a)->limit - (a)->avail))
|
||||
#define JS_CLEAR_ARENA(a) memset((void*)(a), free_PATTERN, \
|
||||
(a)->limit - (jsuword)(a))
|
||||
#else
|
||||
#define JS_CLEAR_UNUSED(a) /* nothing */
|
||||
#define JS_CLEAR_ARENA(a) /* nothing */
|
||||
#endif
|
||||
|
||||
#define JS_ARENA_RELEASE(pool, mark) \
|
||||
JS_BEGIN_MACRO \
|
||||
char *_m = (char *)(mark); \
|
||||
JSArena *_a = (pool)->current; \
|
||||
if (JS_UPTRDIFF(_m, _a) <= JS_UPTRDIFF(_a->avail, _a)) { \
|
||||
_a->avail = (jsuword)JS_ARENA_ALIGN(pool, _m); \
|
||||
JS_CLEAR_UNUSED(_a); \
|
||||
JS_ArenaCountRetract(pool, _m); \
|
||||
} else { \
|
||||
JS_ArenaRelease(pool, _m); \
|
||||
} \
|
||||
JS_ArenaCountRelease(pool, _m); \
|
||||
JS_END_MACRO
|
||||
|
||||
#ifdef JS_ARENAMETER
|
||||
#define JS_COUNT_ARENA(pool,op) ((pool)->stats.narenas op)
|
||||
#else
|
||||
#define JS_COUNT_ARENA(pool,op)
|
||||
#endif
|
||||
|
||||
#define JS_ARENA_DESTROY(pool, a, pnext) \
|
||||
JS_BEGIN_MACRO \
|
||||
JS_COUNT_ARENA(pool,--); \
|
||||
if ((pool)->current == (a)) (pool)->current = &(pool)->first; \
|
||||
*(pnext) = (a)->next; \
|
||||
JS_CLEAR_ARENA(a); \
|
||||
free(a); \
|
||||
(a) = NULL; \
|
||||
JS_END_MACRO
|
||||
|
||||
/*
|
||||
* Initialize an arena pool with the given name for debugging and metering,
|
||||
* with a minimum size per arena of size bytes.
|
||||
*/
|
||||
JS_EXTERN_API(void)
|
||||
JS_InitArenaPool(JSArenaPool *pool, const char *name, JSUint32 size,
|
||||
JSUint32 align);
|
||||
|
||||
/*
|
||||
* Free the arenas in pool. The user may continue to allocate from pool
|
||||
* after calling this function. There is no need to call JS_InitArenaPool()
|
||||
* again unless JS_FinishArenaPool(pool) has been called.
|
||||
*/
|
||||
JS_EXTERN_API(void)
|
||||
JS_FreeArenaPool(JSArenaPool *pool);
|
||||
|
||||
/*
|
||||
* Free the arenas in pool and finish using it altogether.
|
||||
*/
|
||||
JS_EXTERN_API(void)
|
||||
JS_FinishArenaPool(JSArenaPool *pool);
|
||||
|
||||
/*
|
||||
* Compact all of the arenas in a pool so that no space is wasted.
|
||||
*/
|
||||
JS_EXTERN_API(void)
|
||||
JS_CompactArenaPool(JSArenaPool *pool);
|
||||
|
||||
/*
|
||||
* Finish using arenas, freeing all memory associated with them.
|
||||
*/
|
||||
JS_EXTERN_API(void)
|
||||
JS_ArenaFinish(void);
|
||||
|
||||
/*
|
||||
* Friend functions used by the JS_ARENA_*() macros.
|
||||
*/
|
||||
JS_EXTERN_API(void *)
|
||||
JS_ArenaAllocate(JSArenaPool *pool, JSUint32 nb);
|
||||
|
||||
JS_EXTERN_API(void *)
|
||||
JS_ArenaGrow(JSArenaPool *pool, void *p, JSUint32 size, JSUint32 incr);
|
||||
|
||||
JS_EXTERN_API(void)
|
||||
JS_ArenaRelease(JSArenaPool *pool, char *mark);
|
||||
|
||||
#ifdef JS_ARENAMETER
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
JS_EXTERN_API(void)
|
||||
JS_ArenaCountAllocation(JSArenaPool *pool, JSUint32 nb);
|
||||
|
||||
JS_EXTERN_API(void)
|
||||
JS_ArenaCountInplaceGrowth(JSArenaPool *pool, JSUint32 size, JSUint32 incr);
|
||||
|
||||
JS_EXTERN_API(void)
|
||||
JS_ArenaCountGrowth(JSArenaPool *pool, JSUint32 size, JSUint32incr);
|
||||
|
||||
JS_EXTERN_API(void)
|
||||
JS_ArenaCountRelease(JSArenaPool *pool, char *mark);
|
||||
|
||||
JS_EXTERN_API(void)
|
||||
JS_ArenaCountRetract(JSArenaPool *pool, char *mark);
|
||||
|
||||
JS_EXTERN_API(void)
|
||||
JS_DumpArenaStats(FILE *fp);
|
||||
|
||||
#else /* !JS_ARENAMETER */
|
||||
|
||||
#define JS_ArenaCountAllocation(ap, nb) /* nothing */
|
||||
#define JS_ArenaCountInplaceGrowth(ap, size, incr) /* nothing */
|
||||
#define JS_ArenaCountGrowth(ap, size, incr) /* nothing */
|
||||
#define JS_ArenaCountRelease(ap, mark) /* nothing */
|
||||
#define JS_ArenaCountRetract(ap, mark) /* nothing */
|
||||
|
||||
#endif /* !JS_ARENAMETER */
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsarena_h___ */
|
||||
1298
mozilla/js/src/jsarray.c
Normal file
1298
mozilla/js/src/jsarray.c
Normal file
File diff suppressed because it is too large
Load Diff
56
mozilla/js/src/jsarray.h
Normal file
56
mozilla/js/src/jsarray.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef jsarray_h___
|
||||
#define jsarray_h___
|
||||
/*
|
||||
* JS Array interface.
|
||||
*/
|
||||
#include "jsprvtd.h"
|
||||
#include "jspubtd.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
extern JSClass js_ArrayClass;
|
||||
|
||||
extern JSObject *
|
||||
js_InitArrayClass(JSContext *cx, JSObject *obj);
|
||||
|
||||
extern JSObject *
|
||||
js_NewArrayObject(JSContext *cx, jsuint length, jsval *vector);
|
||||
|
||||
extern JSBool
|
||||
js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp);
|
||||
|
||||
extern JSBool
|
||||
js_SetLengthProperty(JSContext *cx, JSObject *obj, jsuint length);
|
||||
|
||||
extern JSBool
|
||||
js_HasLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp);
|
||||
|
||||
/*
|
||||
* JS-specific qsort function.
|
||||
*/
|
||||
typedef int (*JSComparator)(const void *a, const void *b, void *arg);
|
||||
|
||||
extern JSBool
|
||||
js_qsort(void *vec, size_t nel, size_t elsize, JSComparator cmp, void *arg);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsarray_h___ */
|
||||
655
mozilla/js/src/jsatom.c
Normal file
655
mozilla/js/src/jsatom.c
Normal file
@@ -0,0 +1,655 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* JS atom table.
|
||||
*/
|
||||
#include "jsstddef.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "jstypes.h"
|
||||
#include "jsutil.h" /* Added by JSIFY */
|
||||
#include "jshash.h" /* Added by JSIFY */
|
||||
#include "jsprf.h"
|
||||
#include "jsapi.h"
|
||||
#include "jsatom.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsgc.h"
|
||||
#include "jslock.h"
|
||||
#include "jsnum.h"
|
||||
#include "jsopcode.h"
|
||||
#include "jsstr.h"
|
||||
|
||||
/*
|
||||
* Keep this in sync with jspubtd.h -- an assertion below will insist that
|
||||
* its length match the JSType enum's JSTYPE_LIMIT limit value.
|
||||
*/
|
||||
char *js_type_str[] = {
|
||||
"undefined",
|
||||
"object",
|
||||
"function",
|
||||
"string",
|
||||
"number",
|
||||
"boolean",
|
||||
};
|
||||
|
||||
char *js_boolean_str[] = {
|
||||
js_false_str,
|
||||
js_true_str
|
||||
};
|
||||
|
||||
char js_Array_str[] = "Array";
|
||||
char js_Math_str[] = "Math";
|
||||
char js_Object_str[] = "Object";
|
||||
char js_anonymous_str[] = "anonymous";
|
||||
char js_arguments_str[] = "arguments";
|
||||
char js_arity_str[] = "arity";
|
||||
char js_assign_str[] = "assign";
|
||||
char js_callee_str[] = "callee";
|
||||
char js_caller_str[] = "caller";
|
||||
char js_class_prototype_str[] = "prototype";
|
||||
char js_constructor_str[] = "constructor";
|
||||
char js_count_str[] = "__count__";
|
||||
char js_eval_str[] = "eval";
|
||||
char js_index_str[] = "index";
|
||||
char js_input_str[] = "input";
|
||||
char js_length_str[] = "length";
|
||||
char js_name_str[] = "name";
|
||||
char js_parent_str[] = "__parent__";
|
||||
char js_proto_str[] = "__proto__";
|
||||
char js_toSource_str[] = "toSource";
|
||||
char js_toString_str[] = "toString";
|
||||
char js_valueOf_str[] = "valueOf";
|
||||
|
||||
#define HASH_OBJECT(o) ((JSHashNumber)(o) >> JSVAL_TAGBITS)
|
||||
#define HASH_INT(i) ((JSHashNumber)(i))
|
||||
#define HASH_DOUBLE(dp) ((JSHashNumber)(((uint32*)(dp))[0] ^ ((uint32*)(dp))[1]))
|
||||
#define HASH_BOOLEAN(b) ((JSHashNumber)(b))
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(JSHashNumber)
|
||||
js_hash_atom_key(const void *key)
|
||||
{
|
||||
jsval v;
|
||||
jsdouble *dp;
|
||||
|
||||
/* Order JSVAL_IS_* tests by likelihood of success. */
|
||||
v = (jsval)key;
|
||||
if (JSVAL_IS_STRING(v))
|
||||
return js_HashString(JSVAL_TO_STRING(v));
|
||||
if (JSVAL_IS_INT(v))
|
||||
return HASH_INT(JSVAL_TO_INT(v));
|
||||
if (JSVAL_IS_DOUBLE(v)) {
|
||||
dp = JSVAL_TO_DOUBLE(v);
|
||||
return HASH_DOUBLE(dp);
|
||||
}
|
||||
if (JSVAL_IS_OBJECT(v))
|
||||
return HASH_OBJECT(JSVAL_TO_OBJECT(v));
|
||||
if (JSVAL_IS_BOOLEAN(v))
|
||||
return HASH_BOOLEAN(JSVAL_TO_BOOLEAN(v));
|
||||
return (JSHashNumber)v;
|
||||
}
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(intN)
|
||||
js_compare_atom_keys(const void *k1, const void *k2)
|
||||
{
|
||||
jsval v1, v2;
|
||||
|
||||
v1 = (jsval)k1, v2 = (jsval)k2;
|
||||
if (JSVAL_IS_STRING(v1) && JSVAL_IS_STRING(v2))
|
||||
return !js_CompareStrings(JSVAL_TO_STRING(v1), JSVAL_TO_STRING(v2));
|
||||
if (JSVAL_IS_DOUBLE(v1) && JSVAL_IS_DOUBLE(v2)) {
|
||||
double d1 = *JSVAL_TO_DOUBLE(v1);
|
||||
double d2 = *JSVAL_TO_DOUBLE(v2);
|
||||
if (JSDOUBLE_IS_NaN(d1))
|
||||
return JSDOUBLE_IS_NaN(d2);
|
||||
#ifdef XP_PC
|
||||
/* XXX MSVC miscompiles such that (NaN == 0) */
|
||||
if (JSDOUBLE_IS_NaN(d2))
|
||||
return JS_FALSE;
|
||||
#endif
|
||||
return d1 == d2;
|
||||
}
|
||||
return v1 == v2;
|
||||
}
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(int)
|
||||
js_compare_stub(const void *v1, const void *v2)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(void *)
|
||||
js_alloc_atom_space(void *priv, size_t size)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(void)
|
||||
js_free_atom_space(void *priv, void *item)
|
||||
{
|
||||
free(item);
|
||||
}
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(JSHashEntry *)
|
||||
js_alloc_atom(void *priv, const void *key)
|
||||
{
|
||||
JSAtomState *state = priv;
|
||||
JSAtom *atom;
|
||||
|
||||
atom = malloc(sizeof(JSAtom));
|
||||
if (!atom)
|
||||
return NULL;
|
||||
#ifdef JS_THREADSAFE
|
||||
state->tablegen++;
|
||||
#endif
|
||||
atom->entry.key = key;
|
||||
atom->entry.value = NULL;
|
||||
atom->flags = 0;
|
||||
atom->kwindex = -1;
|
||||
atom->number = state->number++;
|
||||
return &atom->entry;
|
||||
}
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(void)
|
||||
js_free_atom(void *priv, JSHashEntry *he, uintN flag)
|
||||
{
|
||||
if (flag != HT_FREE_ENTRY)
|
||||
return;
|
||||
#ifdef JS_THREADSAFE
|
||||
((JSAtomState *)priv)->tablegen++;
|
||||
#endif
|
||||
free(he);
|
||||
}
|
||||
|
||||
static JSHashAllocOps atom_alloc_ops = {
|
||||
js_alloc_atom_space, js_free_atom_space,
|
||||
js_alloc_atom, js_free_atom
|
||||
};
|
||||
|
||||
#define JS_ATOM_HASH_SIZE 1024
|
||||
|
||||
JSBool
|
||||
js_InitAtomState(JSContext *cx, JSAtomState *state)
|
||||
{
|
||||
uintN i;
|
||||
|
||||
state->runtime = cx->runtime;
|
||||
state->number = 0;
|
||||
state->table = JS_NewHashTable(JS_ATOM_HASH_SIZE, js_hash_atom_key,
|
||||
js_compare_atom_keys, js_compare_stub,
|
||||
&atom_alloc_ops, state);
|
||||
if (!state->table) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return JS_FALSE;
|
||||
}
|
||||
#ifdef JS_THREADSAFE
|
||||
js_NewLock(&state->lock);
|
||||
state->tablegen = 0;
|
||||
#endif
|
||||
|
||||
#define FROB(lval,str) { \
|
||||
if (!(state->lval = js_Atomize(cx, str, strlen(str), ATOM_PINNED))) { \
|
||||
js_FreeAtomState(cx, state); \
|
||||
return JS_FALSE; \
|
||||
} \
|
||||
}
|
||||
|
||||
JS_ASSERT(sizeof js_type_str / sizeof js_type_str[0] == JSTYPE_LIMIT);
|
||||
for (i = 0; i < JSTYPE_LIMIT; i++)
|
||||
FROB(typeAtoms[i], js_type_str[i]);
|
||||
|
||||
FROB(booleanAtoms[0], js_false_str);
|
||||
FROB(booleanAtoms[1], js_true_str);
|
||||
FROB(nullAtom, js_null_str);
|
||||
|
||||
FROB(ArrayAtom, js_Array_str);
|
||||
FROB(MathAtom, js_Math_str);
|
||||
FROB(ObjectAtom, js_Object_str);
|
||||
FROB(anonymousAtom, js_anonymous_str);
|
||||
FROB(argumentsAtom, js_arguments_str);
|
||||
FROB(arityAtom, js_arity_str);
|
||||
FROB(assignAtom, js_assign_str);
|
||||
FROB(calleeAtom, js_callee_str);
|
||||
FROB(callerAtom, js_caller_str);
|
||||
FROB(classPrototypeAtom, js_class_prototype_str);
|
||||
FROB(constructorAtom, js_constructor_str);
|
||||
FROB(countAtom, js_count_str);
|
||||
FROB(indexAtom, js_index_str);
|
||||
FROB(inputAtom, js_input_str);
|
||||
FROB(lengthAtom, js_length_str);
|
||||
FROB(nameAtom, js_name_str);
|
||||
FROB(parentAtom, js_parent_str);
|
||||
FROB(protoAtom, js_proto_str);
|
||||
FROB(toSourceAtom, js_toSource_str);
|
||||
FROB(toStringAtom, js_toString_str);
|
||||
FROB(valueOfAtom, js_valueOf_str);
|
||||
FROB(evalAtom, js_eval_str);
|
||||
|
||||
#undef FROB
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
js_FreeAtomState(JSContext *cx, JSAtomState *state)
|
||||
{
|
||||
state->runtime = NULL;
|
||||
JS_HashTableDestroy(state->table);
|
||||
state->table = NULL;
|
||||
state->number = 0;
|
||||
#ifdef JS_THREADSAFE
|
||||
js_DestroyLock(&state->lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
typedef struct MarkArgs {
|
||||
JSRuntime *runtime;
|
||||
JSGCThingMarker mark;
|
||||
} MarkArgs;
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(intN)
|
||||
js_atom_marker(JSHashEntry *he, intN i, void *arg)
|
||||
{
|
||||
JSAtom *atom;
|
||||
jsval key;
|
||||
MarkArgs *args;
|
||||
|
||||
atom = (JSAtom *)he;
|
||||
if (atom->flags & ATOM_PINNED) {
|
||||
atom->flags |= ATOM_MARK;
|
||||
key = ATOM_KEY(atom);
|
||||
if (JSVAL_IS_GCTHING(key)) {
|
||||
args = arg;
|
||||
args->mark(args->runtime, JSVAL_TO_GCTHING(key));
|
||||
}
|
||||
}
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
js_MarkAtomState(JSAtomState *state, JSGCThingMarker mark)
|
||||
{
|
||||
MarkArgs args;
|
||||
|
||||
args.runtime = state->runtime;
|
||||
args.mark = mark;
|
||||
JS_HashTableEnumerateEntries(state->table, js_atom_marker, &args);
|
||||
}
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(intN)
|
||||
js_atom_sweeper(JSHashEntry *he, intN i, void *arg)
|
||||
{
|
||||
JSAtom *atom;
|
||||
|
||||
atom = (JSAtom *)he;
|
||||
if (atom->flags & ATOM_MARK) {
|
||||
atom->flags &= ~ATOM_MARK;
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
JS_ASSERT((atom->flags & ATOM_PINNED) == 0);
|
||||
atom->entry.key = NULL;
|
||||
atom->flags = 0;
|
||||
return HT_ENUMERATE_REMOVE;
|
||||
}
|
||||
|
||||
void
|
||||
js_SweepAtomState(JSAtomState *state)
|
||||
{
|
||||
JS_HashTableEnumerateEntries(state->table, js_atom_sweeper, NULL);
|
||||
}
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(intN)
|
||||
js_atom_unpinner(JSHashEntry *he, intN i, void *arg)
|
||||
{
|
||||
JSAtom *atom;
|
||||
|
||||
atom = (JSAtom *)he;
|
||||
atom->flags &= ~ATOM_PINNED;
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
js_UnpinPinnedAtoms(JSAtomState *state)
|
||||
{
|
||||
JS_HashTableEnumerateEntries(state->table, js_atom_unpinner, NULL);
|
||||
}
|
||||
|
||||
static JSAtom *
|
||||
js_AtomizeHashedKey(JSContext *cx, jsval key, JSHashNumber keyHash, uintN flags)
|
||||
{
|
||||
JSAtomState *state;
|
||||
JSHashTable *table;
|
||||
JSHashEntry *he, **hep;
|
||||
JSAtom *atom;
|
||||
|
||||
state = &cx->runtime->atomState;
|
||||
JS_LOCK(&state->lock,cx);
|
||||
table = state->table;
|
||||
hep = JS_HashTableRawLookup(table, keyHash, (void *)key);
|
||||
if ((he = *hep) == NULL) {
|
||||
he = JS_HashTableRawAdd(table, hep, keyHash, (void *)key, NULL);
|
||||
if (!he) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
atom = NULL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
atom = (JSAtom *)he;
|
||||
atom->flags |= flags;
|
||||
out:
|
||||
JS_UNLOCK(&state->lock,cx);
|
||||
return atom;
|
||||
}
|
||||
|
||||
JSAtom *
|
||||
js_AtomizeObject(JSContext *cx, JSObject *obj, uintN flags)
|
||||
{
|
||||
jsval key;
|
||||
JSHashNumber keyHash;
|
||||
|
||||
/* XXX must be set in the following order or MSVC1.52 will crash */
|
||||
keyHash = HASH_OBJECT(obj);
|
||||
key = OBJECT_TO_JSVAL(obj);
|
||||
return js_AtomizeHashedKey(cx, key, keyHash, flags);
|
||||
}
|
||||
|
||||
JSAtom *
|
||||
js_AtomizeBoolean(JSContext *cx, JSBool b, uintN flags)
|
||||
{
|
||||
jsval key;
|
||||
JSHashNumber keyHash;
|
||||
|
||||
key = BOOLEAN_TO_JSVAL(b);
|
||||
keyHash = HASH_BOOLEAN(b);
|
||||
return js_AtomizeHashedKey(cx, key, keyHash, flags);
|
||||
}
|
||||
|
||||
JSAtom *
|
||||
js_AtomizeInt(JSContext *cx, jsint i, uintN flags)
|
||||
{
|
||||
jsval key;
|
||||
JSHashNumber keyHash;
|
||||
|
||||
key = INT_TO_JSVAL(i);
|
||||
keyHash = HASH_INT(i);
|
||||
return js_AtomizeHashedKey(cx, key, keyHash, flags);
|
||||
}
|
||||
|
||||
JSAtom *
|
||||
js_AtomizeDouble(JSContext *cx, jsdouble d, uintN flags)
|
||||
{
|
||||
jsdouble *dp;
|
||||
JSHashNumber keyHash;
|
||||
jsval key;
|
||||
JSAtomState *state;
|
||||
JSHashTable *table;
|
||||
JSHashEntry *he, **hep;
|
||||
JSAtom *atom;
|
||||
#define ALIGNNUM ((1<<JSVAL_TAGBITS) < sizeof(double) ? sizeof(double) : (1<<JSVAL_TAGBITS))
|
||||
char alignbuf[2*ALIGNNUM];
|
||||
jsuword alignint = (jsuword)alignbuf;
|
||||
jsuword xtra = ALIGNNUM-(alignint%ALIGNNUM);
|
||||
#undef ALIGNNUM
|
||||
dp = (jsdouble *)&alignbuf[xtra];
|
||||
*dp = d;
|
||||
keyHash = HASH_DOUBLE(dp);
|
||||
key = DOUBLE_TO_JSVAL(dp);
|
||||
state = &cx->runtime->atomState;
|
||||
JS_LOCK(&state->lock,cx);
|
||||
table = state->table;
|
||||
hep = JS_HashTableRawLookup(table, keyHash, (void *)key);
|
||||
if ((he = *hep) == NULL) {
|
||||
#ifdef JS_THREADSAFE
|
||||
uint32 gen = state->tablegen;
|
||||
#endif
|
||||
JS_UNLOCK(&state->lock,cx);
|
||||
if (!js_NewDoubleValue(cx, d, &key))
|
||||
return NULL;
|
||||
JS_LOCK(&state->lock,cx);
|
||||
#ifdef JS_THREADSAFE
|
||||
if (state->tablegen != gen) {
|
||||
hep = JS_HashTableRawLookup(table, keyHash, (void *)key);
|
||||
if ((he = *hep) != NULL) {
|
||||
atom = (JSAtom *)he;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
he = JS_HashTableRawAdd(table, hep, keyHash, (void *)key, NULL);
|
||||
if (!he) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
atom = NULL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
atom = (JSAtom *)he;
|
||||
atom->flags |= flags;
|
||||
out:
|
||||
JS_UNLOCK(&state->lock,cx);
|
||||
return atom;
|
||||
}
|
||||
|
||||
JSAtom *
|
||||
js_AtomizeString(JSContext *cx, JSString *str, uintN flags)
|
||||
{
|
||||
JSHashNumber keyHash;
|
||||
jsval key;
|
||||
JSAtomState *state;
|
||||
JSHashTable *table;
|
||||
JSHashEntry *he, **hep;
|
||||
JSAtom *atom;
|
||||
|
||||
keyHash = js_HashString(str);
|
||||
key = STRING_TO_JSVAL(str);
|
||||
state = &cx->runtime->atomState;
|
||||
JS_LOCK(&state->lock,cx);
|
||||
table = state->table;
|
||||
hep = JS_HashTableRawLookup(table, keyHash, (void *)key);
|
||||
if ((he = *hep) == NULL) {
|
||||
if (flags & ATOM_TMPSTR) {
|
||||
#ifdef JS_THREADSAFE
|
||||
uint32 gen = state->tablegen;
|
||||
#endif
|
||||
JS_UNLOCK(&state->lock,cx);
|
||||
flags &= ~ATOM_TMPSTR;
|
||||
if (flags & ATOM_NOCOPY) {
|
||||
flags &= ~ATOM_NOCOPY;
|
||||
str = js_NewString(cx, str->chars, str->length, 0);
|
||||
} else {
|
||||
str = js_NewStringCopyN(cx, str->chars, str->length, 0);
|
||||
}
|
||||
if (!str)
|
||||
return NULL;
|
||||
key = STRING_TO_JSVAL(str);
|
||||
JS_LOCK(&state->lock,cx);
|
||||
#ifdef JS_THREADSAFE
|
||||
if (state->tablegen != gen) {
|
||||
hep = JS_HashTableRawLookup(table, keyHash, (void *)key);
|
||||
if ((he = *hep) != NULL) {
|
||||
atom = (JSAtom *)he;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
he = JS_HashTableRawAdd(table, hep, keyHash, (void *)key, NULL);
|
||||
if (!he) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
atom = NULL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
atom = (JSAtom *)he;
|
||||
atom->flags |= flags;
|
||||
out:
|
||||
JS_UNLOCK(&state->lock,cx);
|
||||
return atom;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSAtom *)
|
||||
js_Atomize(JSContext *cx, const char *bytes, size_t length, uintN flags)
|
||||
{
|
||||
jschar *chars;
|
||||
JSString *str;
|
||||
JSAtom *atom;
|
||||
#define ALIGNNUM ((1<<JSVAL_TAGBITS) < sizeof(JSString) ? sizeof(JSString) : (1<<JSVAL_TAGBITS))
|
||||
char alignbuf[2*ALIGNNUM];
|
||||
jsuword alignint = (jsuword)alignbuf;
|
||||
jsuword xtra = ALIGNNUM-(alignint%ALIGNNUM);
|
||||
#undef ALIGNNUM
|
||||
str = (JSString *)&alignbuf[xtra];
|
||||
chars = js_InflateString(cx, bytes, length);
|
||||
if (!chars)
|
||||
return NULL;
|
||||
str->chars = chars;
|
||||
str->length = length;
|
||||
atom = js_AtomizeString(cx, str, ATOM_TMPSTR | ATOM_NOCOPY | flags);
|
||||
if (!atom || ATOM_TO_STRING(atom)->chars != chars)
|
||||
JS_free(cx, chars);
|
||||
return atom;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSAtom *)
|
||||
js_AtomizeChars(JSContext *cx, const jschar *chars, size_t length, uintN flags)
|
||||
{
|
||||
JSString *str;
|
||||
#define ALIGNNUM ((1<<JSVAL_TAGBITS) < sizeof(JSString) ? sizeof(JSString) : (1<<JSVAL_TAGBITS))
|
||||
char alignbuf[2*ALIGNNUM];
|
||||
jsuword alignint = (jsuword)alignbuf;
|
||||
jsuword xtra = ALIGNNUM-(alignint%ALIGNNUM);
|
||||
#undef ALIGNNUM
|
||||
str = (JSString *)&alignbuf[xtra];
|
||||
str->chars = (jschar *)chars;
|
||||
str->length = length;
|
||||
return js_AtomizeString(cx, str, ATOM_TMPSTR | flags);
|
||||
}
|
||||
|
||||
JSAtom *
|
||||
js_AtomizeValue(JSContext *cx, jsval value, uintN flags)
|
||||
{
|
||||
if (JSVAL_IS_STRING(value))
|
||||
return js_AtomizeString(cx, JSVAL_TO_STRING(value), flags);
|
||||
if (JSVAL_IS_INT(value))
|
||||
return js_AtomizeInt(cx, JSVAL_TO_INT(value), flags);
|
||||
if (JSVAL_IS_DOUBLE(value))
|
||||
return js_AtomizeDouble(cx, *JSVAL_TO_DOUBLE(value), flags);
|
||||
if (JSVAL_IS_OBJECT(value))
|
||||
return js_AtomizeObject(cx, JSVAL_TO_OBJECT(value), flags);
|
||||
if (JSVAL_IS_BOOLEAN(value))
|
||||
return js_AtomizeBoolean(cx, JSVAL_TO_BOOLEAN(value), flags);
|
||||
return js_AtomizeHashedKey(cx, value, (JSHashNumber)value, flags);
|
||||
}
|
||||
|
||||
JSAtom *
|
||||
js_ValueToStringAtom(JSContext *cx, jsval v)
|
||||
{
|
||||
JSString *str;
|
||||
|
||||
str = js_ValueToString(cx, v);
|
||||
if (!str)
|
||||
return NULL;
|
||||
return js_AtomizeString(cx, str, 0);
|
||||
}
|
||||
|
||||
JSAtomListElement *
|
||||
js_IndexAtom(JSContext *cx, JSAtom *atom, JSAtomList *al)
|
||||
{
|
||||
JSAtomListElement *ale;
|
||||
|
||||
ATOM_LIST_SEARCH(ale, al, atom);
|
||||
if (!ale) {
|
||||
JS_ARENA_ALLOCATE(ale, &cx->tempPool, sizeof(JSAtomListElement));
|
||||
if (!ale) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return NULL;
|
||||
}
|
||||
ale->atom = atom;
|
||||
ale->index = (jsatomid) al->count++;
|
||||
ale->next = al->list;
|
||||
al->list = ale;
|
||||
}
|
||||
return ale;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSAtom *)
|
||||
js_GetAtom(JSContext *cx, JSAtomMap *map, jsatomid i)
|
||||
{
|
||||
JSAtom *atom;
|
||||
|
||||
JS_ASSERT(map->vector && i < map->length);
|
||||
if (!map->vector || i >= map->length) {
|
||||
char numBuf[12];
|
||||
JS_snprintf(numBuf, sizeof numBuf, "%lu", (unsigned long)i);
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_BAD_ATOMIC_NUMBER, numBuf);
|
||||
return NULL;
|
||||
}
|
||||
atom = map->vector[i];
|
||||
JS_ASSERT(atom);
|
||||
return atom;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSBool)
|
||||
js_InitAtomMap(JSContext *cx, JSAtomMap *map, JSAtomList *al)
|
||||
{
|
||||
JSAtom **vector;
|
||||
JSAtomListElement *ale, *next;
|
||||
uint32 count;
|
||||
|
||||
ale = al->list;
|
||||
if (!ale) {
|
||||
map->vector = NULL;
|
||||
map->length = 0;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
count = al->count;
|
||||
if (count >= ATOM_INDEX_LIMIT) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_TOO_MANY_LITERALS);
|
||||
return JS_FALSE;
|
||||
}
|
||||
vector = JS_malloc(cx, (size_t) count * sizeof *vector);
|
||||
if (!vector)
|
||||
return JS_FALSE;
|
||||
|
||||
do {
|
||||
vector[ale->index] = ale->atom;
|
||||
next = ale->next;
|
||||
ale->next = NULL;
|
||||
} while ((ale = next) != NULL);
|
||||
al->list = NULL;
|
||||
al->count = 0;
|
||||
|
||||
map->vector = vector;
|
||||
map->length = (jsatomid)count;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
js_FreeAtomMap(JSContext *cx, JSAtomMap *map)
|
||||
{
|
||||
if (map->vector) {
|
||||
free(map->vector);
|
||||
map->vector = NULL;
|
||||
}
|
||||
map->length = 0;
|
||||
}
|
||||
273
mozilla/js/src/jsatom.h
Normal file
273
mozilla/js/src/jsatom.h
Normal file
@@ -0,0 +1,273 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef jsatom_h___
|
||||
#define jsatom_h___
|
||||
/*
|
||||
* JS atom table.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include "jstypes.h"
|
||||
#include "jshash.h" /* Added by JSIFY */
|
||||
#include "jsapi.h"
|
||||
#include "jsprvtd.h"
|
||||
#include "jspubtd.h"
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
#include "jslock.h"
|
||||
#endif
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
#define ATOM_NOCOPY 0x01 /* don't copy atom string bytes */
|
||||
#define ATOM_TMPSTR 0x02 /* internal, to avoid extra string */
|
||||
#define ATOM_MARK 0x04 /* atom is reachable via GC */
|
||||
#define ATOM_PINNED 0x08 /* atom is pinned against GC */
|
||||
|
||||
struct JSAtom {
|
||||
JSHashEntry entry; /* key is jsval, value keyword info */
|
||||
uint8 flags; /* flags, PINNED and/or MARK for now */
|
||||
int8 kwindex; /* keyword index, -1 if not keyword */
|
||||
jsatomid number; /* atom serial number and hash code */
|
||||
};
|
||||
|
||||
#define ATOM_KEY(atom) ((jsval)(atom)->entry.key)
|
||||
#define ATOM_IS_OBJECT(atom) JSVAL_IS_OBJECT(ATOM_KEY(atom))
|
||||
#define ATOM_TO_OBJECT(atom) JSVAL_TO_OBJECT(ATOM_KEY(atom))
|
||||
#define ATOM_IS_INT(atom) JSVAL_IS_INT(ATOM_KEY(atom))
|
||||
#define ATOM_TO_INT(atom) JSVAL_TO_INT(ATOM_KEY(atom))
|
||||
#define ATOM_IS_DOUBLE(atom) JSVAL_IS_DOUBLE(ATOM_KEY(atom))
|
||||
#define ATOM_TO_DOUBLE(atom) JSVAL_TO_DOUBLE(ATOM_KEY(atom))
|
||||
#define ATOM_IS_STRING(atom) JSVAL_IS_STRING(ATOM_KEY(atom))
|
||||
#define ATOM_TO_STRING(atom) JSVAL_TO_STRING(ATOM_KEY(atom))
|
||||
#define ATOM_IS_BOOLEAN(atom) JSVAL_IS_BOOLEAN(ATOM_KEY(atom))
|
||||
#define ATOM_TO_BOOLEAN(atom) JSVAL_TO_BOOLEAN(ATOM_KEY(atom))
|
||||
#define ATOM_BYTES(atom) JS_GetStringBytes(ATOM_TO_STRING(atom))
|
||||
|
||||
struct JSAtomListElement {
|
||||
JSAtomListElement *next;
|
||||
jsatomid index; /* index in script-specific atom map */
|
||||
JSAtom *atom;
|
||||
};
|
||||
|
||||
struct JSAtomList {
|
||||
JSAtomListElement *list; /* literals indexed for mapping */
|
||||
jsuint count; /* count of indexed literals */
|
||||
};
|
||||
|
||||
#define ATOM_LIST_INIT(al) ((al)->list = NULL, (al)->count = 0)
|
||||
|
||||
#define ATOM_LIST_SEARCH(_ale,_al,_atom) \
|
||||
JS_BEGIN_MACRO \
|
||||
JSAtomListElement **_alep = &(_al)->list; \
|
||||
while ((_ale = *_alep) != NULL) { \
|
||||
if (_ale->atom == (_atom)) { \
|
||||
/* Hit, move atom's element to the front of the list. */ \
|
||||
*_alep = _ale->next; \
|
||||
_ale->next = (_al)->list; \
|
||||
(_al)->list = _ale; \
|
||||
break; \
|
||||
} \
|
||||
_alep = &_ale->next; \
|
||||
} \
|
||||
JS_END_MACRO
|
||||
|
||||
struct JSAtomMap {
|
||||
JSAtom **vector; /* array of ptrs to indexed atoms */
|
||||
jsatomid length; /* count of (to-be-)indexed atoms */
|
||||
};
|
||||
|
||||
struct JSAtomState {
|
||||
JSRuntime *runtime; /* runtime that owns us */
|
||||
JSHashTable *table; /* hash table containing all atoms */
|
||||
jsatomid number; /* one beyond greatest atom number */
|
||||
|
||||
/* Type names and value literals. */
|
||||
JSAtom *typeAtoms[JSTYPE_LIMIT];
|
||||
JSAtom *booleanAtoms[2];
|
||||
JSAtom *nullAtom;
|
||||
|
||||
/* Various built-in or commonly-used atoms. */
|
||||
JSAtom *ArrayAtom;
|
||||
JSAtom *MathAtom;
|
||||
JSAtom *ObjectAtom;
|
||||
JSAtom *anonymousAtom;
|
||||
JSAtom *argumentsAtom;
|
||||
JSAtom *arityAtom;
|
||||
JSAtom *assignAtom;
|
||||
JSAtom *calleeAtom;
|
||||
JSAtom *callerAtom;
|
||||
JSAtom *classPrototypeAtom;
|
||||
JSAtom *constructorAtom;
|
||||
JSAtom *countAtom;
|
||||
JSAtom *indexAtom;
|
||||
JSAtom *inputAtom;
|
||||
JSAtom *lengthAtom;
|
||||
JSAtom *nameAtom;
|
||||
JSAtom *parentAtom;
|
||||
JSAtom *protoAtom;
|
||||
JSAtom *toSourceAtom;
|
||||
JSAtom *toStringAtom;
|
||||
JSAtom *valueOfAtom;
|
||||
JSAtom *evalAtom;
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
JSThinLock lock;
|
||||
volatile uint32 tablegen;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Well-known predefined strings and their atoms. */
|
||||
extern char *js_type_str[];
|
||||
extern char *js_boolean_str[];
|
||||
|
||||
extern char js_Array_str[];
|
||||
extern char js_Math_str[];
|
||||
extern char js_Object_str[];
|
||||
extern char js_anonymous_str[];
|
||||
extern char js_arguments_str[];
|
||||
extern char js_arity_str[];
|
||||
extern char js_assign_str[];
|
||||
extern char js_callee_str[];
|
||||
extern char js_caller_str[];
|
||||
extern char js_class_prototype_str[];
|
||||
extern char js_constructor_str[];
|
||||
extern char js_count_str[];
|
||||
extern char js_eval_str[];
|
||||
extern char js_index_str[];
|
||||
extern char js_input_str[];
|
||||
extern char js_length_str[];
|
||||
extern char js_name_str[];
|
||||
extern char js_parent_str[];
|
||||
extern char js_proto_str[];
|
||||
extern char js_toSource_str[];
|
||||
extern char js_toString_str[];
|
||||
extern char js_valueOf_str[];
|
||||
|
||||
/*
|
||||
* Initialize atom state. Return true on success, false with an out of
|
||||
* memory error report on failure.
|
||||
*/
|
||||
extern JSBool
|
||||
js_InitAtomState(JSContext *cx, JSAtomState *state);
|
||||
|
||||
/*
|
||||
* Free and clear atom state.
|
||||
*/
|
||||
extern void
|
||||
js_FreeAtomState(JSContext *cx, JSAtomState *state);
|
||||
|
||||
/*
|
||||
* Atom garbage collection hooks.
|
||||
*/
|
||||
typedef void
|
||||
(*JSGCThingMarker)(JSRuntime *rt, void *thing);
|
||||
|
||||
extern void
|
||||
js_MarkAtomState(JSAtomState *state, JSGCThingMarker mark);
|
||||
|
||||
extern void
|
||||
js_SweepAtomState(JSAtomState *state);
|
||||
|
||||
extern void
|
||||
js_UnpinPinnedAtoms(JSAtomState *state);
|
||||
|
||||
/*
|
||||
* Find or create the atom for an object. If we create a new atom, give it the
|
||||
* type indicated in flags. Return 0 on failure to allocate memory.
|
||||
*/
|
||||
extern JSAtom *
|
||||
js_AtomizeObject(JSContext *cx, JSObject *obj, uintN flags);
|
||||
|
||||
/*
|
||||
* Find or create the atom for a Boolean value. If we create a new atom, give
|
||||
* it the type indicated in flags. Return 0 on failure to allocate memory.
|
||||
*/
|
||||
extern JSAtom *
|
||||
js_AtomizeBoolean(JSContext *cx, JSBool b, uintN flags);
|
||||
|
||||
/*
|
||||
* Find or create the atom for an integer value. If we create a new atom, give
|
||||
* it the type indicated in flags. Return 0 on failure to allocate memory.
|
||||
*/
|
||||
extern JSAtom *
|
||||
js_AtomizeInt(JSContext *cx, jsint i, uintN flags);
|
||||
|
||||
/*
|
||||
* Find or create the atom for a double value. If we create a new atom, give
|
||||
* it the type indicated in flags. Return 0 on failure to allocate memory.
|
||||
*/
|
||||
extern JSAtom *
|
||||
js_AtomizeDouble(JSContext *cx, jsdouble d, uintN flags);
|
||||
|
||||
/*
|
||||
* Find or create the atom for a string. If we create a new atom, give it the
|
||||
* type indicated in flags. Return 0 on failure to allocate memory.
|
||||
*/
|
||||
extern JSAtom *
|
||||
js_AtomizeString(JSContext *cx, JSString *str, uintN flags);
|
||||
|
||||
extern JS_FRIEND_API(JSAtom *)
|
||||
js_Atomize(JSContext *cx, const char *bytes, size_t length, uintN flags);
|
||||
|
||||
extern JS_FRIEND_API(JSAtom *)
|
||||
js_AtomizeChars(JSContext *cx, const jschar *chars, size_t length, uintN flags);
|
||||
|
||||
/*
|
||||
* This variant handles all value tag types.
|
||||
*/
|
||||
extern JSAtom *
|
||||
js_AtomizeValue(JSContext *cx, jsval value, uintN flags);
|
||||
|
||||
/*
|
||||
* Convert v to an atomized string.
|
||||
*/
|
||||
extern JSAtom *
|
||||
js_ValueToStringAtom(JSContext *cx, jsval v);
|
||||
|
||||
/*
|
||||
* Assign atom an index and insert it on al.
|
||||
*/
|
||||
extern JSAtomListElement *
|
||||
js_IndexAtom(JSContext *cx, JSAtom *atom, JSAtomList *al);
|
||||
|
||||
/*
|
||||
* Get the atom with index i from map.
|
||||
*/
|
||||
extern JS_FRIEND_API(JSAtom *)
|
||||
js_GetAtom(JSContext *cx, JSAtomMap *map, jsatomid i);
|
||||
|
||||
/*
|
||||
* For all unmapped atoms recorded in al, add a mapping from the atom's index
|
||||
* to its address. The GC must not run until all indexed atoms in atomLists
|
||||
* have been mapped by scripts connected to live objects (Function and Script
|
||||
* class objects have scripts as/in their private data -- the GC knows about
|
||||
* these two classes).
|
||||
*/
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
js_InitAtomMap(JSContext *cx, JSAtomMap *map, JSAtomList *al);
|
||||
|
||||
/*
|
||||
* Free map->vector and clear map.
|
||||
*/
|
||||
extern JS_FRIEND_API(void)
|
||||
js_FreeAtomMap(JSContext *cx, JSAtomMap *map);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsatom_h___ */
|
||||
92
mozilla/js/src/jsbit.h
Normal file
92
mozilla/js/src/jsbit.h
Normal file
@@ -0,0 +1,92 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef jsbit_h___
|
||||
#define jsbit_h___
|
||||
|
||||
#include "jstypes.h"
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
/*
|
||||
** A jsbitmap_t is a long integer that can be used for bitmaps
|
||||
*/
|
||||
typedef unsigned long jsbitmap_t;
|
||||
|
||||
#define JS_TEST_BIT(_map,_bit) \
|
||||
((_map)[(_bit)>>JS_BITS_PER_LONG_LOG2] & (1L << ((_bit) & (JS_BITS_PER_LONG-1))))
|
||||
#define JS_SET_BIT(_map,_bit) \
|
||||
((_map)[(_bit)>>JS_BITS_PER_LONG_LOG2] |= (1L << ((_bit) & (JS_BITS_PER_LONG-1))))
|
||||
#define JS_CLEAR_BIT(_map,_bit) \
|
||||
((_map)[(_bit)>>JS_BITS_PER_LONG_LOG2] &= ~(1L << ((_bit) & (JS_BITS_PER_LONG-1))))
|
||||
|
||||
/*
|
||||
** Compute the log of the least power of 2 greater than or equal to n
|
||||
*/
|
||||
JS_EXTERN_API(JSIntn) JS_CeilingLog2(JSUint32 i);
|
||||
|
||||
/*
|
||||
** Compute the log of the greatest power of 2 less than or equal to n
|
||||
*/
|
||||
JS_EXTERN_API(JSIntn) JS_FloorLog2(JSUint32 i);
|
||||
|
||||
/*
|
||||
** Macro version of JS_CeilingLog2: Compute the log of the least power of
|
||||
** 2 greater than or equal to _n. The result is returned in _log2.
|
||||
*/
|
||||
#define JS_CEILING_LOG2(_log2,_n) \
|
||||
JS_BEGIN_MACRO \
|
||||
JSUint32 j_ = (JSUint32)(_n); \
|
||||
(_log2) = 0; \
|
||||
if ((j_) & ((j_)-1)) \
|
||||
(_log2) += 1; \
|
||||
if ((j_) >> 16) \
|
||||
(_log2) += 16, (j_) >>= 16; \
|
||||
if ((j_) >> 8) \
|
||||
(_log2) += 8, (j_) >>= 8; \
|
||||
if ((j_) >> 4) \
|
||||
(_log2) += 4, (j_) >>= 4; \
|
||||
if ((j_) >> 2) \
|
||||
(_log2) += 2, (j_) >>= 2; \
|
||||
if ((j_) >> 1) \
|
||||
(_log2) += 1; \
|
||||
JS_END_MACRO
|
||||
|
||||
/*
|
||||
** Macro version of JS_FloorLog2: Compute the log of the greatest power of
|
||||
** 2 less than or equal to _n. The result is returned in _log2.
|
||||
**
|
||||
** This is equivalent to finding the highest set bit in the word.
|
||||
*/
|
||||
#define JS_FLOOR_LOG2(_log2,_n) \
|
||||
JS_BEGIN_MACRO \
|
||||
JSUint32 j_ = (JSUint32)(_n); \
|
||||
(_log2) = 0; \
|
||||
if ((j_) >> 16) \
|
||||
(_log2) += 16, (j_) >>= 16; \
|
||||
if ((j_) >> 8) \
|
||||
(_log2) += 8, (j_) >>= 8; \
|
||||
if ((j_) >> 4) \
|
||||
(_log2) += 4, (j_) >>= 4; \
|
||||
if ((j_) >> 2) \
|
||||
(_log2) += 2, (j_) >>= 2; \
|
||||
if ((j_) >> 1) \
|
||||
(_log2) += 1; \
|
||||
JS_END_MACRO
|
||||
|
||||
JS_END_EXTERN_C
|
||||
#endif /* jsbit_h___ */
|
||||
222
mozilla/js/src/jsbool.c
Normal file
222
mozilla/js/src/jsbool.c
Normal file
@@ -0,0 +1,222 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* JS boolean implementation.
|
||||
*/
|
||||
#include "jsstddef.h"
|
||||
#include "jstypes.h"
|
||||
#include "jsutil.h" /* Added by JSIFY */
|
||||
#include "jsapi.h"
|
||||
#include "jsatom.h"
|
||||
#include "jsbool.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsconfig.h"
|
||||
#include "jsinterp.h"
|
||||
#include "jslock.h"
|
||||
#include "jsnum.h"
|
||||
#include "jsobj.h"
|
||||
#include "jsstr.h"
|
||||
|
||||
static JSClass boolean_class = {
|
||||
"Boolean",
|
||||
JSCLASS_HAS_PRIVATE,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
|
||||
};
|
||||
|
||||
#if JS_HAS_TOSOURCE
|
||||
#include "jsprf.h"
|
||||
|
||||
static JSBool
|
||||
bool_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
{
|
||||
jsval v;
|
||||
char buf[32];
|
||||
JSString *str;
|
||||
|
||||
if (!JS_InstanceOf(cx, obj, &boolean_class, argv))
|
||||
return JS_FALSE;
|
||||
v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
|
||||
if (!JSVAL_IS_BOOLEAN(v))
|
||||
return js_obj_toSource(cx, obj, argc, argv, rval);
|
||||
JS_snprintf(buf, sizeof buf, "(new %s(%s))",
|
||||
boolean_class.name,
|
||||
js_boolean_str[JSVAL_TO_BOOLEAN(v) ? 1 : 0]);
|
||||
str = JS_NewStringCopyZ(cx, buf);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
*rval = STRING_TO_JSVAL(str);
|
||||
return JS_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static JSBool
|
||||
bool_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
{
|
||||
jsval v;
|
||||
JSAtom *atom;
|
||||
JSString *str;
|
||||
|
||||
if (!JS_InstanceOf(cx, obj, &boolean_class, argv))
|
||||
return JS_FALSE;
|
||||
v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
|
||||
if (!JSVAL_IS_BOOLEAN(v))
|
||||
return js_obj_toString(cx, obj, argc, argv, rval);
|
||||
atom = cx->runtime->atomState.booleanAtoms[JSVAL_TO_BOOLEAN(v) ? 1 : 0];
|
||||
str = ATOM_TO_STRING(atom);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
*rval = STRING_TO_JSVAL(str);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
bool_valueOf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
if (!JS_InstanceOf(cx, obj, &boolean_class, argv))
|
||||
return JS_FALSE;
|
||||
*rval = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSFunctionSpec boolean_methods[] = {
|
||||
#if JS_HAS_TOSOURCE
|
||||
{js_toSource_str, bool_toSource, 0},
|
||||
#endif
|
||||
{js_toString_str, bool_toString, 0},
|
||||
{js_valueOf_str, bool_valueOf, 0},
|
||||
{0}
|
||||
};
|
||||
|
||||
#ifdef XP_MAC
|
||||
#undef Boolean
|
||||
#define Boolean js_Boolean
|
||||
#endif
|
||||
|
||||
static JSBool
|
||||
Boolean(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
JSBool b;
|
||||
jsval bval;
|
||||
|
||||
if (argc != 0) {
|
||||
if (!js_ValueToBoolean(cx, argv[0], &b))
|
||||
return JS_FALSE;
|
||||
bval = BOOLEAN_TO_JSVAL(b);
|
||||
} else {
|
||||
bval = JSVAL_FALSE;
|
||||
}
|
||||
if (!cx->fp->constructing) {
|
||||
*rval = bval;
|
||||
return JS_TRUE;
|
||||
}
|
||||
OBJ_SET_SLOT(cx, obj, JSSLOT_PRIVATE, bval);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSObject *
|
||||
js_InitBooleanClass(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JSObject *proto;
|
||||
|
||||
proto = JS_InitClass(cx, obj, NULL, &boolean_class, Boolean, 1,
|
||||
NULL, boolean_methods, NULL, NULL);
|
||||
if (!proto)
|
||||
return NULL;
|
||||
OBJ_SET_SLOT(cx, proto, JSSLOT_PRIVATE, JSVAL_FALSE);
|
||||
return proto;
|
||||
}
|
||||
|
||||
JSObject *
|
||||
js_BooleanToObject(JSContext *cx, JSBool b)
|
||||
{
|
||||
JSObject *obj;
|
||||
|
||||
obj = js_NewObject(cx, &boolean_class, NULL, NULL);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
OBJ_SET_SLOT(cx, obj, JSSLOT_PRIVATE, BOOLEAN_TO_JSVAL(b));
|
||||
return obj;
|
||||
}
|
||||
|
||||
JSString *
|
||||
js_BooleanToString(JSContext *cx, JSBool b)
|
||||
{
|
||||
return ATOM_TO_STRING(cx->runtime->atomState.booleanAtoms[b ? 1 : 0]);
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_ValueToBoolean(JSContext *cx, jsval v, JSBool *bp)
|
||||
{
|
||||
JSBool b;
|
||||
jsdouble d;
|
||||
|
||||
#if defined XP_PC && defined _MSC_VER && _MSC_VER <= 800
|
||||
/* MSVC1.5 coredumps */
|
||||
if (!bp)
|
||||
return JS_TRUE;
|
||||
/* This should be an if-else chain, but MSVC1.5 crashes if it is. */
|
||||
#define ELSE
|
||||
#else
|
||||
#define ELSE else
|
||||
#endif
|
||||
|
||||
if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v)) {
|
||||
/* Must return early to avoid falling thru to JSVAL_IS_OBJECT case. */
|
||||
*bp = JS_FALSE;
|
||||
return JS_TRUE;
|
||||
}
|
||||
if (JSVAL_IS_OBJECT(v)) {
|
||||
if (!JSVERSION_IS_ECMA(cx->version)) {
|
||||
if (!OBJ_DEFAULT_VALUE(cx, JSVAL_TO_OBJECT(v), JSTYPE_BOOLEAN, &v))
|
||||
return JS_FALSE;
|
||||
if (!JSVAL_IS_BOOLEAN(v))
|
||||
v = JSVAL_TRUE; /* non-null object is true */
|
||||
b = JSVAL_TO_BOOLEAN(v);
|
||||
} else {
|
||||
b = JS_TRUE;
|
||||
}
|
||||
} ELSE
|
||||
if (JSVAL_IS_STRING(v)) {
|
||||
b = JSVAL_TO_STRING(v)->length ? JS_TRUE : JS_FALSE;
|
||||
} ELSE
|
||||
if (JSVAL_IS_INT(v)) {
|
||||
b = JSVAL_TO_INT(v) ? JS_TRUE : JS_FALSE;
|
||||
} ELSE
|
||||
if (JSVAL_IS_DOUBLE(v)) {
|
||||
d = *JSVAL_TO_DOUBLE(v);
|
||||
b = (!JSDOUBLE_IS_NaN(d) && d != 0) ? JS_TRUE : JS_FALSE;
|
||||
} ELSE
|
||||
#if defined XP_PC && defined _MSC_VER && _MSC_VER <= 800
|
||||
if (JSVAL_IS_BOOLEAN(v)) {
|
||||
b = JSVAL_TO_BOOLEAN(v);
|
||||
}
|
||||
#else
|
||||
{
|
||||
JS_ASSERT(JSVAL_IS_BOOLEAN(v));
|
||||
b = JSVAL_TO_BOOLEAN(v);
|
||||
}
|
||||
#endif
|
||||
|
||||
#undef ELSE
|
||||
*bp = b;
|
||||
return JS_TRUE;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
@@ -16,10 +16,26 @@
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef __NS_JSWINREG_H__
|
||||
#define __NS_JSWINREG_H__
|
||||
#ifndef jsbool_h___
|
||||
#define jsbool_h___
|
||||
/*
|
||||
* JS boolean interface.
|
||||
*/
|
||||
|
||||
PRInt32
|
||||
InitWinRegPrototype(JSContext *jscontext, JSObject *global, JSObject **winRegPrototype);
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
#endif
|
||||
extern JSObject *
|
||||
js_InitBooleanClass(JSContext *cx, JSObject *obj);
|
||||
|
||||
extern JSObject *
|
||||
js_BooleanToObject(JSContext *cx, JSBool b);
|
||||
|
||||
extern JSString *
|
||||
js_BooleanToString(JSContext *cx, JSBool b);
|
||||
|
||||
extern JSBool
|
||||
js_ValueToBoolean(JSContext *cx, jsval v, JSBool *bp);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsbool_h___ */
|
||||
119
mozilla/js/src/jsclist.h
Normal file
119
mozilla/js/src/jsclist.h
Normal file
@@ -0,0 +1,119 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef jsclist_h___
|
||||
#define jsclist_h___
|
||||
|
||||
#include "jstypes.h"
|
||||
|
||||
/*
|
||||
** Circular linked list
|
||||
*/
|
||||
typedef struct JSCListStr {
|
||||
struct JSCListStr *next;
|
||||
struct JSCListStr *prev;
|
||||
} JSCList;
|
||||
|
||||
/*
|
||||
** Insert element "_e" into the list, before "_l".
|
||||
*/
|
||||
#define JS_INSERT_BEFORE(_e,_l) \
|
||||
JS_BEGIN_MACRO \
|
||||
(_e)->next = (_l); \
|
||||
(_e)->prev = (_l)->prev; \
|
||||
(_l)->prev->next = (_e); \
|
||||
(_l)->prev = (_e); \
|
||||
JS_END_MACRO
|
||||
|
||||
/*
|
||||
** Insert element "_e" into the list, after "_l".
|
||||
*/
|
||||
#define JS_INSERT_AFTER(_e,_l) \
|
||||
JS_BEGIN_MACRO \
|
||||
(_e)->next = (_l)->next; \
|
||||
(_e)->prev = (_l); \
|
||||
(_l)->next->prev = (_e); \
|
||||
(_l)->next = (_e); \
|
||||
JS_END_MACRO
|
||||
|
||||
/*
|
||||
** Return the element following element "_e"
|
||||
*/
|
||||
#define JS_NEXT_LINK(_e) \
|
||||
((_e)->next)
|
||||
/*
|
||||
** Return the element preceding element "_e"
|
||||
*/
|
||||
#define JS_PREV_LINK(_e) \
|
||||
((_e)->prev)
|
||||
|
||||
/*
|
||||
** Append an element "_e" to the end of the list "_l"
|
||||
*/
|
||||
#define JS_APPEND_LINK(_e,_l) JS_INSERT_BEFORE(_e,_l)
|
||||
|
||||
/*
|
||||
** Insert an element "_e" at the head of the list "_l"
|
||||
*/
|
||||
#define JS_INSERT_LINK(_e,_l) JS_INSERT_AFTER(_e,_l)
|
||||
|
||||
/* Return the head/tail of the list */
|
||||
#define JS_LIST_HEAD(_l) (_l)->next
|
||||
#define JS_LIST_TAIL(_l) (_l)->prev
|
||||
|
||||
/*
|
||||
** Remove the element "_e" from it's circular list.
|
||||
*/
|
||||
#define JS_REMOVE_LINK(_e) \
|
||||
JS_BEGIN_MACRO \
|
||||
(_e)->prev->next = (_e)->next; \
|
||||
(_e)->next->prev = (_e)->prev; \
|
||||
JS_END_MACRO
|
||||
|
||||
/*
|
||||
** Remove the element "_e" from it's circular list. Also initializes the
|
||||
** linkage.
|
||||
*/
|
||||
#define JS_REMOVE_AND_INIT_LINK(_e) \
|
||||
JS_BEGIN_MACRO \
|
||||
(_e)->prev->next = (_e)->next; \
|
||||
(_e)->next->prev = (_e)->prev; \
|
||||
(_e)->next = (_e); \
|
||||
(_e)->prev = (_e); \
|
||||
JS_END_MACRO
|
||||
|
||||
/*
|
||||
** Return non-zero if the given circular list "_l" is empty, zero if the
|
||||
** circular list is not empty
|
||||
*/
|
||||
#define JS_CLIST_IS_EMPTY(_l) \
|
||||
((_l)->next == (_l))
|
||||
|
||||
/*
|
||||
** Initialize a circular list
|
||||
*/
|
||||
#define JS_INIT_CLIST(_l) \
|
||||
JS_BEGIN_MACRO \
|
||||
(_l)->next = (_l); \
|
||||
(_l)->prev = (_l); \
|
||||
JS_END_MACRO
|
||||
|
||||
#define JS_INIT_STATIC_CLIST(_l) \
|
||||
{(_l), (_l)}
|
||||
|
||||
#endif /* jsclist_h___ */
|
||||
455
mozilla/js/src/jscntxt.c
Normal file
455
mozilla/js/src/jscntxt.c
Normal file
@@ -0,0 +1,455 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* JS execution context.
|
||||
*/
|
||||
#include "jsstddef.h"
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "jstypes.h"
|
||||
#include "jsarena.h" /* Added by JSIFY */
|
||||
#include "jsutil.h" /* Added by JSIFY */
|
||||
#include "jsclist.h"
|
||||
#include "jsprf.h"
|
||||
#include "jsatom.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsconfig.h"
|
||||
#include "jsdbgapi.h"
|
||||
#include "jsexn.h"
|
||||
#include "jsgc.h"
|
||||
#include "jslock.h"
|
||||
#include "jsobj.h"
|
||||
#include "jsopcode.h"
|
||||
#include "jsscan.h"
|
||||
#include "jsscript.h"
|
||||
|
||||
JSContext *
|
||||
js_NewContext(JSRuntime *rt, size_t stacksize)
|
||||
{
|
||||
JSContext *cx;
|
||||
|
||||
cx = malloc(sizeof *cx);
|
||||
if (!cx)
|
||||
return NULL;
|
||||
memset(cx, 0, sizeof *cx);
|
||||
|
||||
cx->runtime = rt;
|
||||
#ifdef JS_THREADSAFE
|
||||
js_InitContextForLocking(cx);
|
||||
#endif
|
||||
if (rt->contextList.next == (JSCList *)&rt->contextList) {
|
||||
/* First context on this runtime: initialize atoms and keywords. */
|
||||
if (!js_InitAtomState(cx, &rt->atomState) ||
|
||||
!js_InitScanner(cx)) {
|
||||
free(cx);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
/* Atomicly append cx to rt's context list. */
|
||||
JS_LOCK_RUNTIME_VOID(rt, JS_APPEND_LINK(&cx->links, &rt->contextList));
|
||||
|
||||
cx->version = JSVERSION_DEFAULT;
|
||||
cx->jsop_eq = JSOP_EQ;
|
||||
cx->jsop_ne = JSOP_NE;
|
||||
JS_InitArenaPool(&cx->stackPool, "stack", stacksize, sizeof(jsval));
|
||||
JS_InitArenaPool(&cx->codePool, "code", 1024, sizeof(jsbytecode));
|
||||
JS_InitArenaPool(&cx->tempPool, "temp", 1024, sizeof(jsdouble));
|
||||
|
||||
#if JS_HAS_REGEXPS
|
||||
if (!js_InitRegExpStatics(cx, &cx->regExpStatics)) {
|
||||
js_DestroyContext(cx);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
#if JS_HAS_EXCEPTIONS
|
||||
cx->throwing = JS_FALSE;
|
||||
#endif
|
||||
|
||||
return cx;
|
||||
}
|
||||
|
||||
void
|
||||
js_DestroyContext(JSContext *cx)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
JSBool rtempty;
|
||||
|
||||
rt = cx->runtime;
|
||||
|
||||
/* Remove cx from context list first. */
|
||||
JS_LOCK_RUNTIME(rt);
|
||||
JS_REMOVE_LINK(&cx->links);
|
||||
rtempty = (rt->contextList.next == (JSCList *)&rt->contextList);
|
||||
JS_UNLOCK_RUNTIME(rt);
|
||||
|
||||
if (rtempty) {
|
||||
/* Unpin all pinned atoms before final GC. */
|
||||
js_UnpinPinnedAtoms(&rt->atomState);
|
||||
|
||||
/* Unlock GC things held by runtime pointers. */
|
||||
js_UnlockGCThing(cx, rt->jsNaN);
|
||||
js_UnlockGCThing(cx, rt->jsNegativeInfinity);
|
||||
js_UnlockGCThing(cx, rt->jsPositiveInfinity);
|
||||
js_UnlockGCThing(cx, rt->emptyString);
|
||||
|
||||
/*
|
||||
* Clear these so they get recreated if the standard classes are
|
||||
* initialized again.
|
||||
*/
|
||||
rt->jsNaN = NULL;
|
||||
rt->jsNegativeInfinity = NULL;
|
||||
rt->jsPositiveInfinity = NULL;
|
||||
rt->emptyString = NULL;
|
||||
|
||||
/* Clear debugging state to remove GC roots. */
|
||||
JS_ClearAllTraps(cx);
|
||||
JS_ClearAllWatchPoints(cx);
|
||||
}
|
||||
|
||||
/* Remove more GC roots in regExpStatics, then collect garbage. */
|
||||
#if JS_HAS_REGEXPS
|
||||
js_FreeRegExpStatics(cx, &cx->regExpStatics);
|
||||
#endif
|
||||
js_ForceGC(cx);
|
||||
|
||||
if (rtempty) {
|
||||
/* Free atom state now that we've run the GC. */
|
||||
js_FreeAtomState(cx, &rt->atomState);
|
||||
}
|
||||
|
||||
/* Free the stuff hanging off of cx. */
|
||||
JS_FinishArenaPool(&cx->stackPool);
|
||||
JS_FinishArenaPool(&cx->codePool);
|
||||
JS_FinishArenaPool(&cx->tempPool);
|
||||
if (cx->lastMessage)
|
||||
free(cx->lastMessage);
|
||||
free(cx);
|
||||
}
|
||||
|
||||
JSContext *
|
||||
js_ContextIterator(JSRuntime *rt, JSContext **iterp)
|
||||
{
|
||||
JSContext *cx = *iterp;
|
||||
|
||||
JS_LOCK_RUNTIME(rt);
|
||||
if (!cx)
|
||||
cx = (JSContext *)rt->contextList.next;
|
||||
if ((void *)cx == &rt->contextList)
|
||||
cx = NULL;
|
||||
else
|
||||
*iterp = (JSContext *)cx->links.next;
|
||||
JS_UNLOCK_RUNTIME(rt);
|
||||
return cx;
|
||||
}
|
||||
|
||||
void
|
||||
js_ReportErrorVA(JSContext *cx, uintN flags, const char *format, va_list ap)
|
||||
{
|
||||
JSStackFrame *fp;
|
||||
JSErrorReport report, *reportp;
|
||||
char *last;
|
||||
|
||||
fp = cx->fp;
|
||||
if (fp && fp->script && fp->pc) {
|
||||
report.filename = fp->script->filename;
|
||||
report.lineno = js_PCToLineNumber(fp->script, fp->pc);
|
||||
/* XXX should fetch line somehow */
|
||||
report.linebuf = NULL;
|
||||
report.tokenptr = NULL;
|
||||
report.flags = flags;
|
||||
reportp = &report;
|
||||
} else {
|
||||
/* XXXshaver still fill out report here for flags? */
|
||||
reportp = NULL;
|
||||
}
|
||||
last = JS_vsmprintf(format, ap);
|
||||
if (!last)
|
||||
return;
|
||||
|
||||
js_ReportErrorAgain(cx, last, reportp);
|
||||
free(last);
|
||||
}
|
||||
|
||||
/*
|
||||
* The arguments from ap need to be packaged up into an array and stored
|
||||
* into the report struct.
|
||||
*
|
||||
* The format string addressed by the error number may contain operands
|
||||
* identified by the format {N}, where N is a decimal digit. Each of these
|
||||
* is to be replaced by the Nth argument from the va_list. The complete
|
||||
* message is placed into reportp->ucmessage converted to a JSString.
|
||||
*
|
||||
* returns true/false if the expansion succeeds (can fail for memory errors)
|
||||
*/
|
||||
JSBool
|
||||
js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback,
|
||||
void *userRef, const uintN errorNumber,
|
||||
char **messagep, JSErrorReport *reportp,
|
||||
JSBool charArgs, va_list ap)
|
||||
{
|
||||
const JSErrorFormatString *fmtData;
|
||||
int i;
|
||||
int argCount;
|
||||
|
||||
*messagep = NULL;
|
||||
if (callback) {
|
||||
fmtData = (*callback)(userRef, "Mountain View", errorNumber);
|
||||
if (fmtData != NULL) {
|
||||
int totalArgsLength = 0;
|
||||
int argLengths[10]; /* only {0} thru {9} supported */
|
||||
argCount = fmtData->argCount;
|
||||
JS_ASSERT(argCount <= 10);
|
||||
if (argCount > 0) {
|
||||
/*
|
||||
* Gather the arguments into an array, and accumulate
|
||||
* their sizes. We allocate 1 more than necessary and
|
||||
* null it out to act as the caboose when we free the
|
||||
* pointers later.
|
||||
*/
|
||||
reportp->messageArgs
|
||||
= JS_malloc(cx, sizeof(jschar *) * (argCount + 1));
|
||||
if (!reportp->messageArgs)
|
||||
return JS_FALSE;
|
||||
reportp->messageArgs[argCount] = NULL;
|
||||
for (i = 0; i < argCount; i++) {
|
||||
if (charArgs) {
|
||||
char *charArg = va_arg(ap, char *);
|
||||
reportp->messageArgs[i]
|
||||
= js_InflateString(cx, charArg, strlen(charArg));
|
||||
}
|
||||
else
|
||||
reportp->messageArgs[i] = va_arg(ap, jschar *);
|
||||
argLengths[i] = js_strlen(reportp->messageArgs[i]);
|
||||
totalArgsLength += argLengths[i];
|
||||
}
|
||||
/* NULL-terminate for easy copying. */
|
||||
reportp->messageArgs[i] = NULL;
|
||||
}
|
||||
/*
|
||||
* Parse the error format, substituting the argument X
|
||||
* for {X} in the format.
|
||||
*/
|
||||
if (argCount > 0) {
|
||||
if (fmtData->format) {
|
||||
const char *fmt;
|
||||
const jschar *arg;
|
||||
jschar *out;
|
||||
int expandedArgs = 0;
|
||||
int expandedLength
|
||||
= strlen(fmtData->format)
|
||||
- (3 * argCount) /* exclude the {n} */
|
||||
+ totalArgsLength;
|
||||
/* Note - the above calculation assumes that each argument
|
||||
* is used once and only once in the expansion !!!
|
||||
*/
|
||||
reportp->ucmessage = out
|
||||
= JS_malloc(cx, (expandedLength + 1) * sizeof(jschar));
|
||||
if (!out) {
|
||||
if (reportp->messageArgs) {
|
||||
JS_free(cx, (void *)reportp->messageArgs);
|
||||
reportp->messageArgs = NULL;
|
||||
}
|
||||
return JS_FALSE;
|
||||
}
|
||||
fmt = fmtData->format;
|
||||
while (*fmt) {
|
||||
if (*fmt == '{') { /* balance} */
|
||||
if (isdigit(fmt[1])) {
|
||||
int d = JS7_UNDEC(fmt[1]);
|
||||
JS_ASSERT(expandedArgs < argCount);
|
||||
arg = reportp->messageArgs[d];
|
||||
js_strncpy(out, arg, argLengths[d]);
|
||||
out += argLengths[d];
|
||||
fmt += 3;
|
||||
expandedArgs++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* is this kosher?
|
||||
*/
|
||||
*out++ = (unsigned char)(*fmt++);
|
||||
}
|
||||
JS_ASSERT(expandedArgs == argCount);
|
||||
*out = 0;
|
||||
*messagep = js_DeflateString(cx, reportp->ucmessage,
|
||||
out - reportp->ucmessage);
|
||||
}
|
||||
} else { /* 0 arguments, the format string
|
||||
(if it exists) is the entire message */
|
||||
if (fmtData->format) {
|
||||
*messagep = JS_strdup(cx, fmtData->format);
|
||||
reportp->ucmessage
|
||||
= js_InflateString(cx, *messagep, strlen(*messagep));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (*messagep == NULL) {
|
||||
/* where's the right place for this ??? */
|
||||
const char *defaultErrorMessage
|
||||
= "No error message available for error number %d";
|
||||
size_t nbytes = strlen(defaultErrorMessage) + 16;
|
||||
*messagep = (char *)JS_malloc(cx, nbytes);
|
||||
JS_snprintf(*messagep, nbytes, defaultErrorMessage, errorNumber);
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
js_ReportErrorNumberVA(JSContext *cx, uintN flags, JSErrorCallback callback,
|
||||
void *userRef, const uintN errorNumber,
|
||||
JSBool charArgs, va_list ap)
|
||||
{
|
||||
JSStackFrame *fp;
|
||||
JSErrorReport report;
|
||||
char *message;
|
||||
|
||||
report.messageArgs = NULL;
|
||||
report.ucmessage = NULL;
|
||||
message = NULL;
|
||||
|
||||
fp = cx->fp;
|
||||
if (fp && fp->script && fp->pc) {
|
||||
report.filename = fp->script->filename;
|
||||
report.lineno = js_PCToLineNumber(fp->script, fp->pc);
|
||||
} else {
|
||||
report.filename = NULL;
|
||||
report.lineno = 0;
|
||||
}
|
||||
|
||||
/* XXX should fetch line somehow */
|
||||
report.linebuf = NULL;
|
||||
report.tokenptr = NULL;
|
||||
report.flags = flags;
|
||||
report.errorNumber = errorNumber;
|
||||
|
||||
if (!js_ExpandErrorArguments(cx, callback, userRef, errorNumber,
|
||||
&message, &report, charArgs, ap))
|
||||
return;
|
||||
|
||||
#if JS_HAS_ERROR_EXCEPTIONS
|
||||
/*
|
||||
* Check the error report, and set a JavaScript-catchable exception
|
||||
* if the error is defined to have an associated exception. If an
|
||||
* exception is thrown, then the JSREPORT_EXCEPTION flag will be set
|
||||
* on the error report, and exception-aware hosts should ignore it.
|
||||
|
||||
* We set the JSREPORT_EXCEPTION flag for the special case of
|
||||
* user-thrown exeptions.
|
||||
*/
|
||||
if (errorNumber == JSMSG_UNCAUGHT_EXCEPTION)
|
||||
report.flags |= JSREPORT_EXCEPTION;
|
||||
|
||||
/*
|
||||
* Only call the error reporter if an exception wasn't raised.
|
||||
*
|
||||
* If an exception was raised, then we call the debugErrorHook
|
||||
* (if present) to give it a chance to see the error before it
|
||||
* propigates out of scope. This is needed for compatability with
|
||||
* the old scheme.
|
||||
*/
|
||||
if (!js_ErrorToException(cx, message, &report))
|
||||
js_ReportErrorAgain(cx, message, &report);
|
||||
else if (cx->runtime->debugErrorHook && cx->errorReporter) {
|
||||
JSDebugErrorHook hook = cx->runtime->debugErrorHook;
|
||||
/* test local in case debugErrorHook changed on another thread */
|
||||
if (hook)
|
||||
hook(cx, message, &report, cx->runtime->debugErrorHookData);
|
||||
}
|
||||
#else
|
||||
js_ReportErrorAgain(cx, message, &report);
|
||||
#endif
|
||||
|
||||
if (message)
|
||||
JS_free(cx, message);
|
||||
if (report.messageArgs) {
|
||||
int i = 0;
|
||||
while (report.messageArgs[i])
|
||||
JS_free(cx, (void *)report.messageArgs[i++]);
|
||||
JS_free(cx, (void *)report.messageArgs);
|
||||
}
|
||||
if (report.ucmessage)
|
||||
JS_free(cx, (void *)report.ucmessage);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
js_ReportErrorAgain(JSContext *cx, const char *message, JSErrorReport *reportp)
|
||||
{
|
||||
JSErrorReporter onError;
|
||||
|
||||
if (!message)
|
||||
return;
|
||||
if (cx->lastMessage)
|
||||
free(cx->lastMessage);
|
||||
cx->lastMessage = JS_strdup(cx, message);
|
||||
if (!cx->lastMessage)
|
||||
return;
|
||||
onError = cx->errorReporter;
|
||||
/*
|
||||
* If debugErrorHook is present then we give it a chance to veto
|
||||
* sending the error on to the regular ErrorReporter.
|
||||
*/
|
||||
if (cx->runtime->debugErrorHook && onError) {
|
||||
JSDebugErrorHook hook = cx->runtime->debugErrorHook;
|
||||
/* test local in case debugErrorHook changed on another thread */
|
||||
if (hook && !hook(cx, message, reportp,
|
||||
cx->runtime->debugErrorHookData)) {
|
||||
onError = NULL;
|
||||
}
|
||||
}
|
||||
if (onError)
|
||||
(*onError)(cx, cx->lastMessage, reportp);
|
||||
}
|
||||
|
||||
void
|
||||
js_ReportIsNotDefined(JSContext *cx, const char *name)
|
||||
{
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_DEFINED, name);
|
||||
}
|
||||
|
||||
#if defined DEBUG && defined XP_UNIX
|
||||
/* For gdb usage. */
|
||||
void js_traceon(JSContext *cx) { cx->tracefp = stderr; }
|
||||
void js_traceoff(JSContext *cx) { cx->tracefp = NULL; }
|
||||
#endif
|
||||
|
||||
|
||||
JSErrorFormatString js_ErrorFormatString[JSErr_Limit] = {
|
||||
#if JS_HAS_DFLT_MSG_STRINGS
|
||||
#define MSG_DEF(name, number, count, exception, format) \
|
||||
{ format, count } ,
|
||||
#else
|
||||
#define MSG_DEF(name, number, count, exception, format) \
|
||||
{ NULL, count } ,
|
||||
#endif
|
||||
#include "js.msg"
|
||||
#undef MSG_DEF
|
||||
};
|
||||
|
||||
const JSErrorFormatString *
|
||||
js_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber)
|
||||
{
|
||||
if ((errorNumber > 0) && (errorNumber < JSErr_Limit))
|
||||
return &js_ErrorFormatString[errorNumber];
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
232
mozilla/js/src/jscntxt.h
Normal file
232
mozilla/js/src/jscntxt.h
Normal file
@@ -0,0 +1,232 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef jscntxt_h___
|
||||
#define jscntxt_h___
|
||||
/*
|
||||
* JS execution context.
|
||||
*/
|
||||
#include "jsarena.h" /* Added by JSIFY */
|
||||
#include "jsclist.h"
|
||||
#include "jslong.h"
|
||||
#include "jsatom.h"
|
||||
#include "jsconfig.h"
|
||||
#include "jsgc.h"
|
||||
#include "jsinterp.h"
|
||||
#include "jsobj.h"
|
||||
#include "jsprvtd.h"
|
||||
#include "jspubtd.h"
|
||||
#include "jsregexp.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
struct JSRuntime {
|
||||
/* Garbage collector state, used by jsgc.c. */
|
||||
JSArenaPool gcArenaPool;
|
||||
JSArenaPool gcFlagsPool;
|
||||
JSHashTable *gcRootsHash;
|
||||
JSGCThing *gcFreeList;
|
||||
uint32 gcBytes;
|
||||
uint32 gcLastBytes;
|
||||
uint32 gcMaxBytes;
|
||||
uint32 gcLevel;
|
||||
uint32 gcNumber;
|
||||
JSBool gcPoke;
|
||||
JSGCCallback gcCallback;
|
||||
#ifdef JS_GCMETER
|
||||
JSGCStats gcStats;
|
||||
#endif
|
||||
|
||||
/* Literal table maintained by jsatom.c functions. */
|
||||
JSAtomState atomState;
|
||||
|
||||
/* Random number generator state, used by jsmath.c. */
|
||||
JSBool rngInitialized;
|
||||
int64 rngMultiplier;
|
||||
int64 rngAddend;
|
||||
int64 rngMask;
|
||||
int64 rngSeed;
|
||||
jsdouble rngDscale;
|
||||
|
||||
/* Well-known numbers held for use by this runtime's contexts. */
|
||||
jsdouble *jsNaN;
|
||||
jsdouble *jsNegativeInfinity;
|
||||
jsdouble *jsPositiveInfinity;
|
||||
|
||||
/* Empty string held for use by this runtime's contexts. */
|
||||
JSString *emptyString;
|
||||
|
||||
/* List of active contexts sharing this runtime. */
|
||||
JSCList contextList;
|
||||
|
||||
/* These are used for debugging -- see jsprvtd.h and jsdbgapi.h. */
|
||||
JSTrapHandler interruptHandler;
|
||||
void *interruptHandlerData;
|
||||
JSNewScriptHook newScriptHook;
|
||||
void *newScriptHookData;
|
||||
JSDestroyScriptHook destroyScriptHook;
|
||||
void *destroyScriptHookData;
|
||||
JSTrapHandler debuggerHandler;
|
||||
void *debuggerHandlerData;
|
||||
JSSourceHandler sourceHandler;
|
||||
void *sourceHandlerData;
|
||||
JSInterpreterHook executeHook;
|
||||
void *executeHookData;
|
||||
JSInterpreterHook callHook;
|
||||
void *callHookData;
|
||||
JSObjectHook objectHook;
|
||||
void *objectHookData;
|
||||
JSTrapHandler throwHook;
|
||||
void *throwHookData;
|
||||
JSDebugErrorHook debugErrorHook;
|
||||
void *debugErrorHookData;
|
||||
|
||||
/* More debugging state, see jsdbgapi.c. */
|
||||
JSCList trapList;
|
||||
JSCList watchPointList;
|
||||
|
||||
/* Weak links to properties, indexed by quickened get/set opcodes. */
|
||||
/* XXX must come after JSCLists or MSVC alignment bug bites empty lists */
|
||||
JSPropertyCache propertyCache;
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
/* These combine to interlock the GC and new requests. */
|
||||
PRLock *gcLock;
|
||||
PRCondVar *gcDone;
|
||||
PRCondVar *requestDone;
|
||||
uint32 requestCount;
|
||||
|
||||
/* Lock and owning thread pointer for JS_LOCK_RUNTIME. */
|
||||
JSThinLock rtLock;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct JSContext {
|
||||
JSCList links;
|
||||
|
||||
/* Interpreter activation count. */
|
||||
uintN interpLevel;
|
||||
|
||||
/* Runtime version control identifier and equality operators. */
|
||||
JSVersion version;
|
||||
jsbytecode jsop_eq;
|
||||
jsbytecode jsop_ne;
|
||||
|
||||
/* Data shared by threads in an address space. */
|
||||
JSRuntime *runtime;
|
||||
|
||||
/* Stack arena pool and frame pointer register. */
|
||||
JSArenaPool stackPool;
|
||||
JSStackFrame *fp;
|
||||
|
||||
/* Temporary arena pools used while compiling and decompiling. */
|
||||
JSArenaPool codePool;
|
||||
JSArenaPool tempPool;
|
||||
|
||||
/* Top-level object and pointer to top stack frame's scope chain. */
|
||||
JSObject *globalObject;
|
||||
|
||||
/* Most recently created things by type, members of the GC's root set. */
|
||||
JSGCThing *newborn[GCX_NTYPES];
|
||||
|
||||
/* Regular expression class statics (XXX not shared globally). */
|
||||
JSRegExpStatics regExpStatics;
|
||||
|
||||
/* State for object and array toSource conversion. */
|
||||
JSSharpObjectMap sharpObjectMap;
|
||||
|
||||
/* Last message string and trace file for debugging. */
|
||||
char *lastMessage;
|
||||
#ifdef DEBUG
|
||||
void *tracefp;
|
||||
#endif
|
||||
|
||||
/* Per-context optional user callbacks. */
|
||||
JSBranchCallback branchCallback;
|
||||
JSErrorReporter errorReporter;
|
||||
|
||||
/* Client opaque pointer */
|
||||
void *data;
|
||||
|
||||
/* GC and thread-safe state. */
|
||||
JSStackFrame *dormantFrameChain; /* dormant stack frame to scan */
|
||||
uint32 gcDisabled; /* XXX for pre-ECMAv2 switch */
|
||||
#ifdef JS_THREADSAFE
|
||||
jsword thread;
|
||||
jsrefcount requestDepth;
|
||||
JSPackedBool gcActive;
|
||||
#endif
|
||||
|
||||
/* Exception state (NB: throwing is packed with gcActive above). */
|
||||
JSPackedBool throwing; /* is there a pending exception? */
|
||||
jsval exception; /* most-recently-thrown exceptin */
|
||||
};
|
||||
|
||||
extern JSContext *
|
||||
js_NewContext(JSRuntime *rt, size_t stacksize);
|
||||
|
||||
extern void
|
||||
js_DestroyContext(JSContext *cx);
|
||||
|
||||
extern JSContext *
|
||||
js_ContextIterator(JSRuntime *rt, JSContext **iterp);
|
||||
|
||||
/*
|
||||
* Report an exception, which is currently realized as a printf-style format
|
||||
* string and its arguments.
|
||||
*/
|
||||
typedef enum JSErrNum {
|
||||
#define MSG_DEF(name, number, count, exception, format) \
|
||||
name = number,
|
||||
#include "js.msg"
|
||||
#undef MSG_DEF
|
||||
JSErr_Limit
|
||||
} JSErrNum;
|
||||
|
||||
extern const JSErrorFormatString *
|
||||
js_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber);
|
||||
|
||||
#ifdef va_start
|
||||
extern void
|
||||
js_ReportErrorVA(JSContext *cx, uintN flags, const char *format, va_list ap);
|
||||
extern void
|
||||
js_ReportErrorNumberVA(JSContext *cx, uintN flags, JSErrorCallback callback,
|
||||
void *userRef, const uintN errorNumber,
|
||||
JSBool charArgs, va_list ap);
|
||||
|
||||
extern JSBool
|
||||
js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback,
|
||||
void *userRef, const uintN errorNumber,
|
||||
char **message, JSErrorReport *reportp,
|
||||
JSBool charArgs, va_list ap);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Report an exception using a previously composed JSErrorReport.
|
||||
*/
|
||||
extern JS_FRIEND_API(void)
|
||||
js_ReportErrorAgain(JSContext *cx, const char *message, JSErrorReport *report);
|
||||
|
||||
extern void
|
||||
js_ReportIsNotDefined(JSContext *cx, const char *name);
|
||||
|
||||
extern JSErrorFormatString js_ErrorFormatString[JSErr_Limit];
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jscntxt_h___ */
|
||||
20
mozilla/js/src/jscompat.h
Normal file
20
mozilla/js/src/jscompat.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/* -*- Mode: C; tab-width: 8 -*-
|
||||
* Copyright © 1996 Netscape Communications Corporation, All Rights Reserved.
|
||||
*/
|
||||
#ifndef jscompat_h___
|
||||
#define jscompat_h___
|
||||
/*
|
||||
* Compatibility glue for various NSPR versions. We must always define int8,
|
||||
* int16, jsword, and so on to minimize differences with js/ref, no matter what
|
||||
* the NSPR typedef names may be.
|
||||
*/
|
||||
#include "jstypes.h"
|
||||
#include "jslong.h"
|
||||
|
||||
typedef JSIntn intN;
|
||||
typedef JSUintn uintN;
|
||||
typedef JSUword jsuword;
|
||||
typedef JSWord jsword;
|
||||
typedef float float32;
|
||||
#define allocPriv allocPool
|
||||
#endif /* jscompat_h___ */
|
||||
277
mozilla/js/src/jsconfig.h
Normal file
277
mozilla/js/src/jsconfig.h
Normal file
@@ -0,0 +1,277 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* JS configuration macros.
|
||||
*/
|
||||
#ifndef JS_VERSION
|
||||
#define JS_VERSION 140
|
||||
#endif
|
||||
|
||||
#if JS_VERSION == 100
|
||||
|
||||
#define JS_BUG_AUTO_INDEX_PROPS 1 /* new object o: o.p = v sets o[0] */
|
||||
#define JS_BUG_NULL_INDEX_PROPS 1 /* o[0] defaults to null, not void */
|
||||
#define JS_BUG_EMPTY_INDEX_ZERO 1 /* o[""] is equivalent to o[0] */
|
||||
#define JS_BUG_SHORT_CIRCUIT 1 /* 1 && 1 => true, 1 && 0 => 0 bug */
|
||||
#define JS_BUG_EAGER_TOSTRING 1 /* o.toString() trumps o.valueOf() */
|
||||
#define JS_BUG_VOID_TOSTRING 0 /* void 0 + 0 == "undefined0" */
|
||||
#define JS_BUG_EVAL_THIS_FUN 0 /* eval('this') in function f is f */
|
||||
#define JS_BUG_EVAL_THIS_SCOPE 0 /* Math.eval('sin(x)') vs. local x */
|
||||
#define JS_BUG_FALLIBLE_EQOPS 1 /* fallible/intransitive equality ops */
|
||||
#define JS_BUG_FALLIBLE_TONUM 1 /* fallible ValueToNumber primitive */
|
||||
#define JS_BUG_WITH_CLOSURE 0 /* with(o)function f(){} sets o.f */
|
||||
#define JS_BUG_SET_ENUMERATE 1 /* o.p=q flags o.p JSPROP_ENUMERATE */
|
||||
|
||||
#define JS_HAS_PROP_DELETE 0 /* delete o.p removes p from o */
|
||||
#define JS_HAS_CALL_OBJECT 0 /* fun.caller is stack frame obj */
|
||||
#define JS_HAS_LABEL_STATEMENT 0 /* has break/continue to label: */
|
||||
#define JS_HAS_DO_WHILE_LOOP 0 /* has do {...} while (b) */
|
||||
#define JS_HAS_SWITCH_STATEMENT 0 /* has switch (v) {case c: ...} */
|
||||
#define JS_HAS_SOME_PERL_FUN 0 /* has array.join/reverse/sort */
|
||||
#define JS_HAS_MORE_PERL_FUN 0 /* has array.push, str.substr, etc */
|
||||
#define JS_HAS_VALUEOF_HINT 0 /* valueOf(hint) where hint is typeof */
|
||||
#define JS_HAS_LEXICAL_CLOSURE 0 /* nested functions, lexically closed */
|
||||
#define JS_HAS_APPLY_FUNCTION 0 /* has fun.apply(obj, argArray) */
|
||||
#define JS_HAS_CALL_FUNCTION 0 /* has fun.call(obj, arg1, ... argN) */
|
||||
#define JS_HAS_OBJ_PROTO_PROP 0 /* has o.__proto__ etc. */
|
||||
#define JS_HAS_REGEXPS 0 /* has perl r.e.s via RegExp, /pat/ */
|
||||
#define JS_HAS_SEQUENCE_OPS 0 /* has array.slice, string.concat */
|
||||
#define JS_HAS_INITIALIZERS 0 /* has var o = {'foo': 42, 'bar':3} */
|
||||
#define JS_HAS_OBJ_WATCHPOINT 0 /* has o.watch and o.unwatch */
|
||||
#define JS_HAS_EXPORT_IMPORT 0 /* has export fun; import obj.fun */
|
||||
#define JS_HAS_EVAL_THIS_SCOPE 0 /* Math.eval is same as with (Math) */
|
||||
#define JS_HAS_TRIPLE_EQOPS 0 /* has === and !== identity eqops */
|
||||
#define JS_HAS_SHARP_VARS 0 /* has #n=, #n# for object literals */
|
||||
#define JS_HAS_REPLACE_LAMBDA 0 /* has string.replace(re, lambda) */
|
||||
#define JS_HAS_SCRIPT_OBJECT 0 /* has (new Script("x++")).exec() */
|
||||
#define JS_HAS_XDR 0 /* has XDR API and object methods */
|
||||
#define JS_HAS_EXCEPTIONS 0 /* has exception handling */
|
||||
#define JS_HAS_UNDEFINED 0 /* has global "undefined" property */
|
||||
#define JS_HAS_TOSOURCE 0 /* has Object/Array toSource method */
|
||||
#define JS_HAS_IN_OPERATOR 0 /* has in operator ('p' in {p:1}) */
|
||||
#define JS_HAS_INSTANCEOF 0 /* has {p:1} instanceof Object */
|
||||
#define JS_HAS_ARGS_OBJECT 0 /* has minimal ECMA arguments object */
|
||||
#define JS_HAS_DEBUGGER_KEYWORD 0 /* has hook for debugger keyword */
|
||||
#define JS_HAS_ERROR_EXCEPTIONS 0 /* has error object hierarchy */
|
||||
#define JS_HAS_CATCH_GUARD 0 /* has exception handling catch guard */
|
||||
#define JS_HAS_NEW_OBJ_METHODS 0 /* has Object.prototype query methods */
|
||||
|
||||
#elif JS_VERSION == 110
|
||||
|
||||
#define JS_BUG_AUTO_INDEX_PROPS 0 /* new object o: o.p = v sets o[0] */
|
||||
#define JS_BUG_NULL_INDEX_PROPS 1 /* o[0] defaults to null, not void */
|
||||
#define JS_BUG_EMPTY_INDEX_ZERO 1 /* o[""] is equivalent to o[0] */
|
||||
#define JS_BUG_SHORT_CIRCUIT 1 /* 1 && 1 => true, 1 && 0 => 0 bug */
|
||||
#define JS_BUG_EAGER_TOSTRING 1 /* o.toString() trumps o.valueOf() */
|
||||
#define JS_BUG_VOID_TOSTRING 0 /* void 0 + 0 == "undefined0" */
|
||||
#define JS_BUG_EVAL_THIS_FUN 1 /* eval('this') in function f is f */
|
||||
#define JS_BUG_EVAL_THIS_SCOPE 1 /* Math.eval('sin(x)') vs. local x */
|
||||
#define JS_BUG_FALLIBLE_EQOPS 1 /* fallible/intransitive equality ops */
|
||||
#define JS_BUG_FALLIBLE_TONUM 1 /* fallible ValueToNumber primitive */
|
||||
#define JS_BUG_WITH_CLOSURE 0 /* with(o)function f(){} sets o.f */
|
||||
#define JS_BUG_SET_ENUMERATE 1 /* o.p=q flags o.p JSPROP_ENUMERATE */
|
||||
|
||||
#define JS_HAS_PROP_DELETE 0 /* delete o.p removes p from o */
|
||||
#define JS_HAS_CALL_OBJECT 0 /* fun.caller is stack frame obj */
|
||||
#define JS_HAS_LABEL_STATEMENT 0 /* has break/continue to label: */
|
||||
#define JS_HAS_DO_WHILE_LOOP 0 /* has do {...} while (b) */
|
||||
#define JS_HAS_SWITCH_STATEMENT 0 /* has switch (v) {case c: ...} */
|
||||
#define JS_HAS_SOME_PERL_FUN 1 /* has array.join/reverse/sort */
|
||||
#define JS_HAS_MORE_PERL_FUN 0 /* has array.push, str.substr, etc */
|
||||
#define JS_HAS_VALUEOF_HINT 0 /* valueOf(hint) where hint is typeof */
|
||||
#define JS_HAS_LEXICAL_CLOSURE 0 /* nested functions, lexically closed */
|
||||
#define JS_HAS_APPLY_FUNCTION 0 /* has apply(fun, arg1, ... argN) */
|
||||
#define JS_HAS_CALL_FUNCTION 0 /* has fun.call(obj, arg1, ... argN) */
|
||||
#define JS_HAS_OBJ_PROTO_PROP 0 /* has o.__proto__ etc. */
|
||||
#define JS_HAS_REGEXPS 0 /* has perl r.e.s via RegExp, /pat/ */
|
||||
#define JS_HAS_SEQUENCE_OPS 0 /* has array.slice, string.concat */
|
||||
#define JS_HAS_INITIALIZERS 0 /* has var o = {'foo': 42, 'bar':3} */
|
||||
#define JS_HAS_OBJ_WATCHPOINT 0 /* has o.watch and o.unwatch */
|
||||
#define JS_HAS_EXPORT_IMPORT 0 /* has export fun; import obj.fun */
|
||||
#define JS_HAS_EVAL_THIS_SCOPE 0 /* Math.eval is same as with (Math) */
|
||||
#define JS_HAS_TRIPLE_EQOPS 0 /* has === and !== identity eqops */
|
||||
#define JS_HAS_SHARP_VARS 0 /* has #n=, #n# for object literals */
|
||||
#define JS_HAS_REPLACE_LAMBDA 0 /* has string.replace(re, lambda) */
|
||||
#define JS_HAS_SCRIPT_OBJECT 0 /* has (new Script("x++")).exec() */
|
||||
#define JS_HAS_XDR 0 /* has XDR API and object methods */
|
||||
#define JS_HAS_EXCEPTIONS 0 /* has exception handling */
|
||||
#define JS_HAS_UNDEFINED 0 /* has global "undefined" property */
|
||||
#define JS_HAS_TOSOURCE 0 /* has Object/Array toSource method */
|
||||
#define JS_HAS_IN_OPERATOR 0 /* has in operator ('p' in {p:1}) */
|
||||
#define JS_HAS_INSTANCEOF 0 /* has {p:1} instanceof Object */
|
||||
#define JS_HAS_ARGS_OBJECT 0 /* has minimal ECMA arguments object */
|
||||
#define JS_HAS_DEBUGGER_KEYWORD 0 /* has hook for debugger keyword */
|
||||
#define JS_HAS_ERROR_EXCEPTIONS 0 /* has error object hierarchy */
|
||||
#define JS_HAS_CATCH_GUARD 0 /* has exception handling catch guard */
|
||||
#define JS_HAS_NEW_OBJ_METHODS 0 /* has Object.prototype query methods */
|
||||
|
||||
#elif JS_VERSION == 120
|
||||
|
||||
#define JS_BUG_AUTO_INDEX_PROPS 0 /* new object o: o.p = v sets o[0] */
|
||||
#define JS_BUG_NULL_INDEX_PROPS 0 /* o[0] defaults to null, not void */
|
||||
#define JS_BUG_EMPTY_INDEX_ZERO 0 /* o[""] is equivalent to o[0] */
|
||||
#define JS_BUG_SHORT_CIRCUIT 0 /* 1 && 1 => true, 1 && 0 => 0 bug */
|
||||
#define JS_BUG_EAGER_TOSTRING 0 /* o.toString() trumps o.valueOf() */
|
||||
#define JS_BUG_VOID_TOSTRING 1 /* void 0 + 0 == "undefined0" */
|
||||
#define JS_BUG_EVAL_THIS_FUN 0 /* eval('this') in function f is f */
|
||||
#define JS_BUG_EVAL_THIS_SCOPE 0 /* Math.eval('sin(x)') vs. local x */
|
||||
#define JS_BUG_FALLIBLE_EQOPS 0 /* fallible/intransitive equality ops */
|
||||
#define JS_BUG_FALLIBLE_TONUM 0 /* fallible ValueToNumber primitive */
|
||||
#define JS_BUG_WITH_CLOSURE 1 /* with(o)function f(){} sets o.f */
|
||||
#define JS_BUG_SET_ENUMERATE 1 /* o.p=q flags o.p JSPROP_ENUMERATE */
|
||||
|
||||
#define JS_HAS_PROP_DELETE 1 /* delete o.p removes p from o */
|
||||
#define JS_HAS_CALL_OBJECT 1 /* fun.caller is stack frame obj */
|
||||
#define JS_HAS_LABEL_STATEMENT 1 /* has break/continue to label: */
|
||||
#define JS_HAS_DO_WHILE_LOOP 1 /* has do {...} while (b) */
|
||||
#define JS_HAS_SWITCH_STATEMENT 1 /* has switch (v) {case c: ...} */
|
||||
#define JS_HAS_SOME_PERL_FUN 1 /* has array.join/reverse/sort */
|
||||
#define JS_HAS_MORE_PERL_FUN 1 /* has array.push, str.substr, etc */
|
||||
#define JS_HAS_VALUEOF_HINT 1 /* valueOf(hint) where hint is typeof */
|
||||
#define JS_HAS_LEXICAL_CLOSURE 1 /* nested functions, lexically closed */
|
||||
#define JS_HAS_APPLY_FUNCTION 1 /* has apply(fun, arg1, ... argN) */
|
||||
#define JS_HAS_CALL_FUNCTION 0 /* has fun.call(obj, arg1, ... argN) */
|
||||
#define JS_HAS_OBJ_PROTO_PROP 1 /* has o.__proto__ etc. */
|
||||
#define JS_HAS_REGEXPS 1 /* has perl r.e.s via RegExp, /pat/ */
|
||||
#define JS_HAS_SEQUENCE_OPS 1 /* has array.slice, string.concat */
|
||||
#define JS_HAS_INITIALIZERS 1 /* has var o = {'foo': 42, 'bar':3} */
|
||||
#define JS_HAS_OBJ_WATCHPOINT 1 /* has o.watch and o.unwatch */
|
||||
#define JS_HAS_EXPORT_IMPORT 1 /* has export fun; import obj.fun */
|
||||
#define JS_HAS_EVAL_THIS_SCOPE 1 /* Math.eval is same as with (Math) */
|
||||
#define JS_HAS_TRIPLE_EQOPS 0 /* has === and !== identity eqops */
|
||||
#define JS_HAS_SHARP_VARS 0 /* has #n=, #n# for object literals */
|
||||
#define JS_HAS_REPLACE_LAMBDA 0 /* has string.replace(re, lambda) */
|
||||
#define JS_HAS_SCRIPT_OBJECT 0 /* has (new Script("x++")).exec() */
|
||||
#define JS_HAS_XDR 0 /* has XDR API and object methods */
|
||||
#define JS_HAS_EXCEPTIONS 0 /* has exception handling */
|
||||
#define JS_HAS_UNDEFINED 0 /* has global "undefined" property */
|
||||
#define JS_HAS_TOSOURCE 0 /* has Object/Array toSource method */
|
||||
#define JS_HAS_IN_OPERATOR 0 /* has in operator ('p' in {p:1}) */
|
||||
#define JS_HAS_INSTANCEOF 0 /* has {p:1} instanceof Object */
|
||||
#define JS_HAS_ARGS_OBJECT 0 /* has minimal ECMA arguments object */
|
||||
#define JS_HAS_DEBUGGER_KEYWORD 0 /* has hook for debugger keyword */
|
||||
#define JS_HAS_ERROR_EXCEPTIONS 0 /* has error object hierarchy */
|
||||
#define JS_HAS_CATCH_GUARD 0 /* has exception handling catch guard */
|
||||
#define JS_HAS_NEW_OBJ_METHODS 0 /* has Object.prototype query methods */
|
||||
|
||||
#elif JS_VERSION == 130
|
||||
|
||||
#define JS_BUG_AUTO_INDEX_PROPS 0 /* new object o: o.p = v sets o[0] */
|
||||
#define JS_BUG_NULL_INDEX_PROPS 0 /* o[0] defaults to null, not void */
|
||||
#define JS_BUG_EMPTY_INDEX_ZERO 0 /* o[""] is equivalent to o[0] */
|
||||
#define JS_BUG_SHORT_CIRCUIT 0 /* 1 && 1 => true, 1 && 0 => 0 bug */
|
||||
#define JS_BUG_EAGER_TOSTRING 0 /* o.toString() trumps o.valueOf() */
|
||||
#define JS_BUG_VOID_TOSTRING 0 /* void 0 + 0 == "undefined0" */
|
||||
#define JS_BUG_EVAL_THIS_FUN 0 /* eval('this') in function f is f */
|
||||
#define JS_BUG_EVAL_THIS_SCOPE 0 /* Math.eval('sin(x)') vs. local x */
|
||||
#define JS_BUG_FALLIBLE_EQOPS 0 /* fallible/intransitive equality ops */
|
||||
#define JS_BUG_FALLIBLE_TONUM 0 /* fallible ValueToNumber primitive */
|
||||
#define JS_BUG_WITH_CLOSURE 1 /* with(o)function f(){} sets o.f */
|
||||
#define JS_BUG_SET_ENUMERATE 0 /* o.p=q flags o.p JSPROP_ENUMERATE */
|
||||
|
||||
#define JS_HAS_PROP_DELETE 1 /* delete o.p removes p from o */
|
||||
#define JS_HAS_CALL_OBJECT 1 /* fun.caller is stack frame obj */
|
||||
#define JS_HAS_LABEL_STATEMENT 1 /* has break/continue to label: */
|
||||
#define JS_HAS_DO_WHILE_LOOP 1 /* has do {...} while (b) */
|
||||
#define JS_HAS_SWITCH_STATEMENT 1 /* has switch (v) {case c: ...} */
|
||||
#define JS_HAS_SOME_PERL_FUN 1 /* has array.join/reverse/sort */
|
||||
#define JS_HAS_MORE_PERL_FUN 1 /* has array.push, str.substr, etc */
|
||||
#define JS_HAS_VALUEOF_HINT 1 /* valueOf(hint) where hint is typeof */
|
||||
#define JS_HAS_LEXICAL_CLOSURE 1 /* nested functions, lexically closed */
|
||||
#define JS_HAS_APPLY_FUNCTION 1 /* has apply(fun, arg1, ... argN) */
|
||||
#define JS_HAS_CALL_FUNCTION 1 /* has fun.call(obj, arg1, ... argN) */
|
||||
#define JS_HAS_OBJ_PROTO_PROP 1 /* has o.__proto__ etc. */
|
||||
#define JS_HAS_REGEXPS 1 /* has perl r.e.s via RegExp, /pat/ */
|
||||
#define JS_HAS_SEQUENCE_OPS 1 /* has array.slice, string.concat */
|
||||
#define JS_HAS_INITIALIZERS 1 /* has var o = {'foo': 42, 'bar':3} */
|
||||
#define JS_HAS_OBJ_WATCHPOINT 1 /* has o.watch and o.unwatch */
|
||||
#define JS_HAS_EXPORT_IMPORT 1 /* has export fun; import obj.fun */
|
||||
#define JS_HAS_EVAL_THIS_SCOPE 1 /* Math.eval is same as with (Math) */
|
||||
#define JS_HAS_TRIPLE_EQOPS 1 /* has === and !== identity eqops */
|
||||
#define JS_HAS_SHARP_VARS 1 /* has #n=, #n# for object literals */
|
||||
#define JS_HAS_REPLACE_LAMBDA 1 /* has string.replace(re, lambda) */
|
||||
#define JS_HAS_SCRIPT_OBJECT 1 /* has (new Script("x++")).exec() */
|
||||
#define JS_HAS_XDR 1 /* has XDR API and object methods */
|
||||
#define JS_HAS_EXCEPTIONS 0 /* has exception handling */
|
||||
#define JS_HAS_UNDEFINED 1 /* has global "undefined" property */
|
||||
#define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */
|
||||
#define JS_HAS_IN_OPERATOR 0 /* has in operator ('p' in {p:1}) */
|
||||
#define JS_HAS_INSTANCEOF 0 /* has {p:1} instanceof Object */
|
||||
#define JS_HAS_ARGS_OBJECT 1 /* has minimal ECMA arguments object */
|
||||
#define JS_HAS_DEBUGGER_KEYWORD 1 /* has hook for debugger keyword */
|
||||
#define JS_HAS_ERROR_EXCEPTIONS 0 /* has error object hierarchy */
|
||||
#define JS_HAS_CATCH_GUARD 0 /* has exception handling catch guard */
|
||||
#define JS_HAS_NEW_OBJ_METHODS 0 /* has Object.prototype query methods */
|
||||
|
||||
#elif JS_VERSION == 140
|
||||
|
||||
#define JS_BUG_AUTO_INDEX_PROPS 0 /* new object o: o.p = v sets o[0] */
|
||||
#define JS_BUG_NULL_INDEX_PROPS 0 /* o[0] defaults to null, not void */
|
||||
#define JS_BUG_EMPTY_INDEX_ZERO 0 /* o[""] is equivalent to o[0] */
|
||||
#define JS_BUG_SHORT_CIRCUIT 0 /* 1 && 1 => true, 1 && 0 => 0 bug */
|
||||
#define JS_BUG_EAGER_TOSTRING 0 /* o.toString() trumps o.valueOf() */
|
||||
#define JS_BUG_VOID_TOSTRING 0 /* void 0 + 0 == "undefined0" */
|
||||
#define JS_BUG_EVAL_THIS_FUN 0 /* eval('this') in function f is f */
|
||||
#define JS_BUG_EVAL_THIS_SCOPE 0 /* Math.eval('sin(x)') vs. local x */
|
||||
#define JS_BUG_FALLIBLE_EQOPS 0 /* fallible/intransitive equality ops */
|
||||
#define JS_BUG_FALLIBLE_TONUM 0 /* fallible ValueToNumber primitive */
|
||||
#define JS_BUG_WITH_CLOSURE 1 /* with(o)function f(){} sets o.f */
|
||||
#define JS_BUG_SET_ENUMERATE 0 /* o.p=q flags o.p JSPROP_ENUMERATE */
|
||||
|
||||
#define JS_HAS_PROP_DELETE 1 /* delete o.p removes p from o */
|
||||
#define JS_HAS_CALL_OBJECT 1 /* fun.caller is stack frame obj */
|
||||
#define JS_HAS_LABEL_STATEMENT 1 /* has break/continue to label: */
|
||||
#define JS_HAS_DO_WHILE_LOOP 1 /* has do {...} while (b) */
|
||||
#define JS_HAS_SWITCH_STATEMENT 1 /* has switch (v) {case c: ...} */
|
||||
#define JS_HAS_SOME_PERL_FUN 1 /* has array.join/reverse/sort */
|
||||
#define JS_HAS_MORE_PERL_FUN 1 /* has array.push, str.substr, etc */
|
||||
#define JS_HAS_VALUEOF_HINT 1 /* valueOf(hint) where hint is typeof */
|
||||
#define JS_HAS_LEXICAL_CLOSURE 1 /* nested functions, lexically closed */
|
||||
#define JS_HAS_APPLY_FUNCTION 1 /* has apply(fun, arg1, ... argN) */
|
||||
#define JS_HAS_CALL_FUNCTION 1 /* has fun.call(obj, arg1, ... argN) */
|
||||
#define JS_HAS_OBJ_PROTO_PROP 1 /* has o.__proto__ etc. */
|
||||
#define JS_HAS_REGEXPS 1 /* has perl r.e.s via RegExp, /pat/ */
|
||||
#define JS_HAS_SEQUENCE_OPS 1 /* has array.slice, string.concat */
|
||||
#define JS_HAS_INITIALIZERS 1 /* has var o = {'foo': 42, 'bar':3} */
|
||||
#define JS_HAS_OBJ_WATCHPOINT 1 /* has o.watch and o.unwatch */
|
||||
#define JS_HAS_EXPORT_IMPORT 1 /* has export fun; import obj.fun */
|
||||
#define JS_HAS_EVAL_THIS_SCOPE 1 /* Math.eval is same as with (Math) */
|
||||
#define JS_HAS_TRIPLE_EQOPS 1 /* has === and !== identity eqops */
|
||||
#define JS_HAS_SHARP_VARS 1 /* has #n=, #n# for object literals */
|
||||
#define JS_HAS_REPLACE_LAMBDA 1 /* has string.replace(re, lambda) */
|
||||
#define JS_HAS_SCRIPT_OBJECT 1 /* has (new Script("x++")).exec() */
|
||||
#define JS_HAS_XDR 1 /* has XDR API and object methods */
|
||||
#define JS_HAS_EXCEPTIONS 1 /* has exception handling */
|
||||
#define JS_HAS_UNDEFINED 1 /* has global "undefined" property */
|
||||
#define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */
|
||||
#define JS_HAS_IN_OPERATOR 1 /* has in operator ('p' in {p:1}) */
|
||||
#define JS_HAS_INSTANCEOF 1 /* has {p:1} instanceof Object */
|
||||
#define JS_HAS_ARGS_OBJECT 1 /* has minimal ECMA arguments object */
|
||||
#define JS_HAS_DEBUGGER_KEYWORD 1 /* has hook for debugger keyword */
|
||||
#define JS_HAS_ERROR_EXCEPTIONS 0 /* rt errors reflected as exceptions */
|
||||
#define JS_HAS_CATCH_GUARD 0 /* has exception handling catch guard */
|
||||
#define JS_HAS_NEW_OBJ_METHODS 0 /* has Object.prototype query methods */
|
||||
|
||||
#define JS_HAS_DFLT_MSG_STRINGS 1 /* provides English error messages */
|
||||
|
||||
#else
|
||||
|
||||
#error "unknown JS_VERSION"
|
||||
|
||||
#endif
|
||||
135
mozilla/js/src/jsconfig.mk
Normal file
135
mozilla/js/src/jsconfig.mk
Normal file
@@ -0,0 +1,135 @@
|
||||
ifndef OBJDIR
|
||||
ifdef OBJDIR_NAME
|
||||
OBJDIR = $(OBJDIR_NAME)
|
||||
endif
|
||||
endif
|
||||
|
||||
NSPR_VERSION = 19980120
|
||||
NSPR_LOCAL = $(MOZ_DEPTH)/dist/$(OBJDIR)/nspr
|
||||
NSPR_DIST = $(MOZ_DEPTH)/dist/$(OBJDIR)
|
||||
NSPR_OBJDIR = $(OBJDIR)
|
||||
ifeq ($(OS_ARCH), SunOS)
|
||||
NSPR_OBJDIR := $(subst _sparc,,$(NSPR_OBJDIR))
|
||||
endif
|
||||
ifeq ($(OS_ARCH), Linux)
|
||||
NSPR_OBJDIR := $(subst _All,ELF2.0,$(NSPR_OBJDIR))
|
||||
endif
|
||||
ifeq ($(OS_ARCH), AIX)
|
||||
NSPR_OBJDIR := $(subst 4.1,4.2,$(NSPR_OBJDIR))
|
||||
endif
|
||||
ifeq ($(OS_ARCH), WINNT)
|
||||
NSPR_OBJDIR := $(subst WINNT,WIN95,$(NSPR_OBJDIR))
|
||||
ifeq ($(OBJDIR), WIN32_D.OBJ)
|
||||
NSPR_OBJDIR = WIN954.0_DBG.OBJ
|
||||
endif
|
||||
ifeq ($(OBJDIR), WIN32_O.OBJ)
|
||||
NSPR_OBJDIR = WIN954.0_OPT.OBJ
|
||||
endif
|
||||
endif
|
||||
NSPR_SHARED = /share/builds/components/nspr20/$(NSPR_VERSION)/$(NSPR_OBJDIR)
|
||||
ifeq ($(OS_ARCH), WINNT)
|
||||
NSPR_SHARED = nspr20/$(NSPR_VERSION)/$(NSPR_OBJDIR)
|
||||
endif
|
||||
NSPR_VERSIONFILE = $(NSPR_LOCAL)/Version
|
||||
NSPR_CURVERSION := $(shell cat $(NSPR_VERSIONFILE))
|
||||
|
||||
get_nspr:
|
||||
@echo "Grabbing NSPR component..."
|
||||
ifeq ($(NSPR_VERSION), $(NSPR_CURVERSION))
|
||||
@echo "No need, NSPR is up to date in this tree (ver=$(NSPR_VERSION))."
|
||||
else
|
||||
mkdir -p $(NSPR_LOCAL)
|
||||
mkdir -p $(NSPR_DIST)
|
||||
ifneq ($(OS_ARCH), WINNT)
|
||||
cp $(NSPR_SHARED)/*.jar $(NSPR_LOCAL)
|
||||
else
|
||||
sh $(MOZ_DEPTH)/../reltools/compftp.sh $(NSPR_SHARED) $(NSPR_LOCAL) *.jar
|
||||
endif
|
||||
unzip -o $(NSPR_LOCAL)/mdbinary.jar -d $(NSPR_DIST)
|
||||
mkdir -p $(NSPR_DIST)/include
|
||||
unzip -o $(NSPR_LOCAL)/mdheader.jar -d $(NSPR_DIST)/include
|
||||
rm -rf $(NSPR_DIST)/META-INF
|
||||
rm -rf $(NSPR_DIST)/include/META-INF
|
||||
echo $(NSPR_VERSION) > $(NSPR_VERSIONFILE)
|
||||
endif
|
||||
|
||||
SHIP_DIST = $(MOZ_DEPTH)/dist/$(OBJDIR)
|
||||
SHIP_DIR = $(SHIP_DIST)/SHIP
|
||||
|
||||
SHIP_LIBS = libjs.so
|
||||
ifdef JS_LIVECONNECT
|
||||
SHIP_LIBS += jsj.so
|
||||
endif
|
||||
ifdef JS_THREADSAFE
|
||||
ifeq ($(OS_ARCH), HP-UX)
|
||||
SHIP_LIBS += libnspr21.sl
|
||||
else
|
||||
SHIP_LIBS += libnspr21.so
|
||||
endif
|
||||
endif
|
||||
ifeq ($(OS_ARCH), WINNT)
|
||||
SHIP_LIBS = js32.dll
|
||||
ifdef JS_LIVECONNECT
|
||||
SHIP_LIBS += jsj.dll
|
||||
endif
|
||||
ifdef JS_THREADSAFE
|
||||
SHIP_LIBS += libnspr21.dll
|
||||
endif
|
||||
endif
|
||||
SHIP_LIBS := $(addprefix $(SHIP_DIST)/lib/, $(SHIP_LIBS))
|
||||
|
||||
SHIP_INCS = js*.h
|
||||
ifdef JS_LIVECONNECT
|
||||
SHIP_INCS += netscape*.h
|
||||
endif
|
||||
SHIP_INCS := $(addprefix $(SHIP_DIST)/include/, $(SHIP_INCS))
|
||||
|
||||
SHIP_BINS = js
|
||||
ifdef JS_LIVECONNECT
|
||||
SHIP_BINS += jsj
|
||||
endif
|
||||
ifeq ($(OS_ARCH), WINNT)
|
||||
SHIP_BINS := $(addsuffix .exe, $(SHIP_BINS))
|
||||
endif
|
||||
SHIP_BINS := $(addprefix $(SHIP_DIST)/bin/, $(SHIP_BINS))
|
||||
|
||||
ifdef BUILD_OPT
|
||||
JSREFJAR = jsref_opt.jar
|
||||
else
|
||||
JSREFJAR = jsref_dbg.jar
|
||||
endif
|
||||
|
||||
ship:
|
||||
mkdir -p $(SHIP_DIR)/lib
|
||||
mkdir -p $(SHIP_DIR)/include
|
||||
mkdir -p $(SHIP_DIR)/bin
|
||||
cp $(SHIP_LIBS) $(SHIP_DIR)/lib
|
||||
cp $(SHIP_INCS) $(SHIP_DIR)/include
|
||||
cp $(SHIP_BINS) $(SHIP_DIR)/bin
|
||||
cd $(SHIP_DIR); \
|
||||
zip -r $(JSREFJAR) bin lib include
|
||||
ifdef BUILD_SHIP
|
||||
cp $(SHIP_DIR)/$(JSREFJAR) $(BUILD_SHIP)
|
||||
endif
|
||||
|
||||
CWD = $(shell pwd)
|
||||
shipSource: $(SHIP_DIR)/jsref_src.lst .FORCE
|
||||
mkdir -p $(SHIP_DIR)
|
||||
cd $(MOZ_DEPTH)/.. ; \
|
||||
zip $(CWD)/$(SHIP_DIR)/jsref_src.jar -@ < $(CWD)/$(SHIP_DIR)/jsref_src.lst
|
||||
ifdef BUILD_SHIP
|
||||
cp $(SHIP_DIR)/jsref_src.jar $(BUILD_SHIP)
|
||||
endif
|
||||
|
||||
JSREFSRCDIRS := $(shell cat $(DEPTH)/SpiderMonkey.rsp)
|
||||
$(SHIP_DIR)/jsref_src.lst: .FORCE
|
||||
mkdir -p $(SHIP_DIR)
|
||||
rm -f $@
|
||||
touch $@
|
||||
for d in $(JSREFSRCDIRS); do \
|
||||
cd $(MOZ_DEPTH)/..; \
|
||||
ls -1 -d $$d | grep -v CVS | grep -v \.OBJ >> $(CWD)/$@; \
|
||||
cd $(CWD); \
|
||||
done
|
||||
|
||||
.FORCE:
|
||||
282
mozilla/js/src/jscpucfg.c
Normal file
282
mozilla/js/src/jscpucfg.c
Normal file
@@ -0,0 +1,282 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Generate CPU-specific bit-size and similar #defines.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef sgi
|
||||
#ifndef IRIX
|
||||
# error "IRIX is not defined"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __sun
|
||||
#if defined(__svr4) || defined(__svr4__)
|
||||
#ifndef SOLARIS
|
||||
# error "SOLARIS is not defined"
|
||||
#endif
|
||||
#else
|
||||
#ifndef SUNOS4
|
||||
# error "SUNOS4 is not defined"
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __hpux
|
||||
#ifndef HPUX
|
||||
# error "HPUX is not defined"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __osf__
|
||||
#ifndef OSF1
|
||||
# error "OSF1 is not defined"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _IBMR2
|
||||
#ifndef AIX
|
||||
# error "AIX is not defined"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef bsdi
|
||||
#ifndef BSDI
|
||||
# error "BSDI is not defined"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef M_UNIX
|
||||
#ifndef SCO
|
||||
# error "SCO is not defined"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(M_UNIX) && defined(_USLC_)
|
||||
#ifndef UNIXWARE
|
||||
# error "UNIXWARE is not defined"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __MWERKS__
|
||||
#define XP_MAC 1
|
||||
#endif
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
/* Generate cpucfg.h */
|
||||
#ifdef XP_MAC
|
||||
#include <Types.h>
|
||||
#define INT64 UnsignedWide
|
||||
#else
|
||||
#ifdef XP_PC
|
||||
#ifdef WIN32
|
||||
#define INT64 _int64
|
||||
#else
|
||||
#define INT64 long
|
||||
#endif
|
||||
#else
|
||||
#if defined(HPUX) || defined(SCO) || defined(UNIXWARE)
|
||||
#define INT64 long
|
||||
#else
|
||||
#define INT64 long long
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef void *prword;
|
||||
|
||||
struct align_short {
|
||||
char c;
|
||||
short a;
|
||||
};
|
||||
struct align_int {
|
||||
char c;
|
||||
int a;
|
||||
};
|
||||
struct align_long {
|
||||
char c;
|
||||
long a;
|
||||
};
|
||||
struct align_int64 {
|
||||
char c;
|
||||
INT64 a;
|
||||
};
|
||||
struct align_fakelonglong {
|
||||
char c;
|
||||
struct {
|
||||
long hi, lo;
|
||||
} a;
|
||||
};
|
||||
struct align_float {
|
||||
char c;
|
||||
float a;
|
||||
};
|
||||
struct align_double {
|
||||
char c;
|
||||
double a;
|
||||
};
|
||||
struct align_pointer {
|
||||
char c;
|
||||
void *a;
|
||||
};
|
||||
struct align_prword {
|
||||
char c;
|
||||
prword a;
|
||||
};
|
||||
|
||||
#define ALIGN_OF(type) \
|
||||
(((char*)&(((struct align_##type *)0)->a)) - ((char*)0))
|
||||
|
||||
int bpb;
|
||||
|
||||
static int Log2(int n)
|
||||
{
|
||||
int log2 = 0;
|
||||
|
||||
if (n & (n-1))
|
||||
log2++;
|
||||
if (n >> 16)
|
||||
log2 += 16, n >>= 16;
|
||||
if (n >> 8)
|
||||
log2 += 8, n >>= 8;
|
||||
if (n >> 4)
|
||||
log2 += 4, n >>= 4;
|
||||
if (n >> 2)
|
||||
log2 += 2, n >>= 2;
|
||||
if (n >> 1)
|
||||
log2++;
|
||||
return log2;
|
||||
}
|
||||
|
||||
/* We assume that int's are 32 bits */
|
||||
static void do64(void)
|
||||
{
|
||||
union {
|
||||
long i;
|
||||
char c[4];
|
||||
} u;
|
||||
|
||||
u.i = 0x01020304;
|
||||
if (u.c[0] == 0x01) {
|
||||
printf("#undef IS_LITTLE_ENDIAN\n");
|
||||
printf("#define IS_BIG_ENDIAN 1\n\n");
|
||||
} else {
|
||||
printf("#define IS_LITTLE_ENDIAN 1\n");
|
||||
printf("#undef IS_BIG_ENDIAN\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void do32(void)
|
||||
{
|
||||
union {
|
||||
long i;
|
||||
char c[4];
|
||||
} u;
|
||||
|
||||
u.i = 0x01020304;
|
||||
if (u.c[0] == 0x01) {
|
||||
printf("#undef IS_LITTLE_ENDIAN\n");
|
||||
printf("#define IS_BIG_ENDIAN 1\n\n");
|
||||
} else {
|
||||
printf("#define IS_LITTLE_ENDIAN 1\n");
|
||||
printf("#undef IS_BIG_ENDIAN\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Conceivably this could actually be used, but there is lots of code out
|
||||
* there with ands and shifts in it that assumes a byte is exactly 8 bits,
|
||||
* so forget about porting THIS code to all those non 8 bit byte machines.
|
||||
*/
|
||||
static void BitsPerByte(void)
|
||||
{
|
||||
bpb = 8;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
BitsPerByte();
|
||||
|
||||
printf("#ifndef js_cpucfg___\n");
|
||||
printf("#define js_cpucfg___\n\n");
|
||||
|
||||
printf("/* AUTOMATICALLY GENERATED - DO NOT EDIT */\n\n");
|
||||
|
||||
if (sizeof(long) == 8) {
|
||||
do64();
|
||||
} else {
|
||||
do32();
|
||||
}
|
||||
printf("#define JS_BYTES_PER_BYTE %dL\n", sizeof(char));
|
||||
printf("#define JS_BYTES_PER_SHORT %dL\n", sizeof(short));
|
||||
printf("#define JS_BYTES_PER_INT %dL\n", sizeof(int));
|
||||
printf("#define JS_BYTES_PER_INT64 %dL\n", 8);
|
||||
printf("#define JS_BYTES_PER_LONG %dL\n", sizeof(long));
|
||||
printf("#define JS_BYTES_PER_FLOAT %dL\n", sizeof(float));
|
||||
printf("#define JS_BYTES_PER_DOUBLE %dL\n", sizeof(double));
|
||||
printf("#define JS_BYTES_PER_WORD %dL\n", sizeof(prword));
|
||||
printf("#define JS_BYTES_PER_DWORD %dL\n", 8);
|
||||
printf("\n");
|
||||
|
||||
printf("#define JS_BITS_PER_BYTE %dL\n", bpb);
|
||||
printf("#define JS_BITS_PER_SHORT %dL\n", bpb * sizeof(short));
|
||||
printf("#define JS_BITS_PER_INT %dL\n", bpb * sizeof(int));
|
||||
printf("#define JS_BITS_PER_INT64 %dL\n", bpb * 8);
|
||||
printf("#define JS_BITS_PER_LONG %dL\n", bpb * sizeof(long));
|
||||
printf("#define JS_BITS_PER_FLOAT %dL\n", bpb * sizeof(float));
|
||||
printf("#define JS_BITS_PER_DOUBLE %dL\n", bpb * sizeof(double));
|
||||
printf("#define JS_BITS_PER_WORD %dL\n", bpb * sizeof(prword));
|
||||
printf("\n");
|
||||
|
||||
printf("#define JS_BITS_PER_BYTE_LOG2 %dL\n", Log2(bpb));
|
||||
printf("#define JS_BITS_PER_SHORT_LOG2 %dL\n", Log2(bpb * sizeof(short)));
|
||||
printf("#define JS_BITS_PER_INT_LOG2 %dL\n", Log2(bpb * sizeof(int)));
|
||||
printf("#define JS_BITS_PER_INT64_LOG2 %dL\n", 6);
|
||||
printf("#define JS_BITS_PER_LONG_LOG2 %dL\n", Log2(bpb * sizeof(long)));
|
||||
printf("#define JS_BITS_PER_FLOAT_LOG2 %dL\n", Log2(bpb * sizeof(float)));
|
||||
printf("#define JS_BITS_PER_DOUBLE_LOG2 %dL\n", Log2(bpb * sizeof(double)));
|
||||
printf("#define JS_BITS_PER_WORD_LOG2 %dL\n", Log2(bpb * sizeof(prword)));
|
||||
printf("\n");
|
||||
|
||||
printf("#define JS_ALIGN_OF_SHORT %dL\n", ALIGN_OF(short));
|
||||
printf("#define JS_ALIGN_OF_INT %dL\n", ALIGN_OF(int));
|
||||
printf("#define JS_ALIGN_OF_LONG %dL\n", ALIGN_OF(long));
|
||||
if (sizeof(INT64) < 8) {
|
||||
/* this machine doesn't actually support int64's */
|
||||
printf("#define JS_ALIGN_OF_INT64 %dL\n", ALIGN_OF(fakelonglong));
|
||||
} else {
|
||||
printf("#define JS_ALIGN_OF_INT64 %dL\n", ALIGN_OF(int64));
|
||||
}
|
||||
printf("#define JS_ALIGN_OF_FLOAT %dL\n", ALIGN_OF(float));
|
||||
printf("#define JS_ALIGN_OF_DOUBLE %dL\n", ALIGN_OF(double));
|
||||
printf("#define JS_ALIGN_OF_POINTER %dL\n", ALIGN_OF(pointer));
|
||||
printf("#define JS_ALIGN_OF_WORD %dL\n", ALIGN_OF(prword));
|
||||
printf("\n");
|
||||
|
||||
printf("#define JS_BYTES_PER_WORD_LOG2 %dL\n", Log2(sizeof(prword)));
|
||||
printf("#define JS_BYTES_PER_DWORD_LOG2 %dL\n", Log2(8));
|
||||
printf("#define JS_WORDS_PER_DWORD_LOG2 %dL\n", Log2(8/sizeof(prword)));
|
||||
printf("\n");
|
||||
|
||||
printf("#endif /* js_cpucfg___ */\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
175
mozilla/js/src/jscpucfg.h
Normal file
175
mozilla/js/src/jscpucfg.h
Normal file
@@ -0,0 +1,175 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef js_cpucfg___
|
||||
#define js_cpucfg___
|
||||
|
||||
#include "jsosdep.h"
|
||||
|
||||
#ifdef XP_MAC
|
||||
#undef IS_LITTLE_ENDIAN
|
||||
#define IS_BIG_ENDIAN 1
|
||||
|
||||
#define JS_BYTES_PER_BYTE 1L
|
||||
#define JS_BYTES_PER_SHORT 2L
|
||||
#define JS_BYTES_PER_INT 4L
|
||||
#define JS_BYTES_PER_INT64 8L
|
||||
#define JS_BYTES_PER_LONG 4L
|
||||
#define JS_BYTES_PER_FLOAT 4L
|
||||
#define JS_BYTES_PER_DOUBLE 8L
|
||||
#define JS_BYTES_PER_WORD 4L
|
||||
#define JS_BYTES_PER_DWORD 8L
|
||||
|
||||
#define JS_BITS_PER_BYTE 8L
|
||||
#define JS_BITS_PER_SHORT 16L
|
||||
#define JS_BITS_PER_INT 32L
|
||||
#define JS_BITS_PER_INT64 64L
|
||||
#define JS_BITS_PER_LONG 32L
|
||||
#define JS_BITS_PER_FLOAT 32L
|
||||
#define JS_BITS_PER_DOUBLE 64L
|
||||
#define JS_BITS_PER_WORD 32L
|
||||
|
||||
#define JS_BITS_PER_BYTE_LOG2 3L
|
||||
#define JS_BITS_PER_SHORT_LOG2 4L
|
||||
#define JS_BITS_PER_INT_LOG2 5L
|
||||
#define JS_BITS_PER_INT64_LOG2 6L
|
||||
#define JS_BITS_PER_LONG_LOG2 5L
|
||||
#define JS_BITS_PER_FLOAT_LOG2 5L
|
||||
#define JS_BITS_PER_DOUBLE_LOG2 6L
|
||||
#define JS_BITS_PER_WORD_LOG2 5L
|
||||
|
||||
#define JS_ALIGN_OF_SHORT 2L
|
||||
#define JS_ALIGN_OF_INT 4L
|
||||
#define JS_ALIGN_OF_LONG 4L
|
||||
#define JS_ALIGN_OF_INT64 2L
|
||||
#define JS_ALIGN_OF_FLOAT 4L
|
||||
#define JS_ALIGN_OF_DOUBLE 4L
|
||||
#define JS_ALIGN_OF_POINTER 4L
|
||||
#define JS_ALIGN_OF_WORD 4L
|
||||
|
||||
#define JS_BYTES_PER_WORD_LOG2 2L
|
||||
#define JS_BYTES_PER_DWORD_LOG2 3L
|
||||
#define PR_WORDS_PER_DWORD_LOG2 1L
|
||||
|
||||
#elif defined(XP_PC)
|
||||
|
||||
#ifdef _WIN32
|
||||
#define IS_LITTLE_ENDIAN 1
|
||||
#undef IS_BIG_ENDIAN
|
||||
|
||||
#define JS_BYTES_PER_BYTE 1L
|
||||
#define JS_BYTES_PER_SHORT 2L
|
||||
#define JS_BYTES_PER_INT 4L
|
||||
#define JS_BYTES_PER_INT64 8L
|
||||
#define JS_BYTES_PER_LONG 4L
|
||||
#define JS_BYTES_PER_FLOAT 4L
|
||||
#define JS_BYTES_PER_DOUBLE 8L
|
||||
#define JS_BYTES_PER_WORD 4L
|
||||
#define JS_BYTES_PER_DWORD 8L
|
||||
|
||||
#define JS_BITS_PER_BYTE 8L
|
||||
#define JS_BITS_PER_SHORT 16L
|
||||
#define JS_BITS_PER_INT 32L
|
||||
#define JS_BITS_PER_INT64 64L
|
||||
#define JS_BITS_PER_LONG 32L
|
||||
#define JS_BITS_PER_FLOAT 32L
|
||||
#define JS_BITS_PER_DOUBLE 64L
|
||||
#define JS_BITS_PER_WORD 32L
|
||||
|
||||
#define JS_BITS_PER_BYTE_LOG2 3L
|
||||
#define JS_BITS_PER_SHORT_LOG2 4L
|
||||
#define JS_BITS_PER_INT_LOG2 5L
|
||||
#define JS_BITS_PER_INT64_LOG2 6L
|
||||
#define JS_BITS_PER_LONG_LOG2 5L
|
||||
#define JS_BITS_PER_FLOAT_LOG2 5L
|
||||
#define JS_BITS_PER_DOUBLE_LOG2 6L
|
||||
#define JS_BITS_PER_WORD_LOG2 5L
|
||||
|
||||
#define JS_ALIGN_OF_SHORT 2L
|
||||
#define JS_ALIGN_OF_INT 4L
|
||||
#define JS_ALIGN_OF_LONG 4L
|
||||
#define JS_ALIGN_OF_INT64 8L
|
||||
#define JS_ALIGN_OF_FLOAT 4L
|
||||
#define JS_ALIGN_OF_DOUBLE 4L
|
||||
#define JS_ALIGN_OF_POINTER 4L
|
||||
#define JS_ALIGN_OF_WORD 4L
|
||||
|
||||
#define JS_BYTES_PER_WORD_LOG2 2L
|
||||
#define JS_BYTES_PER_DWORD_LOG2 3L
|
||||
#define PR_WORDS_PER_DWORD_LOG2 1L
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#if defined(_WINDOWS) && !defined(_WIN32) /* WIN16 */
|
||||
#define IS_LITTLE_ENDIAN 1
|
||||
#undef IS_BIG_ENDIAN
|
||||
|
||||
#define JS_BYTES_PER_BYTE 1L
|
||||
#define JS_BYTES_PER_SHORT 2L
|
||||
#define JS_BYTES_PER_INT 2L
|
||||
#define JS_BYTES_PER_INT64 8L
|
||||
#define JS_BYTES_PER_LONG 4L
|
||||
#define JS_BYTES_PER_FLOAT 4L
|
||||
#define JS_BYTES_PER_DOUBLE 8L
|
||||
#define JS_BYTES_PER_WORD 4L
|
||||
#define JS_BYTES_PER_DWORD 8L
|
||||
|
||||
#define JS_BITS_PER_BYTE 8L
|
||||
#define JS_BITS_PER_SHORT 16L
|
||||
#define JS_BITS_PER_INT 16L
|
||||
#define JS_BITS_PER_INT64 64L
|
||||
#define JS_BITS_PER_LONG 32L
|
||||
#define JS_BITS_PER_FLOAT 32L
|
||||
#define JS_BITS_PER_DOUBLE 64L
|
||||
#define JS_BITS_PER_WORD 32L
|
||||
|
||||
#define JS_BITS_PER_BYTE_LOG2 3L
|
||||
#define JS_BITS_PER_SHORT_LOG2 4L
|
||||
#define JS_BITS_PER_INT_LOG2 4L
|
||||
#define JS_BITS_PER_INT64_LOG2 6L
|
||||
#define JS_BITS_PER_LONG_LOG2 5L
|
||||
#define JS_BITS_PER_FLOAT_LOG2 5L
|
||||
#define JS_BITS_PER_DOUBLE_LOG2 6L
|
||||
#define JS_BITS_PER_WORD_LOG2 5L
|
||||
|
||||
#define JS_ALIGN_OF_SHORT 2L
|
||||
#define JS_ALIGN_OF_INT 2L
|
||||
#define JS_ALIGN_OF_LONG 2L
|
||||
#define JS_ALIGN_OF_INT64 2L
|
||||
#define JS_ALIGN_OF_FLOAT 2L
|
||||
#define JS_ALIGN_OF_DOUBLE 2L
|
||||
#define JS_ALIGN_OF_POINTER 2L
|
||||
#define JS_ALIGN_OF_WORD 2L
|
||||
|
||||
#define JS_BYTES_PER_WORD_LOG2 2L
|
||||
#define JS_BYTES_PER_DWORD_LOG2 3L
|
||||
#define PR_WORDS_PER_DWORD_LOG2 1L
|
||||
#endif /* defined(_WINDOWS) && !defined(_WIN32) */
|
||||
|
||||
#elif defined(XP_UNIX)
|
||||
|
||||
#error "This file is supposed to be auto-generated on UNIX platforms, but the"
|
||||
#error "static version for Mac and Windows platforms is being used."
|
||||
#error "Something's probably wrong with paths/headers/dependencies/Makefiles."
|
||||
|
||||
#else
|
||||
|
||||
#error "Must define one of XP_MAC, XP_PC or XP_UNIX"
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* js_cpucfg___ */
|
||||
2022
mozilla/js/src/jsdate.c
Normal file
2022
mozilla/js/src/jsdate.c
Normal file
File diff suppressed because it is too large
Load Diff
76
mozilla/js/src/jsdate.h
Normal file
76
mozilla/js/src/jsdate.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef jsdate_h___
|
||||
#define jsdate_h___
|
||||
/*
|
||||
* JS Date class interface.
|
||||
*/
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
extern JSObject *
|
||||
js_InitDateClass(JSContext *cx, JSObject *obj);
|
||||
|
||||
/*
|
||||
* These functions provide a C interface to the date/time object
|
||||
*/
|
||||
extern JS_FRIEND_API(JSObject*)
|
||||
js_NewDateObject(JSContext* cx, int year, int mon, int mday,
|
||||
int hour, int min, int sec);
|
||||
|
||||
extern JS_FRIEND_API(int)
|
||||
js_DateGetYear(JSContext *cx, JSObject* obj);
|
||||
|
||||
extern JS_FRIEND_API(int)
|
||||
js_DateGetMonth(JSContext *cx, JSObject* obj);
|
||||
|
||||
extern JS_FRIEND_API(int)
|
||||
js_DateGetDate(JSContext *cx, JSObject* obj);
|
||||
|
||||
extern JS_FRIEND_API(int)
|
||||
js_DateGetHours(JSContext *cx, JSObject* obj);
|
||||
|
||||
extern JS_FRIEND_API(int)
|
||||
js_DateGetMinutes(JSContext *cx, JSObject* obj);
|
||||
|
||||
extern JS_FRIEND_API(int)
|
||||
js_DateGetSeconds(JSContext *cx, JSObject* obj);
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
js_DateSetYear(JSContext *cx, JSObject *obj, int year);
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
js_DateSetMonth(JSContext *cx, JSObject *obj, int year);
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
js_DateSetDate(JSContext *cx, JSObject *obj, int date);
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
js_DateSetHours(JSContext *cx, JSObject *obj, int hours);
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
js_DateSetMinutes(JSContext *cx, JSObject *obj, int minutes);
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
js_DateSetSeconds(JSContext *cx, JSObject *obj, int seconds);
|
||||
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsdate_h___ */
|
||||
880
mozilla/js/src/jsdbgapi.c
Normal file
880
mozilla/js/src/jsdbgapi.c
Normal file
@@ -0,0 +1,880 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* JS debugging API.
|
||||
*/
|
||||
#include "jsstddef.h"
|
||||
#include <string.h>
|
||||
#include "jstypes.h"
|
||||
#include "jsutil.h" /* Added by JSIFY */
|
||||
#include "jsclist.h"
|
||||
#include "jsapi.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsconfig.h"
|
||||
#include "jsdbgapi.h"
|
||||
#include "jsfun.h"
|
||||
#include "jsgc.h"
|
||||
#include "jsinterp.h"
|
||||
#include "jslock.h"
|
||||
#include "jsobj.h"
|
||||
#include "jsopcode.h"
|
||||
#include "jsscope.h"
|
||||
#include "jsscript.h"
|
||||
#include "jsstr.h"
|
||||
|
||||
typedef struct JSTrap {
|
||||
JSCList links;
|
||||
JSScript *script;
|
||||
jsbytecode *pc;
|
||||
JSOp op;
|
||||
JSTrapHandler handler;
|
||||
void *closure;
|
||||
} JSTrap;
|
||||
|
||||
static JSTrap *
|
||||
FindTrap(JSRuntime *rt, JSScript *script, jsbytecode *pc)
|
||||
{
|
||||
JSTrap *trap;
|
||||
|
||||
for (trap = (JSTrap *)rt->trapList.next;
|
||||
trap != (JSTrap *)&rt->trapList;
|
||||
trap = (JSTrap *)trap->links.next) {
|
||||
if (trap->script == script && trap->pc == pc)
|
||||
return trap;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
js_PatchOpcode(JSContext *cx, JSScript *script, jsbytecode *pc, JSOp op)
|
||||
{
|
||||
JSTrap *trap;
|
||||
|
||||
trap = FindTrap(cx->runtime, script, pc);
|
||||
if (trap)
|
||||
trap->op = op;
|
||||
else
|
||||
*pc = (jsbytecode)op;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
JSTrapHandler handler, void *closure)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
JSTrap *trap;
|
||||
|
||||
rt = cx->runtime;
|
||||
trap = FindTrap(rt, script, pc);
|
||||
if (trap) {
|
||||
/* Restore opcode at pc so it can be saved again. */
|
||||
*pc = (jsbytecode)trap->op;
|
||||
} else {
|
||||
trap = JS_malloc(cx, sizeof *trap);
|
||||
if (!trap || !js_AddRoot(cx, &trap->closure, "trap->closure")) {
|
||||
if (trap)
|
||||
JS_free(cx, trap);
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
JS_APPEND_LINK(&trap->links, &rt->trapList);
|
||||
trap->script = script;
|
||||
trap->pc = pc;
|
||||
trap->op = (JSOp)*pc;
|
||||
trap->handler = handler;
|
||||
trap->closure = closure;
|
||||
*pc = JSOP_TRAP;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSOp)
|
||||
JS_GetTrapOpcode(JSContext *cx, JSScript *script, jsbytecode *pc)
|
||||
{
|
||||
JSTrap *trap;
|
||||
|
||||
trap = FindTrap(cx->runtime, script, pc);
|
||||
if (!trap) {
|
||||
JS_ASSERT(0); /* XXX can't happen */
|
||||
return JSOP_LIMIT;
|
||||
}
|
||||
return trap->op;
|
||||
}
|
||||
|
||||
static void
|
||||
DestroyTrap(JSContext *cx, JSTrap *trap)
|
||||
{
|
||||
JS_REMOVE_LINK(&trap->links);
|
||||
*trap->pc = (jsbytecode)trap->op;
|
||||
js_RemoveRoot(cx, &trap->closure);
|
||||
JS_free(cx, trap);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_ClearTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
JSTrapHandler *handlerp, void **closurep)
|
||||
{
|
||||
JSTrap *trap;
|
||||
|
||||
trap = FindTrap(cx->runtime, script, pc);
|
||||
if (handlerp)
|
||||
*handlerp = trap ? trap->handler : NULL;
|
||||
if (closurep)
|
||||
*closurep = trap ? trap->closure : NULL;
|
||||
if (trap)
|
||||
DestroyTrap(cx, trap);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_ClearScriptTraps(JSContext *cx, JSScript *script)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
JSTrap *trap, *next;
|
||||
|
||||
rt = cx->runtime;
|
||||
for (trap = (JSTrap *)rt->trapList.next;
|
||||
trap != (JSTrap *)&rt->trapList;
|
||||
trap = next) {
|
||||
next = (JSTrap *)trap->links.next;
|
||||
if (trap->script == script)
|
||||
DestroyTrap(cx, trap);
|
||||
}
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_ClearAllTraps(JSContext *cx)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
JSTrap *trap, *next;
|
||||
|
||||
rt = cx->runtime;
|
||||
for (trap = (JSTrap *)rt->trapList.next;
|
||||
trap != (JSTrap *)&rt->trapList;
|
||||
trap = next) {
|
||||
next = (JSTrap *)trap->links.next;
|
||||
DestroyTrap(cx, trap);
|
||||
}
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSTrapStatus)
|
||||
JS_HandleTrap(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval)
|
||||
{
|
||||
JSTrap *trap;
|
||||
JSTrapStatus status;
|
||||
jsint op;
|
||||
|
||||
trap = FindTrap(cx->runtime, script, pc);
|
||||
if (!trap) {
|
||||
JS_ASSERT(0); /* XXX can't happen */
|
||||
return JSTRAP_ERROR;
|
||||
}
|
||||
/*
|
||||
* It's important that we not use 'trap->' after calling the callback --
|
||||
* the callback might remove the trap!
|
||||
*/
|
||||
op = (jsint)trap->op;
|
||||
status = trap->handler(cx, script, pc, rval, trap->closure);
|
||||
if (status == JSTRAP_CONTINUE) {
|
||||
/* By convention, return the true op to the interpreter in rval. */
|
||||
*rval = INT_TO_JSVAL(op);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_SetInterrupt(JSRuntime *rt, JSTrapHandler handler, void *closure)
|
||||
{
|
||||
rt->interruptHandler = handler;
|
||||
rt->interruptHandlerData = closure;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_ClearInterrupt(JSRuntime *rt, JSTrapHandler *handlerp, void **closurep)
|
||||
{
|
||||
if (handlerp)
|
||||
*handlerp = (JSTrapHandler)rt->interruptHandler;
|
||||
if (closurep)
|
||||
*closurep = rt->interruptHandlerData;
|
||||
rt->interruptHandler = 0;
|
||||
rt->interruptHandlerData = 0;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
|
||||
typedef struct JSWatchPoint {
|
||||
JSCList links;
|
||||
JSObject *object; /* weak link, see js_FinalizeObject */
|
||||
jsval userid;
|
||||
JSScopeProperty *sprop;
|
||||
JSPropertyOp setter;
|
||||
JSWatchPointHandler handler;
|
||||
void *closure;
|
||||
jsrefcount nrefs;
|
||||
} JSWatchPoint;
|
||||
|
||||
#define HoldWatchPoint(wp) ((wp)->nrefs++)
|
||||
|
||||
static void
|
||||
DropWatchPoint(JSContext *cx, JSWatchPoint *wp)
|
||||
{
|
||||
if (--wp->nrefs != 0)
|
||||
return;
|
||||
wp->sprop->setter = wp->setter;
|
||||
JS_LOCK_OBJ_VOID(cx, wp->object,
|
||||
js_DropScopeProperty(cx, (JSScope *)wp->object->map,
|
||||
wp->sprop));
|
||||
JS_REMOVE_LINK(&wp->links);
|
||||
js_RemoveRoot(cx, &wp->closure);
|
||||
JS_free(cx, wp);
|
||||
}
|
||||
|
||||
static JSWatchPoint *
|
||||
FindWatchPoint(JSRuntime *rt, JSObject *obj, jsval userid)
|
||||
{
|
||||
JSWatchPoint *wp;
|
||||
|
||||
for (wp = (JSWatchPoint *)rt->watchPointList.next;
|
||||
wp != (JSWatchPoint *)&rt->watchPointList;
|
||||
wp = (JSWatchPoint *)wp->links.next) {
|
||||
if (wp->object == obj && wp->userid == userid)
|
||||
return wp;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JSScopeProperty *
|
||||
js_FindWatchPoint(JSRuntime *rt, JSObject *obj, jsval userid)
|
||||
{
|
||||
JSWatchPoint *wp;
|
||||
|
||||
wp = FindWatchPoint(rt, obj, userid);
|
||||
if (!wp)
|
||||
return NULL;
|
||||
return wp->sprop;
|
||||
}
|
||||
|
||||
JSBool JS_DLL_CALLBACK
|
||||
js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
JSWatchPoint *wp;
|
||||
JSScopeProperty *sprop;
|
||||
JSSymbol *sym;
|
||||
jsval userid, value;
|
||||
jsid symid;
|
||||
JSScope *scope;
|
||||
JSAtom *atom;
|
||||
JSBool ok;
|
||||
|
||||
rt = cx->runtime;
|
||||
for (wp = (JSWatchPoint *)rt->watchPointList.next;
|
||||
wp != (JSWatchPoint *)&rt->watchPointList;
|
||||
wp = (JSWatchPoint *)wp->links.next) {
|
||||
sprop = wp->sprop;
|
||||
if (wp->object == obj && sprop->id == id) {
|
||||
JS_LOCK_OBJ(cx, obj);
|
||||
sym = sprop->symbols;
|
||||
if (!sym) {
|
||||
userid = wp->userid;
|
||||
atom = NULL;
|
||||
if (JSVAL_IS_INT(userid)) {
|
||||
symid = (jsid)userid;
|
||||
} else {
|
||||
atom = js_ValueToStringAtom(cx, userid);
|
||||
if (!atom) {
|
||||
JS_UNLOCK_OBJ(cx, obj);
|
||||
return JS_FALSE;
|
||||
}
|
||||
symid = (jsid)atom;
|
||||
}
|
||||
scope = (JSScope *) obj->map;
|
||||
JS_ASSERT(scope->props);
|
||||
ok = LOCKED_OBJ_GET_CLASS(obj)->addProperty(cx, obj, sprop->id,
|
||||
&value);
|
||||
if (!ok) {
|
||||
JS_UNLOCK_OBJ(cx, obj);
|
||||
return JS_FALSE;
|
||||
}
|
||||
ok = (scope->ops->add(cx, scope, symid, sprop) != NULL);
|
||||
if (!ok) {
|
||||
JS_UNLOCK_OBJ(cx, obj);
|
||||
return JS_FALSE;
|
||||
}
|
||||
sym = sprop->symbols;
|
||||
}
|
||||
JS_UNLOCK_OBJ(cx, obj);
|
||||
HoldWatchPoint(wp);
|
||||
ok = wp->handler(cx, obj, js_IdToValue(sym_id(sym)),
|
||||
OBJ_GET_SLOT(cx, obj, wp->sprop->slot), vp,
|
||||
wp->closure);
|
||||
if (ok)
|
||||
ok = wp->setter(cx, obj, id, vp);
|
||||
DropWatchPoint(cx, wp);
|
||||
return ok;
|
||||
}
|
||||
}
|
||||
JS_ASSERT(0); /* XXX can't happen */
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval id,
|
||||
JSWatchPointHandler handler, void *closure)
|
||||
{
|
||||
JSAtom *atom;
|
||||
jsid symid;
|
||||
JSObject *pobj;
|
||||
JSScopeProperty *sprop;
|
||||
JSRuntime *rt;
|
||||
JSWatchPoint *wp;
|
||||
|
||||
if (!OBJ_IS_NATIVE(obj)) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_WATCH,
|
||||
OBJ_GET_CLASS(cx, obj)->name);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (JSVAL_IS_INT(id)) {
|
||||
symid = (jsid)id;
|
||||
atom = NULL;
|
||||
} else {
|
||||
atom = js_ValueToStringAtom(cx, id);
|
||||
if (!atom)
|
||||
return JS_FALSE;
|
||||
symid = (jsid)atom;
|
||||
}
|
||||
|
||||
if (!js_LookupProperty(cx, obj, symid, &pobj, (JSProperty **)&sprop))
|
||||
return JS_FALSE;
|
||||
rt = cx->runtime;
|
||||
if (!sprop) {
|
||||
/* Check for a deleted symbol watchpoint, which holds its property. */
|
||||
sprop = js_FindWatchPoint(rt, obj, id);
|
||||
if (sprop) {
|
||||
#ifdef JS_THREADSAFE
|
||||
/* Emulate js_LookupProperty if thread-safe. */
|
||||
JS_LOCK_OBJ(cx, obj);
|
||||
sprop->nrefs++;
|
||||
#endif
|
||||
} else {
|
||||
/* Make a new property in obj so we can watch for the first set. */
|
||||
if (!js_DefineProperty(cx, obj, symid, JSVAL_VOID, NULL, NULL, 0,
|
||||
(JSProperty **)&sprop)) {
|
||||
sprop = NULL;
|
||||
}
|
||||
}
|
||||
} else if (pobj != obj) {
|
||||
/* Clone the prototype property so we can watch the right object. */
|
||||
jsval value;
|
||||
JSPropertyOp getter, setter;
|
||||
uintN attrs;
|
||||
|
||||
if (OBJ_IS_NATIVE(pobj)) {
|
||||
value = LOCKED_OBJ_GET_SLOT(pobj, sprop->slot);
|
||||
} else {
|
||||
if (!OBJ_GET_PROPERTY(cx, pobj, id, &value)) {
|
||||
OBJ_DROP_PROPERTY(cx, pobj, (JSProperty *)sprop);
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
getter = sprop->getter;
|
||||
setter = sprop->setter;
|
||||
attrs = sprop->attrs;
|
||||
OBJ_DROP_PROPERTY(cx, pobj, (JSProperty *)sprop);
|
||||
|
||||
if (!js_DefineProperty(cx, obj, symid, value, getter, setter, attrs,
|
||||
(JSProperty **)&sprop)) {
|
||||
sprop = NULL;
|
||||
}
|
||||
}
|
||||
if (!sprop)
|
||||
return JS_FALSE;
|
||||
|
||||
wp = FindWatchPoint(rt, obj, id);
|
||||
if (!wp) {
|
||||
wp = JS_malloc(cx, sizeof *wp);
|
||||
if (!wp)
|
||||
return JS_FALSE;
|
||||
if (!js_AddRoot(cx, &wp->closure, "wp->closure")) {
|
||||
JS_free(cx, wp);
|
||||
return JS_FALSE;
|
||||
}
|
||||
JS_APPEND_LINK(&wp->links, &rt->watchPointList);
|
||||
wp->object = obj;
|
||||
wp->userid = id;
|
||||
wp->sprop = js_HoldScopeProperty(cx, (JSScope *)obj->map, sprop);
|
||||
wp->setter = sprop->setter;
|
||||
sprop->setter = js_watch_set;
|
||||
wp->nrefs = 1;
|
||||
}
|
||||
wp->handler = handler;
|
||||
wp->closure = closure;
|
||||
OBJ_DROP_PROPERTY(cx, obj, (JSProperty *)sprop);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_ClearWatchPoint(JSContext *cx, JSObject *obj, jsval id,
|
||||
JSWatchPointHandler *handlerp, void **closurep)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
JSWatchPoint *wp;
|
||||
|
||||
rt = cx->runtime;
|
||||
for (wp = (JSWatchPoint *)rt->watchPointList.next;
|
||||
wp != (JSWatchPoint *)&rt->watchPointList;
|
||||
wp = (JSWatchPoint *)wp->links.next) {
|
||||
if (wp->object == obj && wp->userid == id) {
|
||||
if (handlerp)
|
||||
*handlerp = wp->handler;
|
||||
if (closurep)
|
||||
*closurep = wp->closure;
|
||||
DropWatchPoint(cx, wp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (handlerp)
|
||||
*handlerp = NULL;
|
||||
if (closurep)
|
||||
*closurep = NULL;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_ClearWatchPointsForObject(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
JSWatchPoint *wp, *next;
|
||||
|
||||
rt = cx->runtime;
|
||||
for (wp = (JSWatchPoint *)rt->watchPointList.next;
|
||||
wp != (JSWatchPoint *)&rt->watchPointList;
|
||||
wp = next) {
|
||||
next = (JSWatchPoint *)wp->links.next;
|
||||
if (wp->object == obj)
|
||||
DropWatchPoint(cx, wp);
|
||||
}
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_ClearAllWatchPoints(JSContext *cx)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
JSWatchPoint *wp, *next;
|
||||
|
||||
rt = cx->runtime;
|
||||
for (wp = (JSWatchPoint *)rt->watchPointList.next;
|
||||
wp != (JSWatchPoint *)&rt->watchPointList;
|
||||
wp = next) {
|
||||
next = (JSWatchPoint *)wp->links.next;
|
||||
DropWatchPoint(cx, wp);
|
||||
}
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(uintN)
|
||||
JS_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc)
|
||||
{
|
||||
return js_PCToLineNumber(script, pc);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(jsbytecode *)
|
||||
JS_LineNumberToPC(JSContext *cx, JSScript *script, uintN lineno)
|
||||
{
|
||||
return js_LineNumberToPC(script, lineno);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSScript *)
|
||||
JS_GetFunctionScript(JSContext *cx, JSFunction *fun)
|
||||
{
|
||||
return fun->script;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSPrincipals *)
|
||||
JS_GetScriptPrincipals(JSContext *cx, JSScript *script)
|
||||
{
|
||||
return script->principals;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Stack Frame Iterator
|
||||
*/
|
||||
JS_PUBLIC_API(JSStackFrame *)
|
||||
JS_FrameIterator(JSContext *cx, JSStackFrame **iteratorp)
|
||||
{
|
||||
*iteratorp = (*iteratorp == NULL) ? cx->fp : (*iteratorp)->down;
|
||||
return *iteratorp;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSScript *)
|
||||
JS_GetFrameScript(JSContext *cx, JSStackFrame *fp)
|
||||
{
|
||||
return fp->script;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(jsbytecode *)
|
||||
JS_GetFramePC(JSContext *cx, JSStackFrame *fp)
|
||||
{
|
||||
return fp->pc;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void *)
|
||||
JS_GetFrameAnnotation(JSContext *cx, JSStackFrame *fp)
|
||||
{
|
||||
if (fp->annotation) {
|
||||
JSPrincipals *principals = fp->script
|
||||
? fp->script->principals
|
||||
: NULL;
|
||||
|
||||
if (principals == NULL)
|
||||
return NULL;
|
||||
|
||||
if (principals->globalPrivilegesEnabled(cx, principals)) {
|
||||
/*
|
||||
* Only give out an annotation if privileges have not
|
||||
* been revoked globally.
|
||||
*/
|
||||
return fp->annotation;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_SetFrameAnnotation(JSContext *cx, JSStackFrame *fp, void *annotation)
|
||||
{
|
||||
fp->annotation = annotation;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void *)
|
||||
JS_GetFramePrincipalArray(JSContext *cx, JSStackFrame *fp)
|
||||
{
|
||||
JSPrincipals *principals = fp->script
|
||||
? fp->script->principals
|
||||
: NULL;
|
||||
|
||||
return principals
|
||||
? principals->getPrincipalArray(cx, principals)
|
||||
: NULL;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_IsNativeFrame(JSContext *cx, JSStackFrame *fp)
|
||||
{
|
||||
return fp->fun && fp->fun->call;
|
||||
}
|
||||
|
||||
/* this is deprecated, use JS_GetFrameScopeChain instead */
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
JS_GetFrameObject(JSContext *cx, JSStackFrame *fp)
|
||||
{
|
||||
return fp->scopeChain;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
JS_GetFrameScopeChain(JSContext *cx, JSStackFrame *fp)
|
||||
{
|
||||
/* Force creation of argument and call objects if not yet created */
|
||||
JS_GetFrameCallObject(cx, fp);
|
||||
return fp->scopeChain;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
JS_GetFrameCallObject(JSContext *cx, JSStackFrame *fp)
|
||||
{
|
||||
if (! fp->fun)
|
||||
return NULL;
|
||||
/* Force creation of argument object if not yet created */
|
||||
js_GetArgsObject(cx, fp);
|
||||
#if JS_HAS_CALL_OBJECT
|
||||
return js_GetCallObject(cx, fp, NULL, NULL);
|
||||
#else
|
||||
return NULL;
|
||||
#endif /* JS_HAS_CALL_OBJECT */
|
||||
}
|
||||
|
||||
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
JS_GetFrameThis(JSContext *cx, JSStackFrame *fp)
|
||||
{
|
||||
return fp->thisp;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSFunction *)
|
||||
JS_GetFrameFunction(JSContext *cx, JSStackFrame *fp)
|
||||
{
|
||||
return fp->fun;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_IsContructorFrame(JSContext *cx, JSStackFrame *fp)
|
||||
{
|
||||
return fp->constructing;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_IsDebuggerFrame(JSContext *cx, JSStackFrame *fp)
|
||||
{
|
||||
return fp->debugging;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(jsval)
|
||||
JS_GetFrameReturnValue(JSContext *cx, JSStackFrame *fp)
|
||||
{
|
||||
return fp->rval;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_SetFrameReturnValue(JSContext *cx, JSStackFrame *fp, jsval rval)
|
||||
{
|
||||
fp->rval = rval;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
JS_PUBLIC_API(const char *)
|
||||
JS_GetScriptFilename(JSContext *cx, JSScript *script)
|
||||
{
|
||||
return script->filename;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(uintN)
|
||||
JS_GetScriptBaseLineNumber(JSContext *cx, JSScript *script)
|
||||
{
|
||||
return script->lineno;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(uintN)
|
||||
JS_GetScriptLineExtent(JSContext *cx, JSScript *script)
|
||||
{
|
||||
return js_GetScriptLineExtent(script);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_SetNewScriptHook(JSRuntime *rt, JSNewScriptHook hook, void *callerdata)
|
||||
{
|
||||
rt->newScriptHook = hook;
|
||||
rt->newScriptHookData = callerdata;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_SetDestroyScriptHook(JSRuntime *rt, JSDestroyScriptHook hook,
|
||||
void *callerdata)
|
||||
{
|
||||
rt->destroyScriptHook = hook;
|
||||
rt->destroyScriptHookData = callerdata;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_EvaluateInStackFrame(JSContext *cx, JSStackFrame *fp,
|
||||
const char *bytes, uintN length,
|
||||
const char *filename, uintN lineno,
|
||||
jsval *rval)
|
||||
{
|
||||
JSScript *script;
|
||||
JSBool ok;
|
||||
|
||||
script = JS_CompileScriptForPrincipals(cx, fp->scopeChain,
|
||||
fp->script ? fp->script->principals
|
||||
: NULL,
|
||||
bytes, length, filename, lineno);
|
||||
if (!script)
|
||||
return JS_FALSE;
|
||||
ok = js_Execute(cx, fp->scopeChain, script, fp->fun, fp, JS_TRUE, rval);
|
||||
js_DestroyScript(cx, script);
|
||||
return ok;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
JS_PUBLIC_API(JSScopeProperty *)
|
||||
JS_PropertyIterator(JSObject *obj, JSScopeProperty **iteratorp)
|
||||
{
|
||||
JSScopeProperty *sprop;
|
||||
JSScope *scope;
|
||||
|
||||
sprop = *iteratorp;
|
||||
scope = (JSScope *) obj->map;
|
||||
sprop = (sprop == NULL) ? scope->props : sprop->next;
|
||||
*iteratorp = sprop;
|
||||
return sprop;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop,
|
||||
JSPropertyDesc *pd)
|
||||
{
|
||||
JSSymbol *sym;
|
||||
|
||||
sym = sprop->symbols;
|
||||
pd->id = sym ? js_IdToValue(sym_id(sym)) : JSVAL_VOID;
|
||||
if (!sym || !js_GetProperty(cx, obj, sym_id(sym), &pd->value))
|
||||
pd->value = OBJ_GET_SLOT(cx, obj, sprop->slot);
|
||||
pd->flags = ((sprop->attrs & JSPROP_ENUMERATE) ? JSPD_ENUMERATE : 0)
|
||||
| ((sprop->attrs & JSPROP_READONLY) ? JSPD_READONLY : 0)
|
||||
| ((sprop->attrs & JSPROP_PERMANENT) ? JSPD_PERMANENT : 0)
|
||||
#if JS_HAS_CALL_OBJECT
|
||||
| ((sprop->getter == js_GetCallVariable) ? JSPD_VARIABLE : 0)
|
||||
#endif /* JS_HAS_CALL_OBJECT */
|
||||
| ((sprop->getter == js_GetArgument) ? JSPD_ARGUMENT : 0)
|
||||
| ((sprop->getter == js_GetLocalVariable) ? JSPD_VARIABLE : 0);
|
||||
#if JS_HAS_CALL_OBJECT
|
||||
/* for Call Object 'real' getter isn't passed in to us */
|
||||
if (OBJ_GET_CLASS(cx, obj) == &js_CallClass &&
|
||||
OBJ_GET_CLASS(cx, obj)->getProperty == sprop->getter)
|
||||
pd->flags |= JSPD_ARGUMENT;
|
||||
#endif /* JS_HAS_CALL_OBJECT */
|
||||
pd->spare = 0;
|
||||
pd->slot = (pd->flags & (JSPD_ARGUMENT | JSPD_VARIABLE))
|
||||
? JSVAL_TO_INT(sprop->id)
|
||||
: 0;
|
||||
if (!sym || !sym->next || (pd->flags & (JSPD_ARGUMENT | JSPD_VARIABLE))) {
|
||||
pd->alias = JSVAL_VOID;
|
||||
} else {
|
||||
pd->alias = js_IdToValue(sym_id(sym->next));
|
||||
pd->flags |= JSPD_ALIAS;
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_GetPropertyDescArray(JSContext *cx, JSObject *obj, JSPropertyDescArray *pda)
|
||||
{
|
||||
JSScope *scope;
|
||||
uint32 i, n;
|
||||
JSPropertyDesc *pd;
|
||||
JSScopeProperty *sprop;
|
||||
jsval state;
|
||||
jsid num_prop;
|
||||
|
||||
if (!OBJ_ENUMERATE(cx, obj, JSENUMERATE_INIT, &state, &num_prop))
|
||||
return JS_FALSE;
|
||||
scope = (JSScope *)obj->map;
|
||||
/* have no props, or object's scope has not mutated from that of proto */
|
||||
if (!scope->props ||
|
||||
(OBJ_GET_PROTO(cx,obj) &&
|
||||
scope == (JSScope *)(OBJ_GET_PROTO(cx,obj)->map))) {
|
||||
pda->length = 0;
|
||||
pda->array = NULL;
|
||||
return JS_TRUE;
|
||||
}
|
||||
n = scope->map.freeslot;
|
||||
pd = JS_malloc(cx, (size_t)n * sizeof(JSPropertyDesc));
|
||||
if (!pd)
|
||||
return JS_FALSE;
|
||||
i = 0;
|
||||
for (sprop = scope->props; sprop; sprop = sprop->next) {
|
||||
if (!js_AddRoot(cx, &pd[i].id, NULL))
|
||||
goto bad;
|
||||
if (!js_AddRoot(cx, &pd[i].value, NULL))
|
||||
goto bad;
|
||||
JS_GetPropertyDesc(cx, obj, sprop, &pd[i]);
|
||||
if ((pd[i].flags & JSPD_ALIAS) && !js_AddRoot(cx, &pd[i].alias, NULL))
|
||||
goto bad;
|
||||
if (++i == n)
|
||||
break;
|
||||
}
|
||||
pda->length = i;
|
||||
pda->array = pd;
|
||||
return JS_TRUE;
|
||||
|
||||
bad:
|
||||
pda->length = i + 1;
|
||||
pda->array = pd;
|
||||
JS_PutPropertyDescArray(cx, pda);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_PutPropertyDescArray(JSContext *cx, JSPropertyDescArray *pda)
|
||||
{
|
||||
JSPropertyDesc *pd;
|
||||
uint32 i;
|
||||
|
||||
pd = pda->array;
|
||||
for (i = 0; i < pda->length; i++) {
|
||||
js_RemoveRoot(cx, &pd[i].id);
|
||||
js_RemoveRoot(cx, &pd[i].value);
|
||||
if (pd[i].flags & JSPD_ALIAS)
|
||||
js_RemoveRoot(cx, &pd[i].alias);
|
||||
}
|
||||
JS_free(cx, pd);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_SetDebuggerHandler(JSRuntime *rt, JSTrapHandler handler, void *closure)
|
||||
{
|
||||
rt->debuggerHandler = handler;
|
||||
rt->debuggerHandlerData = closure;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_SetSourceHandler(JSRuntime *rt, JSSourceHandler handler, void *closure)
|
||||
{
|
||||
rt->sourceHandler = handler;
|
||||
rt->sourceHandlerData = closure;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_SetExecuteHook(JSRuntime *rt, JSInterpreterHook hook, void *closure)
|
||||
{
|
||||
rt->executeHook = hook;
|
||||
rt->executeHookData = closure;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_SetCallHook(JSRuntime *rt, JSInterpreterHook hook, void *closure)
|
||||
{
|
||||
rt->callHook = hook;
|
||||
rt->callHookData = closure;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_SetObjectHook(JSRuntime *rt, JSObjectHook hook, void *closure)
|
||||
{
|
||||
rt->objectHook = hook;
|
||||
rt->objectHookData = closure;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_SetThrowHook(JSRuntime *rt, JSTrapHandler hook, void *closure)
|
||||
{
|
||||
rt->throwHook = hook;
|
||||
rt->throwHookData = closure;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_SetDebugErrorHook(JSRuntime *rt, JSDebugErrorHook hook, void *closure)
|
||||
{
|
||||
rt->debugErrorHook = hook;
|
||||
rt->debugErrorHookData = closure;
|
||||
return JS_TRUE;
|
||||
}
|
||||
254
mozilla/js/src/jsdbgapi.h
Normal file
254
mozilla/js/src/jsdbgapi.h
Normal file
@@ -0,0 +1,254 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef jsdbgapi_h___
|
||||
#define jsdbgapi_h___
|
||||
/*
|
||||
* JS debugger API.
|
||||
*/
|
||||
#include "jsapi.h"
|
||||
#include "jsopcode.h"
|
||||
#include "jsprvtd.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
extern void
|
||||
js_PatchOpcode(JSContext *cx, JSScript *script, jsbytecode *pc, JSOp op);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
JSTrapHandler handler, void *closure);
|
||||
|
||||
extern JS_PUBLIC_API(JSOp)
|
||||
JS_GetTrapOpcode(JSContext *cx, JSScript *script, jsbytecode *pc);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_ClearTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
JSTrapHandler *handlerp, void **closurep);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_ClearScriptTraps(JSContext *cx, JSScript *script);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_ClearAllTraps(JSContext *cx);
|
||||
|
||||
extern JS_PUBLIC_API(JSTrapStatus)
|
||||
JS_HandleTrap(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetInterrupt(JSRuntime *rt, JSTrapHandler handler, void *closure);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_ClearInterrupt(JSRuntime *rt, JSTrapHandler *handlerp, void **closurep);
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval id,
|
||||
JSWatchPointHandler handler, void *closure);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_ClearWatchPoint(JSContext *cx, JSObject *obj, jsval id,
|
||||
JSWatchPointHandler *handlerp, void **closurep);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_ClearWatchPointsForObject(JSContext *cx, JSObject *obj);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_ClearAllWatchPoints(JSContext *cx);
|
||||
|
||||
#ifdef JS_HAS_OBJ_WATCHPOINT
|
||||
/*
|
||||
* Hide these non-API function prototypes by testing whether the internal
|
||||
* header file "jsconfig.h" has been included.
|
||||
*/
|
||||
extern JSScopeProperty *
|
||||
js_FindWatchPoint(JSRuntime *rt, JSObject *obj, jsval userid);
|
||||
|
||||
extern JSBool JS_DLL_CALLBACK
|
||||
js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
||||
#endif
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
extern JS_PUBLIC_API(uintN)
|
||||
JS_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc);
|
||||
|
||||
extern JS_PUBLIC_API(jsbytecode *)
|
||||
JS_LineNumberToPC(JSContext *cx, JSScript *script, uintN lineno);
|
||||
|
||||
extern JS_PUBLIC_API(JSScript *)
|
||||
JS_GetFunctionScript(JSContext *cx, JSFunction *fun);
|
||||
|
||||
extern JS_PUBLIC_API(JSPrincipals *)
|
||||
JS_GetScriptPrincipals(JSContext *cx, JSScript *script);
|
||||
|
||||
/*
|
||||
* Stack Frame Iterator
|
||||
*
|
||||
* Used to iterate through the JS stack frames to extract
|
||||
* information from the frames.
|
||||
*/
|
||||
|
||||
extern JS_PUBLIC_API(JSStackFrame *)
|
||||
JS_FrameIterator(JSContext *cx, JSStackFrame **iteratorp);
|
||||
|
||||
extern JS_PUBLIC_API(JSScript *)
|
||||
JS_GetFrameScript(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(jsbytecode *)
|
||||
JS_GetFramePC(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_IsNativeFrame(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(void *)
|
||||
JS_GetFrameAnnotation(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_SetFrameAnnotation(JSContext *cx, JSStackFrame *fp, void *annotation);
|
||||
|
||||
extern JS_PUBLIC_API(void *)
|
||||
JS_GetFramePrincipalArray(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
/* this is deprecated, use JS_GetFrameScopeChain instead */
|
||||
extern JS_PUBLIC_API(JSObject *)
|
||||
JS_GetFrameObject(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(JSObject *)
|
||||
JS_GetFrameScopeChain(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(JSObject *)
|
||||
JS_GetFrameCallObject(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(JSObject *)
|
||||
JS_GetFrameThis(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(JSFunction *)
|
||||
JS_GetFrameFunction(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_IsContructorFrame(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_IsDebuggerFrame(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(jsval)
|
||||
JS_GetFrameReturnValue(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_SetFrameReturnValue(JSContext *cx, JSStackFrame *fp, jsval rval);
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
extern JS_PUBLIC_API(const char *)
|
||||
JS_GetScriptFilename(JSContext *cx, JSScript *script);
|
||||
|
||||
extern JS_PUBLIC_API(uintN)
|
||||
JS_GetScriptBaseLineNumber(JSContext *cx, JSScript *script);
|
||||
|
||||
extern JS_PUBLIC_API(uintN)
|
||||
JS_GetScriptLineExtent(JSContext *cx, JSScript *script);
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
/*
|
||||
* Hook setters for script creation and destruction, see jsprvtd.h for the
|
||||
* typedefs. These macros provide binary compatibility and newer, shorter
|
||||
* synonyms.
|
||||
*/
|
||||
#define JS_SetNewScriptHook JS_SetNewScriptHookProc
|
||||
#define JS_SetDestroyScriptHook JS_SetDestroyScriptHookProc
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_SetNewScriptHook(JSRuntime *rt, JSNewScriptHook hook, void *callerdata);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_SetDestroyScriptHook(JSRuntime *rt, JSDestroyScriptHook hook,
|
||||
void *callerdata);
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_EvaluateInStackFrame(JSContext *cx, JSStackFrame *fp,
|
||||
const char *bytes, uintN length,
|
||||
const char *filename, uintN lineno,
|
||||
jsval *rval);
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
typedef struct JSPropertyDesc {
|
||||
jsval id; /* primary id, a string or int */
|
||||
jsval value; /* property value */
|
||||
uint8 flags; /* flags, see below */
|
||||
uint8 spare; /* unused */
|
||||
uint16 slot; /* argument/variable slot */
|
||||
jsval alias; /* alias id if JSPD_ALIAS flag */
|
||||
} JSPropertyDesc;
|
||||
|
||||
#define JSPD_ENUMERATE 0x01 /* visible to for/in loop */
|
||||
#define JSPD_READONLY 0x02 /* assignment is error */
|
||||
#define JSPD_PERMANENT 0x04 /* property cannot be deleted */
|
||||
#define JSPD_ALIAS 0x08 /* property has an alias id */
|
||||
#define JSPD_ARGUMENT 0x10 /* argument to function */
|
||||
#define JSPD_VARIABLE 0x20 /* local variable in function */
|
||||
|
||||
typedef struct JSPropertyDescArray {
|
||||
uint32 length; /* number of elements in array */
|
||||
JSPropertyDesc *array; /* alloc'd by Get, freed by Put */
|
||||
} JSPropertyDescArray;
|
||||
|
||||
extern JS_PUBLIC_API(JSScopeProperty *)
|
||||
JS_PropertyIterator(JSObject *obj, JSScopeProperty **iteratorp);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop,
|
||||
JSPropertyDesc *pd);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_GetPropertyDescArray(JSContext *cx, JSObject *obj, JSPropertyDescArray *pda);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_PutPropertyDescArray(JSContext *cx, JSPropertyDescArray *pda);
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetDebuggerHandler(JSRuntime *rt, JSTrapHandler handler, void *closure);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetSourceHandler(JSRuntime *rt, JSSourceHandler handler, void *closure);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetExecuteHook(JSRuntime *rt, JSInterpreterHook hook, void *closure);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetCallHook(JSRuntime *rt, JSInterpreterHook hook, void *closure);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetObjectHook(JSRuntime *rt, JSObjectHook hook, void *closure);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetThrowHook(JSRuntime *rt, JSTrapHandler hook, void *closure);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetDebugErrorHook(JSRuntime *rt, JSDebugErrorHook hook, void *closure);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsdbgapi_h___ */
|
||||
2611
mozilla/js/src/jsdtoa.c
Normal file
2611
mozilla/js/src/jsdtoa.c
Normal file
File diff suppressed because it is too large
Load Diff
54
mozilla/js/src/jsdtoa.h
Normal file
54
mozilla/js/src/jsdtoa.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef jsdtoa_h___
|
||||
#define jsdtoa_h___
|
||||
/*
|
||||
* Public interface to portable double-precision floating point to string
|
||||
* and back conversion package.
|
||||
*/
|
||||
|
||||
#include "jscompat.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
/*
|
||||
* JS_strtod() returns as a double-precision floating-point number
|
||||
* the value represented by the character string pointed to by
|
||||
* s00. The string is scanned up to the first unrecognized
|
||||
* character.
|
||||
* If the value of se is not (char **)NULL, a pointer to
|
||||
* the character terminating the scan is returned in the location pointed
|
||||
* to by se. If no number can be formed, se is set to s00r, and
|
||||
* zero is returned.
|
||||
*/
|
||||
JS_FRIEND_API(double)
|
||||
JS_strtod(const char *s00, char **se);
|
||||
|
||||
/*
|
||||
* JS_cnvtf()
|
||||
* conversion routines for floating point
|
||||
* prcsn - number of digits of precision to generate floating
|
||||
* point value.
|
||||
*/
|
||||
JS_FRIEND_API(void)
|
||||
JS_cnvtf(char *buf, intN bufsz, intN prcsn, double dval);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsdtoa_h___ */
|
||||
2539
mozilla/js/src/jsemit.c
Normal file
2539
mozilla/js/src/jsemit.c
Normal file
File diff suppressed because it is too large
Load Diff
369
mozilla/js/src/jsemit.h
Normal file
369
mozilla/js/src/jsemit.h
Normal file
@@ -0,0 +1,369 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef jsemit_h___
|
||||
#define jsemit_h___
|
||||
/*
|
||||
* JS bytecode generation.
|
||||
*/
|
||||
|
||||
#include "jsstddef.h"
|
||||
#include "jstypes.h"
|
||||
#include "jsatom.h"
|
||||
#include "jsopcode.h"
|
||||
#include "jsprvtd.h"
|
||||
#include "jspubtd.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
typedef enum JSStmtType {
|
||||
STMT_BLOCK = 0, /* compound statement: { s1[;... sN] } */
|
||||
STMT_LABEL = 1, /* labeled statement: l: s */
|
||||
STMT_IF = 2, /* if (then) statement */
|
||||
STMT_ELSE = 3, /* else statement */
|
||||
STMT_SWITCH = 4, /* switch statement */
|
||||
STMT_WITH = 5, /* with statement */
|
||||
STMT_TRY = 6, /* try statement */
|
||||
STMT_CATCH = 7, /* catch block */
|
||||
STMT_FINALLY = 8, /* finally statement */
|
||||
STMT_DO_LOOP = 9, /* do/while loop statement */
|
||||
STMT_FOR_LOOP = 10, /* for loop statement */
|
||||
STMT_FOR_IN_LOOP = 11, /* for/in loop statement */
|
||||
STMT_WHILE_LOOP = 12 /* while loop statement */
|
||||
} JSStmtType;
|
||||
|
||||
#define STMT_IS_LOOP(stmt) ((stmt)->type >= STMT_DO_LOOP)
|
||||
|
||||
typedef struct JSStmtInfo JSStmtInfo;
|
||||
|
||||
struct JSStmtInfo {
|
||||
JSStmtType type; /* statement type */
|
||||
ptrdiff_t top; /* offset of loop top from cg base */
|
||||
ptrdiff_t update; /* loop update offset (top if none) */
|
||||
ptrdiff_t breaks; /* offset of last break in loop */
|
||||
ptrdiff_t continues; /* offset of last continue in loop */
|
||||
JSAtom *label; /* label name if type is STMT_LABEL */
|
||||
JSStmtInfo *down; /* info for enclosing statement */
|
||||
};
|
||||
|
||||
#define SET_STATEMENT_TOP(stmt, top) \
|
||||
((stmt)->top = (stmt)->update = (top), (stmt)->breaks = (stmt)->continues = (-1))
|
||||
|
||||
struct JSTreeContext { /* tree context for semantic checks */
|
||||
uint32 flags; /* statement state flags, see below */
|
||||
uint32 tryCount; /* total count of try statements parsed */
|
||||
JSStmtInfo *topStmt; /* top of statement info stack */
|
||||
};
|
||||
|
||||
#define TCF_IN_FUNCTION 0x01 /* parsing inside function body */
|
||||
#define TCF_RETURN_EXPR 0x02 /* function has 'return expr;' */
|
||||
#define TCF_RETURN_VOID 0x04 /* function has 'return;' */
|
||||
#define TCF_IN_FOR_INIT 0x08 /* parsing init expr of for; exclude 'in' */
|
||||
|
||||
#define TREE_CONTEXT_INIT(tc) \
|
||||
((tc)->flags = 0, (tc)->tryCount = 0, (tc)->topStmt = NULL)
|
||||
|
||||
struct JSCodeGenerator {
|
||||
void *codeMark; /* low watermark in cx->codePool */
|
||||
void *tempMark; /* low watermark in cx->tempPool */
|
||||
jsbytecode *base; /* base of JS bytecode vector */
|
||||
jsbytecode *limit; /* one byte beyond end of bytecode */
|
||||
jsbytecode *next; /* pointer to next free bytecode */
|
||||
const char *filename; /* null or weak link to source filename */
|
||||
uintN firstLine; /* first line, for js_NewScriptFromCG */
|
||||
uintN currentLine; /* line number for tree-based srcnote gen */
|
||||
JSPrincipals *principals; /* principals for constant folding eval */
|
||||
JSTreeContext treeContext; /* for break/continue code generation */
|
||||
JSAtomList atomList; /* literals indexed for mapping */
|
||||
intN stackDepth; /* current stack depth in basic block */
|
||||
uintN maxStackDepth; /* maximum stack depth so far */
|
||||
jssrcnote *notes; /* source notes, see below */
|
||||
uintN noteCount; /* number of source notes so far */
|
||||
ptrdiff_t lastNoteOffset; /* code offset for last source note */
|
||||
JSTryNote *tryBase; /* first exception handling note */
|
||||
JSTryNote *tryNext; /* next available note */
|
||||
size_t tryNoteSpace; /* # of bytes allocated at tryBase */
|
||||
};
|
||||
|
||||
#define CG_CODE(cg,offset) ((cg)->base + (offset))
|
||||
#define CG_OFFSET(cg) PTRDIFF((cg)->next, (cg)->base, jsbytecode)
|
||||
|
||||
/*
|
||||
* Initialize cg to allocate bytecode space from cx->codePool, and srcnote
|
||||
* space from cx->tempPool. Return true on success. Report an error and
|
||||
* return false if the initial code segment can't be allocated.
|
||||
*/
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
js_InitCodeGenerator(JSContext *cx, JSCodeGenerator *cg,
|
||||
const char *filename, uintN lineno,
|
||||
JSPrincipals *principals);
|
||||
|
||||
/*
|
||||
* Release cx->codePool and cx->tempPool to marks set by js_InitCodeGenerator.
|
||||
* Note that cgs are magic: they own tempPool and codePool "tops-of-stack"
|
||||
* above their codeMark and tempMark points. This means you cannot alloc
|
||||
* from tempPool and save the pointer beyond the next JS_FinishCodeGenerator.
|
||||
*/
|
||||
extern JS_FRIEND_API(void)
|
||||
js_FinishCodeGenerator(JSContext *cx, JSCodeGenerator *cg);
|
||||
|
||||
/*
|
||||
* Emit one bytecode.
|
||||
*/
|
||||
extern ptrdiff_t
|
||||
js_Emit1(JSContext *cx, JSCodeGenerator *cg, JSOp op);
|
||||
|
||||
/*
|
||||
* Emit two bytecodes, an opcode (op) with a byte of immediate operand (op1).
|
||||
*/
|
||||
extern ptrdiff_t
|
||||
js_Emit2(JSContext *cx, JSCodeGenerator *cg, JSOp op, jsbytecode op1);
|
||||
|
||||
/*
|
||||
* Emit three bytecodes, an opcode with two bytes of immediate operands.
|
||||
*/
|
||||
extern ptrdiff_t
|
||||
js_Emit3(JSContext *cx, JSCodeGenerator *cg, JSOp op, jsbytecode op1,
|
||||
jsbytecode op2);
|
||||
|
||||
/*
|
||||
* Emit (1 + extra) bytecodes, for N bytes of op and its immediate operand.
|
||||
*/
|
||||
extern ptrdiff_t
|
||||
js_EmitN(JSContext *cx, JSCodeGenerator *cg, JSOp op, size_t extra);
|
||||
|
||||
/*
|
||||
* Unsafe macro to call js_SetJumpOffset and return false if it does.
|
||||
*/
|
||||
#define CHECK_AND_SET_JUMP_OFFSET(cx,cg,pc,off) \
|
||||
JS_BEGIN_MACRO \
|
||||
if (!js_SetJumpOffset(cx, cg, pc, off)) \
|
||||
return JS_FALSE; \
|
||||
JS_END_MACRO
|
||||
|
||||
#define CHECK_AND_SET_JUMP_OFFSET_AT(cx,cg,off) \
|
||||
CHECK_AND_SET_JUMP_OFFSET(cx, cg, CG_CODE(cg,off), CG_OFFSET(cg) - (off))
|
||||
|
||||
extern JSBool
|
||||
js_SetJumpOffset(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc,
|
||||
ptrdiff_t off);
|
||||
|
||||
/*
|
||||
* Push the C-stack-allocated struct at stmt onto the stmtInfo stack.
|
||||
*/
|
||||
extern void
|
||||
js_PushStatement(JSTreeContext *tc, JSStmtInfo *stmt, JSStmtType type,
|
||||
ptrdiff_t top);
|
||||
|
||||
/*
|
||||
* Emit a break instruction, recording it for backpatching.
|
||||
*/
|
||||
extern ptrdiff_t
|
||||
js_EmitBreak(JSContext *cx, JSCodeGenerator *cg, JSStmtInfo *stmt,
|
||||
JSAtomListElement *label);
|
||||
|
||||
/*
|
||||
* Emit a continue instruction, recording it for backpatching.
|
||||
*/
|
||||
extern ptrdiff_t
|
||||
js_EmitContinue(JSContext *cx, JSCodeGenerator *cg, JSStmtInfo *stmt,
|
||||
JSAtomListElement *label);
|
||||
|
||||
/*
|
||||
* Pop tc->topStmt. If the top JSStmtInfo struct is not stack-allocated, it
|
||||
* is up to the caller to free it.
|
||||
*/
|
||||
extern void
|
||||
js_PopStatement(JSTreeContext *tc);
|
||||
|
||||
/*
|
||||
* Like js_PopStatement(&cg->treeContext), also patch breaks and continues.
|
||||
* May fail if a jump offset overflows.
|
||||
*/
|
||||
extern JSBool
|
||||
js_PopStatementCG(JSContext *cx, JSCodeGenerator *cg);
|
||||
|
||||
/*
|
||||
* Emit code into cg for the tree rooted at pn.
|
||||
*/
|
||||
extern JSBool
|
||||
js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn);
|
||||
|
||||
/*
|
||||
* Emit code into cg for the tree rooted at body, then create a persistent
|
||||
* script for fun from cg.
|
||||
*/
|
||||
extern JSBool
|
||||
js_EmitFunctionBody(JSContext *cx, JSCodeGenerator *cg, JSParseNode *body,
|
||||
JSFunction *fun);
|
||||
|
||||
/*
|
||||
* Source notes generated along with bytecode for decompiling and debugging.
|
||||
* A source note is a uint8 with 5 bits of type and 3 of offset from the pc of
|
||||
* the previous note. If 3 bits of offset aren't enough, extended delta notes
|
||||
* (SRC_XDELTA) consisting of 2 set high order bits followed by 6 offset bits
|
||||
* are emitted before the next note. Some notes have operand offsets encoded
|
||||
* immediately after them, in note bytes or byte-triples.
|
||||
*
|
||||
* At most one "gettable" note (i.e., a note of type other than SRC_NEWLINE,
|
||||
* SRC_SETLINE, and SRC_XDELTA) applies to a given bytecode.
|
||||
*
|
||||
* NB: the js_SrcNoteName and js_SrcNoteArity arrays in jsemit.c are indexed
|
||||
* by this enum, so their initializers need to match the order here.
|
||||
*/
|
||||
typedef enum JSSrcNoteType {
|
||||
SRC_NULL = 0, /* terminates a note vector */
|
||||
SRC_IF = 1, /* JSOP_IFEQ bytecode is from an if-then */
|
||||
SRC_IF_ELSE = 2, /* JSOP_IFEQ bytecode is from an if-then-else */
|
||||
SRC_WHILE = 3, /* JSOP_IFEQ is from a while loop */
|
||||
SRC_FOR = 4, /* JSOP_NOP or JSOP_POP in for loop head */
|
||||
SRC_CONTINUE = 5, /* JSOP_GOTO is a continue, not a break;
|
||||
also used on JSOP_ENDINIT if extra comma
|
||||
at end of array literal: [1,2,,] */
|
||||
SRC_VAR = 6, /* JSOP_NAME/FORNAME with a var declaration */
|
||||
SRC_PCDELTA = 7, /* offset from comma-operator to next POP,
|
||||
or from CONDSWITCH to first CASE opcode */
|
||||
SRC_ASSIGNOP = 8, /* += or another assign-op follows */
|
||||
SRC_COND = 9, /* JSOP_IFEQ is from conditional ?: operator */
|
||||
SRC_PAREN = 10, /* JSOP_NOP generated to mark user parens */
|
||||
SRC_HIDDEN = 11, /* opcode shouldn't be decompiled */
|
||||
SRC_PCBASE = 12, /* offset of first obj.prop.subprop bytecode */
|
||||
SRC_LABEL = 13, /* JSOP_NOP for label: with atomid immediate */
|
||||
SRC_LABELBRACE = 14, /* JSOP_NOP for label: {...} begin brace */
|
||||
SRC_ENDBRACE = 15, /* JSOP_NOP for label: {...} end brace */
|
||||
SRC_BREAK2LABEL = 16, /* JSOP_GOTO for 'break label' with atomid */
|
||||
SRC_CONT2LABEL = 17, /* JSOP_GOTO for 'continue label' with atomid */
|
||||
SRC_SWITCH = 18, /* JSOP_*SWITCH with offset to end of switch,
|
||||
2nd off to first JSOP_CASE if condswitch */
|
||||
SRC_FUNCDEF = 19, /* JSOP_NOP for function f() with atomid */
|
||||
SRC_TRYFIN = 20, /* JSOP_NOP for try or finally section */
|
||||
SRC_CATCH = 21, /* catch block has guard */
|
||||
SRC_NEWLINE = 22, /* bytecode follows a source newline */
|
||||
SRC_SETLINE = 23, /* a file-absolute source line number note */
|
||||
SRC_XDELTA = 24 /* 24-31 are for extended delta notes */
|
||||
} JSSrcNoteType;
|
||||
|
||||
#define SN_TYPE_BITS 5
|
||||
#define SN_DELTA_BITS 3
|
||||
#define SN_XDELTA_BITS 6
|
||||
#define SN_TYPE_MASK (JS_BITMASK(SN_TYPE_BITS) << SN_DELTA_BITS)
|
||||
#define SN_DELTA_MASK ((ptrdiff_t)JS_BITMASK(SN_DELTA_BITS))
|
||||
#define SN_XDELTA_MASK ((ptrdiff_t)JS_BITMASK(SN_XDELTA_BITS))
|
||||
|
||||
#define SN_MAKE_NOTE(sn,t,d) (*(sn) = (jssrcnote) \
|
||||
(((t) << SN_DELTA_BITS) \
|
||||
| ((d) & SN_DELTA_MASK)))
|
||||
#define SN_MAKE_XDELTA(sn,d) (*(sn) = (jssrcnote) \
|
||||
((SRC_XDELTA << SN_DELTA_BITS) \
|
||||
| ((d) & SN_XDELTA_MASK)))
|
||||
|
||||
#define SN_IS_XDELTA(sn) ((*(sn) >> SN_DELTA_BITS) >= SRC_XDELTA)
|
||||
#define SN_TYPE(sn) (SN_IS_XDELTA(sn) ? SRC_XDELTA \
|
||||
: *(sn) >> SN_DELTA_BITS)
|
||||
#define SN_SET_TYPE(sn,type) SN_MAKE_NOTE(sn, type, SN_DELTA(sn))
|
||||
#define SN_IS_GETTABLE(sn) (SN_TYPE(sn) < SRC_NEWLINE)
|
||||
|
||||
#define SN_DELTA(sn) ((ptrdiff_t)(SN_IS_XDELTA(sn) \
|
||||
? *(sn) & SN_XDELTA_MASK \
|
||||
: *(sn) & SN_DELTA_MASK))
|
||||
#define SN_SET_DELTA(sn,delta) (SN_IS_XDELTA(sn) \
|
||||
? SN_MAKE_XDELTA(sn, delta) \
|
||||
: SN_MAKE_NOTE(sn, SN_TYPE(sn), delta))
|
||||
|
||||
#define SN_DELTA_LIMIT ((ptrdiff_t)JS_BIT(SN_DELTA_BITS))
|
||||
#define SN_XDELTA_LIMIT ((ptrdiff_t)JS_BIT(SN_XDELTA_BITS))
|
||||
|
||||
/*
|
||||
* Offset fields follow certain notes and are frequency-encoded: an offset in
|
||||
* [0,0x7f] consumes one byte, an offset in [0x80,0x7fffff] takes three, and
|
||||
* the high bit of the first byte is set.
|
||||
*/
|
||||
#define SN_3BYTE_OFFSET_FLAG 0x80
|
||||
#define SN_3BYTE_OFFSET_MASK 0x7f
|
||||
|
||||
extern JS_FRIEND_DATA(const char *) js_SrcNoteName[];
|
||||
extern JS_FRIEND_DATA(uint8) js_SrcNoteArity[];
|
||||
extern JS_FRIEND_API(uintN) js_SrcNoteLength(jssrcnote *sn);
|
||||
|
||||
#define SN_LENGTH(sn) ((js_SrcNoteArity[SN_TYPE(sn)] == 0) ? 1 \
|
||||
: js_SrcNoteLength(sn))
|
||||
#define SN_NEXT(sn) ((sn) + SN_LENGTH(sn))
|
||||
|
||||
/* A source note array is terminated by an all-zero element. */
|
||||
#define SN_MAKE_TERMINATOR(sn) (*(sn) = SRC_NULL)
|
||||
#define SN_IS_TERMINATOR(sn) (*(sn) == SRC_NULL)
|
||||
|
||||
/*
|
||||
* Append a new source note of the given type (and therefore size) to cg's
|
||||
* notes dynamic array, updating cg->noteCount. Return the new note's index
|
||||
* within the array pointed at by cg->notes. Return -1 if out of memory.
|
||||
*/
|
||||
extern intN
|
||||
js_NewSrcNote(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type);
|
||||
|
||||
extern intN
|
||||
js_NewSrcNote2(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type,
|
||||
ptrdiff_t offset);
|
||||
|
||||
extern intN
|
||||
js_NewSrcNote3(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type,
|
||||
ptrdiff_t offset1, ptrdiff_t offset2);
|
||||
|
||||
/*
|
||||
* Get and set the offset operand identified by which (0 for the first, etc.).
|
||||
*/
|
||||
extern JS_FRIEND_API(ptrdiff_t)
|
||||
js_GetSrcNoteOffset(jssrcnote *sn, uintN which);
|
||||
|
||||
extern JSBool
|
||||
js_SetSrcNoteOffset(JSContext *cx, JSCodeGenerator *cg, uintN index,
|
||||
uintN which, ptrdiff_t offset);
|
||||
|
||||
/*
|
||||
* Finish taking source notes in cx's tempPool by copying them to new
|
||||
* stable store allocated via JS_malloc. Return null on malloc failure,
|
||||
* which means this function reported an error.
|
||||
*/
|
||||
extern jssrcnote *
|
||||
js_FinishTakingSrcNotes(JSContext *cx, JSCodeGenerator *cg);
|
||||
|
||||
/*
|
||||
* Allocate cg->treeContext.tryCount notes (plus one for the end sentinel)
|
||||
* from cx->tempPool and set up cg->tryBase/tryNext for exactly tryCount
|
||||
* js_NewTryNote calls. The storage is freed by js_FinishCodeGenerator.
|
||||
*/
|
||||
extern JSBool
|
||||
js_AllocTryNotes(JSContext *cx, JSCodeGenerator *cg);
|
||||
|
||||
/*
|
||||
* Grab the next trynote slot in cg, filling it in appropriately.
|
||||
*/
|
||||
extern JSTryNote *
|
||||
js_NewTryNote(JSContext *cx, JSCodeGenerator *cg, ptrdiff_t start,
|
||||
ptrdiff_t end, ptrdiff_t catchStart);
|
||||
|
||||
/*
|
||||
* Finish generating exception information, and copy it to JS_malloc
|
||||
* storage.
|
||||
*/
|
||||
extern JSBool
|
||||
js_FinishTakingTryNotes(JSContext *cx, JSCodeGenerator *cg, JSTryNote **tryp);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsemit_h___ */
|
||||
619
mozilla/js/src/jsexn.c
Normal file
619
mozilla/js/src/jsexn.c
Normal file
@@ -0,0 +1,619 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* JS standard exception implementation.
|
||||
*/
|
||||
|
||||
#include "jsstddef.h"
|
||||
#include "jstypes.h"
|
||||
#include "jsutil.h" /* Added by JSIFY */
|
||||
#include "jsprf.h"
|
||||
#include "jsapi.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsconfig.h"
|
||||
#include "jsexn.h"
|
||||
#include "jsfun.h"
|
||||
|
||||
#if JS_HAS_ERROR_EXCEPTIONS
|
||||
#if !JS_HAS_EXCEPTIONS
|
||||
# error "JS_HAS_EXCEPTIONS must be defined to use JS_HAS_ERROR_EXCEPTIONS"
|
||||
#endif
|
||||
|
||||
/* Declaration to resolve circular reference of exn_class by Exception. */
|
||||
static JSBool
|
||||
Exception(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
|
||||
|
||||
static void
|
||||
exn_finalize(JSContext *cx, JSObject *obj);
|
||||
|
||||
static JSClass exn_class = {
|
||||
"Exception",
|
||||
JSCLASS_HAS_PRIVATE,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, exn_finalize,
|
||||
NULL, NULL, NULL, Exception
|
||||
};
|
||||
|
||||
/*
|
||||
* A copy of the JSErrorReport originally generated.
|
||||
*/
|
||||
typedef struct JSExnPrivate {
|
||||
JSErrorReport *errorReport;
|
||||
} JSExnPrivate;
|
||||
|
||||
/*
|
||||
* Copy everything interesting about an error into allocated memory.
|
||||
*/
|
||||
static JSExnPrivate *
|
||||
exn_initPrivate(JSContext *cx, JSErrorReport *report)
|
||||
{
|
||||
JSExnPrivate *newPrivate;
|
||||
JSErrorReport *newReport;
|
||||
|
||||
newPrivate = (JSExnPrivate *)JS_malloc(cx, sizeof (JSExnPrivate));
|
||||
|
||||
/* Copy the error report */
|
||||
newReport = (JSErrorReport *)JS_malloc(cx, sizeof (JSErrorReport));
|
||||
|
||||
if (report->filename != NULL) {
|
||||
newReport->filename =
|
||||
(const char *)JS_malloc(cx, strlen(report->filename)+1);
|
||||
strcpy((char *)newReport->filename, report->filename);
|
||||
} else {
|
||||
newReport->filename = NULL;
|
||||
}
|
||||
|
||||
newReport->lineno = report->lineno;
|
||||
|
||||
/*
|
||||
* We don't need to copy linebuf and tokenptr, because they
|
||||
* point into the deflated string cache. (currently?)
|
||||
*/
|
||||
newReport->linebuf = report->linebuf;
|
||||
newReport->tokenptr = report->tokenptr;
|
||||
|
||||
/*
|
||||
* But we do need to copy uclinebuf, uctokenptr, because they're
|
||||
* pointers into internal tokenstream structs, and may go away.
|
||||
*
|
||||
* NOTE nothing uses this and I'm not really maintaining it until
|
||||
* I know it's the desired API.
|
||||
*
|
||||
* Temporarily disabled, because uclinebuf is 0x10 when I evaluate 'Math()'!
|
||||
*/
|
||||
#if 0
|
||||
if (report->uclinebuf != NULL) {
|
||||
len = js_strlen(report->uclinebuf) + 1;
|
||||
newReport->uclinebuf =
|
||||
(const jschar *)JS_malloc(cx, len * sizeof(jschar));
|
||||
js_strncpy(newReport->uclinebuf, report->uclinebuf, len);
|
||||
newReport->uctokenptr = newReport->uclinebuf + (report->uctokenptr -
|
||||
report->uclinebuf);
|
||||
} else
|
||||
#endif
|
||||
newReport->uclinebuf = newReport->uctokenptr = NULL;
|
||||
|
||||
/* Executing the code below makes a seg fault where JS_malloc fails!? */
|
||||
#if 0
|
||||
if (report->ucmessage != NULL) {
|
||||
len = js_strlen(report->ucmessage) + 1;
|
||||
newReport->ucmessage = (const jschar *)JS_malloc(cx, len);
|
||||
js_strncpy((jschar *)newReport->ucmessage, report->ucmessage, len);
|
||||
|
||||
if (report->messageArgs) {
|
||||
int i;
|
||||
|
||||
for (i = 0; report->messageArgs[i] != NULL; i++)
|
||||
;
|
||||
JS_ASSERT(i);
|
||||
newReport->messageArgs =
|
||||
(const jschar **)JS_malloc(cx, (i + 1) * sizeof(jschar *));
|
||||
for (i = 0; report->messageArgs[i] != NULL; i++) {
|
||||
len = js_strlen(report->messageArgs[i]) + 1;
|
||||
newReport->messageArgs[i] =
|
||||
(const jschar *)JS_malloc(cx, len * sizeof(jschar));
|
||||
js_strncpy((jschar *)(newReport->messageArgs[i]),
|
||||
report->messageArgs[i], len);
|
||||
}
|
||||
report->messageArgs[i] = NULL;
|
||||
} else {
|
||||
report->messageArgs = NULL;
|
||||
}
|
||||
} else {
|
||||
newReport->ucmessage = NULL;
|
||||
newReport->messageArgs = NULL;
|
||||
}
|
||||
#else
|
||||
newReport->ucmessage = NULL;
|
||||
newReport->messageArgs = NULL;
|
||||
#endif
|
||||
|
||||
/* Note that this is before it gets flagged with JSREPORT_EXCEPTION */
|
||||
newReport->flags = report->flags;
|
||||
|
||||
newPrivate->errorReport = newReport;
|
||||
return newPrivate;
|
||||
}
|
||||
|
||||
/*
|
||||
* Undo all the damage done by exn_initPrivate.
|
||||
*/
|
||||
static void
|
||||
exn_destroyPrivate(JSContext *cx, JSExnPrivate *privateData)
|
||||
{
|
||||
JSErrorReport *report;
|
||||
const jschar **args;
|
||||
|
||||
report = privateData->errorReport;
|
||||
JS_ASSERT(report);
|
||||
if (report->uclinebuf)
|
||||
JS_free(cx, (void *)report->uclinebuf);
|
||||
if (report->filename)
|
||||
JS_free(cx, (void *)report->filename);
|
||||
if (report->ucmessage)
|
||||
JS_free(cx, (void *)report->ucmessage);
|
||||
if (report->ucmessage)
|
||||
JS_free(cx, (void *)report->ucmessage);
|
||||
if (report->messageArgs) {
|
||||
args = report->messageArgs;
|
||||
while(*args++ != NULL)
|
||||
JS_free(cx, (void *)*args);
|
||||
JS_free(cx, (void *)report->messageArgs);
|
||||
}
|
||||
JS_free(cx, report);
|
||||
JS_free(cx, privateData);
|
||||
}
|
||||
|
||||
static void
|
||||
exn_finalize(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JSExnPrivate *privateData;
|
||||
jsval private;
|
||||
|
||||
private = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
|
||||
|
||||
if (private != JSVAL_NULL) {
|
||||
privateData = JSVAL_TO_PRIVATE(private);
|
||||
if (privateData)
|
||||
exn_destroyPrivate(cx, privateData);
|
||||
}
|
||||
}
|
||||
|
||||
static JSErrorReport *
|
||||
js_ErrorFromException(JSContext *cx, jsval exn)
|
||||
{
|
||||
JSObject *obj;
|
||||
JSExnPrivate *privateData;
|
||||
jsval private;
|
||||
|
||||
if (!JSVAL_IS_OBJECT(exn))
|
||||
return NULL;
|
||||
obj = JSVAL_TO_OBJECT(exn);
|
||||
if (OBJ_GET_CLASS(cx, obj) != &exn_class)
|
||||
return NULL;
|
||||
private = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
|
||||
privateData = JSVAL_TO_PRIVATE(OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE));
|
||||
if (!privateData)
|
||||
return NULL;
|
||||
|
||||
JS_ASSERT(privateData->errorReport);
|
||||
return privateData->errorReport;
|
||||
}
|
||||
|
||||
/* This must be kept in synch with the exceptions array below. */
|
||||
typedef enum JSExnType {
|
||||
JSEXN_NONE = -1,
|
||||
JSEXN_EXCEPTION,
|
||||
JSEXN_ERR,
|
||||
JSEXN_INTERNALERR,
|
||||
JSEXN_SYNTAXERR,
|
||||
JSEXN_REFERENCEERR,
|
||||
JSEXN_CALLERR,
|
||||
JSEXN_TARGETERR,
|
||||
JSEXN_CONSTRUCTORERR,
|
||||
JSEXN_CONVERSIONERR,
|
||||
JSEXN_TOOBJECTERR,
|
||||
JSEXN_TOPRIMITIVEERR,
|
||||
JSEXN_DEFAULTVALUEERR,
|
||||
JSEXN_ARRAYERR,
|
||||
JSEXN_LIMIT
|
||||
} JSExnType;
|
||||
|
||||
struct JSExnSpec {
|
||||
int protoIndex;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
static struct JSExnSpec exceptions[] = {
|
||||
{ JSEXN_NONE, "Exception" },
|
||||
{ JSEXN_EXCEPTION, "Error" },
|
||||
{ JSEXN_ERR, "InternalError" },
|
||||
{ JSEXN_ERR, "SyntaxError" },
|
||||
{ JSEXN_ERR, "ReferenceError" },
|
||||
{ JSEXN_ERR, "CallError" },
|
||||
{ JSEXN_CALLERR, "TargetError" },
|
||||
{ JSEXN_ERR, "ConstructorError" },
|
||||
{ JSEXN_ERR, "ConversionError" },
|
||||
{ JSEXN_CONVERSIONERR, "ToObjectError" },
|
||||
{ JSEXN_CONVERSIONERR, "ToPrimitiveError" },
|
||||
{ JSEXN_CONVERSIONERR, "DefaultValueError" },
|
||||
{ JSEXN_ERR, "ArrayError" },
|
||||
{0}
|
||||
};
|
||||
|
||||
static JSBool
|
||||
Exception(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
JSString *message;
|
||||
|
||||
/*
|
||||
* Does it make sense to throw a not-a-function-error here?
|
||||
* A constructor that was not a function would be novel.
|
||||
*/
|
||||
if (!cx->fp->constructing) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* If it's a new object of class Exception, then null out the private
|
||||
* data so that the finalizer doesn't attempt to free it.
|
||||
*/
|
||||
if (OBJ_GET_CLASS(cx, obj) == &exn_class)
|
||||
OBJ_SET_SLOT(cx, obj, JSSLOT_PRIVATE, JSVAL_NULL);
|
||||
|
||||
/*
|
||||
* Set the 'message' property.
|
||||
*/
|
||||
if (argc > 0) {
|
||||
message = js_ValueToString(cx, argv[0]);
|
||||
if (!message)
|
||||
return JS_FALSE;
|
||||
} else {
|
||||
message = cx->runtime->emptyString;
|
||||
}
|
||||
if (!JS_DefineProperty(cx, obj, "message", STRING_TO_JSVAL(message),
|
||||
NULL, NULL, JSPROP_ENUMERATE));
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert to string.
|
||||
*
|
||||
* This method only uses JavaScript-modifiable properties name, message; it is
|
||||
* left to the host to check for private data and report filename and line
|
||||
* number information along with this message.
|
||||
*/
|
||||
static JSBool
|
||||
exn_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
jsval v;
|
||||
JSString *name, *message, *result;
|
||||
jschar *chars, *cp;
|
||||
size_t length;
|
||||
jsid id;
|
||||
|
||||
id = (jsid) cx->runtime->atomState.nameAtom;
|
||||
if (!OBJ_GET_PROPERTY(cx, obj, id, &v) || !(name = js_ValueToString(cx, v)))
|
||||
return JS_FALSE;
|
||||
|
||||
if (!JS_GetProperty(cx, obj, "message", &v) ||
|
||||
!(message = js_ValueToString(cx, v)))
|
||||
return JS_FALSE;
|
||||
|
||||
if (message->length > 0) {
|
||||
length = name->length + message->length + 2;
|
||||
cp = chars = JS_malloc(cx, (length + 1) * sizeof(jschar));
|
||||
if (!chars)
|
||||
return JS_FALSE;
|
||||
|
||||
js_strncpy(cp, name->chars, name->length);
|
||||
cp += name->length;
|
||||
*cp++ = ':'; *cp++ = ' ';
|
||||
js_strncpy(cp, message->chars, message->length);
|
||||
cp += message->length;
|
||||
*cp = 0;
|
||||
|
||||
result = js_NewString(cx, chars, length, 0);
|
||||
if (!result) {
|
||||
JS_free(cx, chars);
|
||||
return JS_FALSE;
|
||||
}
|
||||
} else {
|
||||
result = name;
|
||||
}
|
||||
|
||||
*rval = STRING_TO_JSVAL(result);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
#if JS_HAS_TOSOURCE
|
||||
/*
|
||||
* Return a string that may eval to something similar to the original object.
|
||||
*/
|
||||
static JSBool
|
||||
exn_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
JSString *name, *message, *result;
|
||||
jschar *chars, *cp;
|
||||
jsid id;
|
||||
size_t length;
|
||||
jsval v;
|
||||
|
||||
id = (jsid) cx->runtime->atomState.nameAtom;
|
||||
if (!OBJ_GET_PROPERTY(cx, obj, id, &v) || !(name = js_ValueToString(cx, v)))
|
||||
return JS_FALSE;
|
||||
|
||||
if (!JS_GetProperty(cx, obj, "message", &v) ||
|
||||
!(message = js_ValueToString(cx, v)))
|
||||
return JS_FALSE;
|
||||
|
||||
length = (message->length > 0) ? name->length + message->length + 10
|
||||
: name->length + 8;
|
||||
|
||||
cp = chars = JS_malloc(cx, (length + 1) * sizeof(jschar));
|
||||
if (!chars)
|
||||
return JS_FALSE;
|
||||
|
||||
*cp++ = '('; *cp++ = 'n'; *cp++ = 'e'; *cp++ = 'w'; *cp++ = ' ';
|
||||
js_strncpy(cp, name->chars, name->length);
|
||||
cp += name->length;
|
||||
*cp++ = '(';
|
||||
if (message->length > 0) {
|
||||
*cp++ = '"';
|
||||
js_strncpy(cp, message->chars, message->length);
|
||||
cp += message->length;
|
||||
*cp++ = '"';
|
||||
}
|
||||
*cp++ = ')'; *cp++ = ')'; *cp = 0;
|
||||
|
||||
result = js_NewString(cx, chars, length, 0);
|
||||
if (!result) {
|
||||
JS_free(cx, chars);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
*rval = STRING_TO_JSVAL(result);
|
||||
return JS_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static JSFunctionSpec exception_methods[] = {
|
||||
#if JS_HAS_TOSOURCE
|
||||
{js_toSource_str, exn_toSource, 0},
|
||||
#endif
|
||||
{js_toString_str, exn_toString, 0},
|
||||
{0}
|
||||
};
|
||||
|
||||
JSObject *
|
||||
js_InitExceptionClasses(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
int i;
|
||||
JSObject *protos[JSEXN_LIMIT];
|
||||
|
||||
/* Initialize the prototypes first. */
|
||||
for (i = 0; exceptions[i].name != 0; i++) {
|
||||
JSAtom *atom;
|
||||
JSFunction *fun;
|
||||
JSString *nameString;
|
||||
int protoidx = exceptions[i].protoIndex;
|
||||
|
||||
/* Make the prototype for the current constructor name. */
|
||||
protos[i] = js_NewObject(cx, &exn_class,
|
||||
protoidx >= 0 ? protos[protoidx] : NULL,
|
||||
obj);
|
||||
if (!protos[i])
|
||||
return NULL;
|
||||
|
||||
atom = js_Atomize(cx, exceptions[i].name, strlen(exceptions[i].name), 0);
|
||||
|
||||
/* Make a constructor function for the current name. */
|
||||
fun = js_DefineFunction(cx, obj, atom, Exception, 1, 0);
|
||||
if (!fun)
|
||||
return NULL; /* XXX also remove named property from obj... */
|
||||
|
||||
/* Make this constructor make objects of class Exception. */
|
||||
fun->clasp = &exn_class;
|
||||
|
||||
/* Make the prototype and constructor links. */
|
||||
if (!js_SetClassPrototype(cx, fun->object, protos[i],
|
||||
JSPROP_READONLY | JSPROP_PERMANENT))
|
||||
return NULL;
|
||||
|
||||
/* proto bootstrap bit from JS_InitClass omitted. */
|
||||
nameString = JS_NewStringCopyZ(cx, exceptions[i].name);
|
||||
if (nameString == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Add the name property to the prototype. */
|
||||
if (!JS_DefineProperty(cx, protos[i], js_name_str,
|
||||
STRING_TO_JSVAL(nameString),
|
||||
NULL, NULL,
|
||||
JSPROP_ENUMERATE)) {
|
||||
/* release it? */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* So finalize knows whether to. */
|
||||
OBJ_SET_SLOT(cx, protos[i], JSSLOT_PRIVATE, JSVAL_NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add an empty message property. (To Exception.prototype only,
|
||||
* because this property will be the same for all the exception
|
||||
* protos.)
|
||||
*/
|
||||
if (!JS_DefineProperty(cx, protos[0], "message",
|
||||
STRING_TO_JSVAL(cx->runtime->emptyString),
|
||||
NULL, NULL, JSPROP_ENUMERATE))
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* Add methods only to Exception.prototype, because ostensibly all
|
||||
* exception types delegate to that.
|
||||
*/
|
||||
if (!JS_DefineFunctions(cx, protos[0], exception_methods))
|
||||
return NULL;
|
||||
|
||||
return protos[0];
|
||||
}
|
||||
|
||||
static JSExnType errorToExceptionNum[] = {
|
||||
#define MSG_DEF(name, number, count, exception, format) \
|
||||
exception,
|
||||
#include "js.msg"
|
||||
#undef MSG_DEF
|
||||
};
|
||||
|
||||
#if defined ( DEBUG_mccabe ) && defined ( PRINTNAMES )
|
||||
/* For use below... get character strings for error name and exception name */
|
||||
static struct exnname { char *name; char *exception; } errortoexnname[] = {
|
||||
#define MSG_DEF(name, number, count, exception, format) \
|
||||
{#name, #exception},
|
||||
#include "js.msg"
|
||||
#undef MSG_DEF
|
||||
};
|
||||
#endif /* DEBUG */
|
||||
|
||||
JSBool
|
||||
js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp)
|
||||
{
|
||||
JSErrNum errorNumber;
|
||||
JSObject *errObject, *errProto;
|
||||
JSExnType exn;
|
||||
JSExnPrivate *privateData;
|
||||
JSString *msgstr;
|
||||
|
||||
/* Find the exception index associated with this error. */
|
||||
JS_ASSERT(reportp);
|
||||
errorNumber = reportp->errorNumber;
|
||||
exn = errorToExceptionNum[errorNumber];
|
||||
JS_ASSERT(exn < JSEXN_LIMIT);
|
||||
|
||||
#if defined( DEBUG_mccabe ) && defined ( PRINTNAMES )
|
||||
/* Print the error name and the associated exception name to stderr */
|
||||
fprintf(stderr, "%s\t%s\n",
|
||||
errortoexnname[errorNumber].name,
|
||||
errortoexnname[errorNumber].exception);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Return false (no exception raised) if no exception is associated
|
||||
* with the given error number.
|
||||
*/
|
||||
if (exn == JSEXN_NONE)
|
||||
return JS_FALSE;
|
||||
|
||||
/*
|
||||
* Try to get an appropriate prototype by looking up the corresponding
|
||||
* exception constructor name in the current context. If the constructor
|
||||
* has been deleted or overwritten, this may fail or return NULL, and
|
||||
* js_NewObject will fall back to using Object.prototype.
|
||||
*/
|
||||
if (!js_GetClassPrototype(cx, exceptions[exn].name, &errProto))
|
||||
errProto = NULL;
|
||||
|
||||
/*
|
||||
* Use js_NewObject instead of js_ConstructObject, because
|
||||
* js_ConstructObject seems to require a frame.
|
||||
*/
|
||||
errObject = js_NewObject(cx, &exn_class, errProto, NULL);
|
||||
|
||||
/* Store 'message' as a javascript-visible value. */
|
||||
msgstr = JS_NewStringCopyZ(cx, message);
|
||||
if (!JS_DefineProperty(cx, errObject, "message", STRING_TO_JSVAL(msgstr),
|
||||
NULL, NULL,
|
||||
JSPROP_ENUMERATE))
|
||||
return JS_FALSE;
|
||||
|
||||
/*
|
||||
* Construct a new copy of the error report, and store it in the
|
||||
* exception objects' private data. We can't use the error report
|
||||
* handed in, because it's stack-allocated, and may point to transient
|
||||
* data in the JSTokenStream.
|
||||
*/
|
||||
privateData = exn_initPrivate(cx, reportp);
|
||||
OBJ_SET_SLOT(cx, errObject, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(privateData));
|
||||
|
||||
/* Set the generated Exception object as the current exception. */
|
||||
JS_SetPendingException(cx, OBJECT_TO_JSVAL(errObject));
|
||||
|
||||
/* Flag the error report passed in to indicate an exception was raised. */
|
||||
reportp->flags |= JSREPORT_EXCEPTION;
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
#endif /* JS_HAS_ERROR_EXCEPTIONS */
|
||||
|
||||
#if JS_HAS_EXCEPTIONS
|
||||
|
||||
extern JSBool
|
||||
js_ReportUncaughtException(JSContext *cx)
|
||||
{
|
||||
JSObject *exnObject;
|
||||
JSString *str;
|
||||
jsval exn;
|
||||
JSErrorReport *reportp;
|
||||
|
||||
if (!JS_IsExceptionPending(cx))
|
||||
return JS_FALSE;
|
||||
|
||||
if (!JS_GetPendingException(cx, &exn))
|
||||
return JS_FALSE;
|
||||
|
||||
/*
|
||||
* Because js_ValueToString below could error and an exception object
|
||||
* could become unrooted, we root it here.
|
||||
*/
|
||||
if (JSVAL_IS_OBJECT(exn)) {
|
||||
exnObject = JSVAL_TO_OBJECT(exn);
|
||||
if (!js_AddRoot(cx, exnObject, "exn.report.root"))
|
||||
return JS_FALSE;
|
||||
} else {
|
||||
exnObject = NULL;
|
||||
}
|
||||
str = js_ValueToString(cx, exn);
|
||||
|
||||
#if JS_HAS_ERROR_EXCEPTIONS
|
||||
reportp = js_ErrorFromException(cx, exn);
|
||||
#else
|
||||
reportp = NULL;
|
||||
#endif
|
||||
|
||||
if (reportp == NULL) {
|
||||
/*
|
||||
* XXXmccabe todo: Instead of doing this, synthesize an error report
|
||||
* struct that includes the filename, lineno where the exception was
|
||||
* originally thrown.
|
||||
*/
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_UNCAUGHT_EXCEPTION, js_GetStringBytes(str));
|
||||
} else {
|
||||
/* Flag the error as an exception. */
|
||||
reportp->flags |= JSREPORT_EXCEPTION;
|
||||
js_ReportErrorAgain(cx, js_GetStringBytes(str), reportp);
|
||||
}
|
||||
|
||||
if (exnObject != NULL)
|
||||
js_RemoveRoot(cx, exnObject);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
#endif /* JS_HAS_EXCEPTIONS */
|
||||
66
mozilla/js/src/jsexn.h
Normal file
66
mozilla/js/src/jsexn.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* JS runtime exception classes.
|
||||
*/
|
||||
|
||||
#ifndef jsexn_h___
|
||||
#define jsexn_h___
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
/*
|
||||
* Initialize exception object hierarchy.
|
||||
*/
|
||||
extern JSObject *
|
||||
js_InitExceptionClasses(JSContext *cx, JSObject *obj);
|
||||
|
||||
/*
|
||||
* Given a JSErrorReport, check to see if there is an exception associated with
|
||||
* the error number. If there is, then create an appropriate exception object,
|
||||
* set it as the pending exception, and set the JSREPORT_EXCEPTION flag on the
|
||||
* error report. Exception-aware host error reporters should probably ignore
|
||||
* error reports so flagged. Returns JS_TRUE if an associated exception is
|
||||
* found and set, JS_FALSE otherwise..
|
||||
*/
|
||||
extern JSBool
|
||||
js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp);
|
||||
|
||||
/*
|
||||
* Called if an api call to js_Execute or js_CallFunctionValue fails; calls the
|
||||
* error reporter with the error report associated with any uncaught exception
|
||||
* that has been raised. Returns true if there was an exception pending, and
|
||||
* the error reporter was actually called.
|
||||
*
|
||||
* The JSErrorReport * that the error reporter is called with is currently
|
||||
* associated with a JavaScript object, and is not guaranteed to persist after
|
||||
* the object is collected. Any persistent uses of the JSErrorReport contents
|
||||
* should make their own copy.
|
||||
*
|
||||
* The flags field of the JSErrorReport will have the JSREPORT_EXCEPTION flag
|
||||
* set; embeddings that want to silently propagate JavaScript exceptions to
|
||||
* other contexts may want to use an error reporter that ignores errors with
|
||||
* this flag.
|
||||
*/
|
||||
extern JSBool
|
||||
js_ReportUncaughtException(JSContext *cx);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsexn_h___ */
|
||||
2265
mozilla/js/src/jsfile.c
Normal file
2265
mozilla/js/src/jsfile.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
@@ -16,9 +16,12 @@
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "nsWinRegValue.h"
|
||||
#ifndef _jsfile_h__
|
||||
#define _jsfile_h__
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
extern JSObject*
|
||||
js_InitFileClass(JSContext *cx, JSObject* obj);
|
||||
|
||||
|
||||
PR_END_EXTERN_C
|
||||
#endif /* _jsfile_h__ */
|
||||
|
||||
1816
mozilla/js/src/jsfun.c
Normal file
1816
mozilla/js/src/jsfun.c
Normal file
File diff suppressed because it is too large
Load Diff
108
mozilla/js/src/jsfun.h
Normal file
108
mozilla/js/src/jsfun.h
Normal file
@@ -0,0 +1,108 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef jsfun_h___
|
||||
#define jsfun_h___
|
||||
/*
|
||||
* JS function definitions.
|
||||
*/
|
||||
#include "jsprvtd.h"
|
||||
#include "jspubtd.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
struct JSFunction {
|
||||
jsrefcount nrefs; /* number of referencing objects */
|
||||
JSObject *object; /* back-pointer to GC'ed object header */
|
||||
JSNative call; /* native method pointer or null */
|
||||
uint16 nargs; /* minimum number of actual arguments */
|
||||
uint16 extra; /* number of arg slots for local GC roots */
|
||||
uint16 nvars; /* number of local variables */
|
||||
uint8 flags; /* bound method and other flags, see jsapi.h */
|
||||
uint8 spare; /* reserved for future use */
|
||||
JSAtom *atom; /* name for diagnostics and decompiling */
|
||||
JSScript *script; /* interpreted bytecode descriptor or null */
|
||||
JSClass *clasp; /* this function is a constructor for objects
|
||||
* of this class */
|
||||
};
|
||||
|
||||
extern JSClass js_ArgumentsClass;
|
||||
extern JSClass js_CallClass;
|
||||
extern JSClass js_ClosureClass;
|
||||
/* JS_FRIEND_DATA so that JSVAL_IS_FUNCTION is callable from outside */
|
||||
extern JS_FRIEND_DATA(JSClass) js_FunctionClass;
|
||||
|
||||
/*
|
||||
* NB: jsapi.h and jsobj.h must be included before any call to this macro.
|
||||
*/
|
||||
#define JSVAL_IS_FUNCTION(cx, v) \
|
||||
(JSVAL_IS_OBJECT(v) && JSVAL_TO_OBJECT(v) && \
|
||||
OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == &js_FunctionClass)
|
||||
|
||||
extern JSBool
|
||||
js_IsIdentifier(JSString *str);
|
||||
|
||||
extern JSObject *
|
||||
js_InitFunctionClass(JSContext *cx, JSObject *obj);
|
||||
|
||||
extern JSBool
|
||||
js_InitArgsCallClosureClasses(JSContext *cx, JSObject *obj,
|
||||
JSObject *objProto);
|
||||
|
||||
extern JSFunction *
|
||||
js_NewFunction(JSContext *cx, JSObject *funobj, JSNative call, uintN nargs,
|
||||
uintN flags, JSObject *parent, JSAtom *atom);
|
||||
|
||||
extern JSBool
|
||||
js_LinkFunctionObject(JSContext *cx, JSFunction *fun, JSObject *object);
|
||||
|
||||
extern JSFunction *
|
||||
js_DefineFunction(JSContext *cx, JSObject *obj, JSAtom *atom, JSNative call,
|
||||
uintN nargs, uintN flags);
|
||||
|
||||
extern JSFunction *
|
||||
js_ValueToFunction(JSContext *cx, jsval *vp, JSBool constructing);
|
||||
|
||||
extern void
|
||||
js_ReportIsNotFunction(JSContext *cx, jsval *vp, JSBool constructing);
|
||||
|
||||
extern JSObject *
|
||||
js_GetCallObject(JSContext *cx, JSStackFrame *fp, JSObject *parent,
|
||||
JSObject *withobj);
|
||||
|
||||
extern JSBool
|
||||
js_PutCallObject(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JSBool
|
||||
js_GetCallVariable(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
||||
|
||||
extern JSBool
|
||||
js_SetCallVariable(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
||||
|
||||
extern JSObject *
|
||||
js_GetArgsObject(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JSBool
|
||||
js_PutArgsObject(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JSBool
|
||||
js_XDRFunction(JSXDRState *xdr, JSObject **objp);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsfun_h___ */
|
||||
918
mozilla/js/src/jsgc.c
Normal file
918
mozilla/js/src/jsgc.c
Normal file
@@ -0,0 +1,918 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* JS Mark-and-Sweep Garbage Collector.
|
||||
*
|
||||
* This GC allocates only fixed-sized things big enough to contain two words
|
||||
* (pointers) on any host architecture. It allocates from an arena pool (see
|
||||
* jsarena.h). It uses a parallel arena-pool array of flag bytes to hold the
|
||||
* mark bit, finalizer type index, etc.
|
||||
*
|
||||
* XXX swizzle page to freelist for better locality of reference
|
||||
*/
|
||||
#include "jsstddef.h"
|
||||
#include <stdlib.h> /* for free, called by JS_ARENA_DESTROY */
|
||||
#include <string.h> /* for memset, called by jsarena.h macros if DEBUG */
|
||||
#include "jstypes.h"
|
||||
#include "jsarena.h" /* Added by JSIFY */
|
||||
#include "jsutil.h" /* Added by JSIFY */
|
||||
#include "jshash.h" /* Added by JSIFY */
|
||||
#include "jsapi.h"
|
||||
#include "jsatom.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsfun.h"
|
||||
#include "jsgc.h"
|
||||
#include "jsinterp.h"
|
||||
#include "jslock.h"
|
||||
#include "jsnum.h"
|
||||
#include "jsobj.h"
|
||||
#include "jsscope.h"
|
||||
#include "jsscript.h"
|
||||
#include "jsstr.h"
|
||||
|
||||
/*
|
||||
* Arena sizes, the first must be a multiple of the second so the two arena
|
||||
* pools can be maintained (in particular, arenas may be destroyed from the
|
||||
* middle of each pool) in parallel.
|
||||
*/
|
||||
#define GC_ARENA_SIZE 8192 /* 1024 (512 on Alpha) objects */
|
||||
#define GC_FLAGS_SIZE (GC_ARENA_SIZE / sizeof(JSGCThing))
|
||||
#define GC_ROOTS_SIZE 256 /* SWAG, small enough to amortize */
|
||||
|
||||
static JSHashNumber gc_hash_root(const void *key);
|
||||
|
||||
struct JSGCThing {
|
||||
JSGCThing *next;
|
||||
uint8 *flagp;
|
||||
};
|
||||
|
||||
typedef void (*GCFinalizeOp)(JSContext *cx, JSGCThing *thing);
|
||||
|
||||
static GCFinalizeOp gc_finalizers[GCX_NTYPES];
|
||||
|
||||
#ifdef JS_GCMETER
|
||||
#define METER(x) x
|
||||
#else
|
||||
#define METER(x) /* nothing */
|
||||
#endif
|
||||
|
||||
JSBool
|
||||
js_InitGC(JSRuntime *rt, uint32 maxbytes)
|
||||
{
|
||||
if (!gc_finalizers[GCX_OBJECT]) {
|
||||
gc_finalizers[GCX_OBJECT] = (GCFinalizeOp)js_FinalizeObject;
|
||||
gc_finalizers[GCX_STRING] = (GCFinalizeOp)js_FinalizeString;
|
||||
gc_finalizers[GCX_DOUBLE] = (GCFinalizeOp)js_FinalizeDouble;
|
||||
}
|
||||
|
||||
JS_InitArenaPool(&rt->gcArenaPool, "gc-arena", GC_ARENA_SIZE,
|
||||
sizeof(JSGCThing));
|
||||
JS_InitArenaPool(&rt->gcFlagsPool, "gc-flags", GC_FLAGS_SIZE,
|
||||
sizeof(uint8));
|
||||
rt->gcRootsHash = JS_NewHashTable(GC_ROOTS_SIZE, gc_hash_root,
|
||||
JS_CompareValues, JS_CompareValues,
|
||||
NULL, NULL);
|
||||
if (!rt->gcRootsHash)
|
||||
return JS_FALSE;
|
||||
rt->gcMaxBytes = maxbytes;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
#ifdef JS_GCMETER
|
||||
void
|
||||
js_DumpGCStats(JSRuntime *rt, FILE *fp)
|
||||
{
|
||||
fprintf(fp, "\nGC allocation statistics:\n");
|
||||
fprintf(fp, " bytes currently allocated: %lu\n", rt->gcBytes);
|
||||
fprintf(fp, " alloc attempts: %lu\n", rt->gcStats.alloc);
|
||||
fprintf(fp, " GC freelist length: %lu\n", rt->gcStats.freelen);
|
||||
fprintf(fp, " recycles through GC freelist: %lu\n", rt->gcStats.recycle);
|
||||
fprintf(fp, "alloc retries after running GC: %lu\n", rt->gcStats.retry);
|
||||
fprintf(fp, " allocation failures: %lu\n", rt->gcStats.fail);
|
||||
fprintf(fp, " valid lock calls: %lu\n", rt->gcStats.lock);
|
||||
fprintf(fp, " valid unlock calls: %lu\n", rt->gcStats.unlock);
|
||||
fprintf(fp, " locks that hit stuck counts: %lu\n", rt->gcStats.stuck);
|
||||
fprintf(fp, " unlocks that saw stuck counts: %lu\n", rt->gcStats.unstuck);
|
||||
fprintf(fp, " mark recursion depth: %lu\n", rt->gcStats.depth);
|
||||
fprintf(fp, " maximum mark recursion depth: %lu\n", rt->gcStats.maxdepth);
|
||||
fprintf(fp, " maximum GC nesting level: %lu\n", rt->gcStats.maxlevel);
|
||||
fprintf(fp, " potentially useful GC calls: %lu\n", rt->gcStats.poke);
|
||||
fprintf(fp, " useless GC calls: %lu\n", rt->gcStats.nopoke);
|
||||
fprintf(fp, " thing arena corruption: %lu\n", rt->gcStats.badarena);
|
||||
fprintf(fp, " flags arena corruption: %lu\n", rt->gcStats.badflag);
|
||||
fprintf(fp, " thing arenas freed so far: %lu\n", rt->gcStats.afree);
|
||||
fprintf(fp, " flags arenas freed so far: %lu\n", rt->gcStats.fafree);
|
||||
#ifdef JS_ARENAMETER
|
||||
JS_DumpArenaStats(fp);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
js_FinishGC(JSRuntime *rt)
|
||||
{
|
||||
#ifdef JS_ARENAMETER
|
||||
JS_DumpArenaStats(stdout);
|
||||
#endif
|
||||
#ifdef JS_GCMETER
|
||||
js_DumpGCStats(rt, stdout);
|
||||
#endif
|
||||
JS_FinishArenaPool(&rt->gcArenaPool);
|
||||
JS_FinishArenaPool(&rt->gcFlagsPool);
|
||||
JS_ArenaFinish();
|
||||
JS_HashTableDestroy(rt->gcRootsHash);
|
||||
rt->gcRootsHash = NULL;
|
||||
rt->gcFreeList = NULL;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_AddRoot(JSContext *cx, void *rp, const char *name)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
JSBool ok;
|
||||
|
||||
rt = cx->runtime;
|
||||
JS_LOCK_GC_VOID(rt,
|
||||
ok = (JS_HashTableAdd(rt->gcRootsHash, rp, (void *)name) != NULL));
|
||||
if (!ok)
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return ok;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_RemoveRoot(JSContext *cx, void *rp)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
|
||||
rt = cx->runtime;
|
||||
JS_LOCK_GC_VOID(rt, JS_HashTableRemove(rt->gcRootsHash, rp));
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
void *
|
||||
js_AllocGCThing(JSContext *cx, uintN flags)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
JSGCThing *thing;
|
||||
uint8 *flagp = NULL;
|
||||
#ifdef TOO_MUCH_GC
|
||||
JSBool tried_gc = JS_TRUE;
|
||||
js_GC(cx);
|
||||
#else
|
||||
JSBool tried_gc = JS_FALSE;
|
||||
#endif
|
||||
|
||||
rt = cx->runtime;
|
||||
JS_LOCK_GC(rt);
|
||||
METER(rt->gcStats.alloc++);
|
||||
retry:
|
||||
thing = rt->gcFreeList;
|
||||
if (thing) {
|
||||
rt->gcFreeList = thing->next;
|
||||
flagp = thing->flagp;
|
||||
METER(rt->gcStats.freelen--);
|
||||
METER(rt->gcStats.recycle++);
|
||||
} else {
|
||||
if (rt->gcBytes < rt->gcMaxBytes) {
|
||||
JS_ARENA_ALLOCATE(thing, &rt->gcArenaPool, sizeof(JSGCThing));
|
||||
JS_ARENA_ALLOCATE(flagp, &rt->gcFlagsPool, sizeof(uint8));
|
||||
}
|
||||
if (!thing || !flagp) {
|
||||
if (thing)
|
||||
JS_ARENA_RELEASE(&rt->gcArenaPool, thing);
|
||||
if (!tried_gc) {
|
||||
JS_UNLOCK_GC(rt);
|
||||
js_GC(cx);
|
||||
tried_gc = JS_TRUE;
|
||||
JS_LOCK_GC(rt);
|
||||
METER(rt->gcStats.retry++);
|
||||
goto retry;
|
||||
}
|
||||
METER(rt->gcStats.fail++);
|
||||
JS_UNLOCK_GC(rt);
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
*flagp = (uint8)flags;
|
||||
rt->gcBytes += sizeof(JSGCThing) + sizeof(uint8);
|
||||
cx->newborn[flags & GCF_TYPEMASK] = thing;
|
||||
|
||||
/*
|
||||
* Clear thing before unlocking in case a GC run is about to scan it,
|
||||
* finding it via cx->newborn[].
|
||||
*/
|
||||
thing->next = NULL;
|
||||
thing->flagp = NULL;
|
||||
JS_UNLOCK_GC(rt);
|
||||
return thing;
|
||||
}
|
||||
|
||||
static uint8 *
|
||||
gc_find_flags(JSRuntime *rt, void *thing)
|
||||
{
|
||||
jsuword index, offset, length;
|
||||
JSArena *a, *fa;
|
||||
|
||||
index = 0;
|
||||
for (a = rt->gcArenaPool.first.next; a; a = a->next) {
|
||||
offset = JS_UPTRDIFF(thing, a->base);
|
||||
length = a->avail - a->base;
|
||||
if (offset < length) {
|
||||
index += offset / sizeof(JSGCThing);
|
||||
for (fa = rt->gcFlagsPool.first.next; fa; fa = fa->next) {
|
||||
offset = fa->avail - fa->base;
|
||||
if (index < offset)
|
||||
return (uint8 *)fa->base + index;
|
||||
index -= offset;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
index += length / sizeof(JSGCThing);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_LockGCThing(JSContext *cx, void *thing)
|
||||
{
|
||||
uint8 *flagp, flags;
|
||||
|
||||
if (!thing)
|
||||
return JS_TRUE;
|
||||
flagp = gc_find_flags(cx->runtime, thing);
|
||||
if (!flagp)
|
||||
return JS_FALSE;
|
||||
flags = *flagp;
|
||||
if ((flags & GCF_LOCKMASK) != GCF_LOCKMASK) {
|
||||
*flagp = (uint8)(flags + GCF_LOCK);
|
||||
} else {
|
||||
METER(cx->runtime->gcStats.stuck++);
|
||||
}
|
||||
METER(cx->runtime->gcStats.lock++);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_UnlockGCThing(JSContext *cx, void *thing)
|
||||
{
|
||||
uint8 *flagp, flags;
|
||||
|
||||
if (!thing)
|
||||
return JS_TRUE;
|
||||
flagp = gc_find_flags(cx->runtime, thing);
|
||||
if (!flagp)
|
||||
return JS_FALSE;
|
||||
flags = *flagp;
|
||||
if ((flags & GCF_LOCKMASK) != GCF_LOCKMASK) {
|
||||
*flagp = (uint8)(flags - GCF_LOCK);
|
||||
} else {
|
||||
METER(cx->runtime->gcStats.unstuck++);
|
||||
}
|
||||
METER(cx->runtime->gcStats.unlock++);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
#ifdef GC_MARK_DEBUG
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "jsprf.h"
|
||||
|
||||
JS_FRIEND_DATA(FILE *) js_DumpGCHeap;
|
||||
JS_FRIEND_DATA(void *) js_LiveThingToFind;
|
||||
|
||||
typedef struct GCMarkNode GCMarkNode;
|
||||
|
||||
struct GCMarkNode {
|
||||
void *thing;
|
||||
char *name;
|
||||
GCMarkNode *next;
|
||||
GCMarkNode *prev;
|
||||
};
|
||||
|
||||
static void
|
||||
gc_dump_thing(JSGCThing *thing, uint8 flags, GCMarkNode *prev, FILE *fp)
|
||||
{
|
||||
GCMarkNode *next = NULL;
|
||||
char *path = NULL;
|
||||
JSObject *obj;
|
||||
JSClass *clasp;
|
||||
|
||||
while (prev) {
|
||||
next = prev;
|
||||
prev = prev->prev;
|
||||
}
|
||||
while (next) {
|
||||
path = JS_sprintf_append(path, "%s.", next->name);
|
||||
next = next->next;
|
||||
}
|
||||
if (!path)
|
||||
return;
|
||||
|
||||
fprintf(fp, "%08lx ", (long)thing);
|
||||
switch (flags & GCF_TYPEMASK) {
|
||||
case GCX_OBJECT:
|
||||
obj = (JSObject *)thing;
|
||||
clasp = JSVAL_TO_PRIVATE(obj->slots[JSSLOT_CLASS]);
|
||||
fprintf(fp, "object %s", clasp->name);
|
||||
break;
|
||||
case GCX_STRING:
|
||||
fprintf(fp, "string %s", JS_GetStringBytes((JSString *)thing));
|
||||
break;
|
||||
case GCX_DOUBLE:
|
||||
fprintf(fp, "double %g", *(jsdouble *)thing);
|
||||
break;
|
||||
case GCX_DECIMAL:
|
||||
break;
|
||||
}
|
||||
fprintf(fp, " via %s\n", path);
|
||||
free(path);
|
||||
}
|
||||
|
||||
static void
|
||||
gc_mark_node(JSRuntime *rt, void *thing, GCMarkNode *prev);
|
||||
|
||||
#define GC_MARK(_rt, _thing, _name, _prev) \
|
||||
JS_BEGIN_MACRO \
|
||||
GCMarkNode _node; \
|
||||
_node.thing = _thing; \
|
||||
_node.name = _name; \
|
||||
_node.next = NULL; \
|
||||
_node.prev = _prev; \
|
||||
if (_prev) ((GCMarkNode *)(_prev))->next = &_node; \
|
||||
gc_mark_node(_rt, _thing, &_node); \
|
||||
JS_END_MACRO
|
||||
|
||||
static void
|
||||
gc_mark(JSRuntime *rt, void *thing)
|
||||
{
|
||||
GC_MARK(rt, thing, "atom", NULL);
|
||||
}
|
||||
|
||||
#define GC_MARK_ATOM(rt, atom, prev) gc_mark_atom(rt, atom, prev)
|
||||
#define GC_MARK_SCRIPT(rt, script, prev) gc_mark_script(rt, script, prev)
|
||||
|
||||
#else /* !GC_MARK_DEBUG */
|
||||
|
||||
#define GC_MARK(rt, thing, name, prev) gc_mark(rt, thing)
|
||||
#define GC_MARK_ATOM(rt, atom, prev) gc_mark_atom(rt, atom)
|
||||
#define GC_MARK_SCRIPT(rt, script, prev) gc_mark_script(rt, script)
|
||||
|
||||
static void
|
||||
gc_mark(JSRuntime *rt, void *thing);
|
||||
|
||||
#endif /* !GC_MARK_DEBUG */
|
||||
|
||||
static void
|
||||
gc_mark_atom(JSRuntime *rt, JSAtom *atom
|
||||
#ifdef GC_MARK_DEBUG
|
||||
, GCMarkNode *prev
|
||||
#endif
|
||||
)
|
||||
{
|
||||
jsval key;
|
||||
|
||||
if (!atom || atom->flags & ATOM_MARK)
|
||||
return;
|
||||
atom->flags |= ATOM_MARK;
|
||||
key = ATOM_KEY(atom);
|
||||
if (JSVAL_IS_GCTHING(key)) {
|
||||
#ifdef GC_MARK_DEBUG
|
||||
char name[32];
|
||||
|
||||
if (JSVAL_IS_STRING(key)) {
|
||||
JS_snprintf(name, sizeof name, "'%s'",
|
||||
JS_GetStringBytes(JSVAL_TO_STRING(key)));
|
||||
} else {
|
||||
JS_snprintf(name, sizeof name, "<%x>", key);
|
||||
}
|
||||
#endif
|
||||
GC_MARK(rt, JSVAL_TO_GCTHING(key), name, prev);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gc_mark_script(JSRuntime *rt, JSScript *script
|
||||
#ifdef GC_MARK_DEBUG
|
||||
, GCMarkNode *prev
|
||||
#endif
|
||||
)
|
||||
{
|
||||
JSAtomMap *map;
|
||||
uintN i, length;
|
||||
JSAtom **vector;
|
||||
|
||||
map = &script->atomMap;
|
||||
length = map->length;
|
||||
vector = map->vector;
|
||||
for (i = 0; i < length; i++)
|
||||
GC_MARK_ATOM(rt, vector[i], prev);
|
||||
}
|
||||
|
||||
static void
|
||||
#ifdef GC_MARK_DEBUG
|
||||
gc_mark_node(JSRuntime *rt, void *thing, GCMarkNode *prev)
|
||||
#else
|
||||
gc_mark(JSRuntime *rt, void *thing)
|
||||
#endif
|
||||
{
|
||||
uint8 flags, *flagp;
|
||||
JSObject *obj;
|
||||
jsval v, *vp, *end;
|
||||
JSScope *scope;
|
||||
JSClass *clasp;
|
||||
JSScript *script;
|
||||
JSFunction *fun;
|
||||
JSScopeProperty *sprop;
|
||||
JSSymbol *sym;
|
||||
|
||||
if (!thing)
|
||||
return;
|
||||
flagp = gc_find_flags(rt, thing);
|
||||
if (!flagp)
|
||||
return;
|
||||
|
||||
/* Check for something on the GC freelist to handle recycled stack. */
|
||||
flags = *flagp;
|
||||
if (flags == GCF_FINAL)
|
||||
return;
|
||||
|
||||
#ifdef GC_MARK_DEBUG
|
||||
if (js_LiveThingToFind == thing)
|
||||
gc_dump_thing(thing, flags, prev, stderr);
|
||||
#endif
|
||||
|
||||
if (flags & GCF_MARK)
|
||||
return;
|
||||
*flagp |= GCF_MARK;
|
||||
METER(if (++rt->gcStats.depth > rt->gcStats.maxdepth)
|
||||
rt->gcStats.maxdepth = rt->gcStats.depth);
|
||||
|
||||
#ifdef GC_MARK_DEBUG
|
||||
if (js_DumpGCHeap)
|
||||
gc_dump_thing(thing, flags, prev, js_DumpGCHeap);
|
||||
#endif
|
||||
|
||||
if ((flags & GCF_TYPEMASK) == GCX_OBJECT) {
|
||||
obj = thing;
|
||||
vp = obj->slots;
|
||||
if (vp) {
|
||||
scope = OBJ_IS_NATIVE(obj) ? (JSScope *) obj->map : NULL;
|
||||
if (scope) {
|
||||
clasp = JSVAL_TO_PRIVATE(obj->slots[JSSLOT_CLASS]);
|
||||
|
||||
if (clasp == &js_ScriptClass) {
|
||||
v = vp[JSSLOT_PRIVATE];
|
||||
if (!JSVAL_IS_VOID(v)) {
|
||||
script = JSVAL_TO_PRIVATE(v);
|
||||
if (script)
|
||||
GC_MARK_SCRIPT(rt, script, prev);
|
||||
}
|
||||
}
|
||||
|
||||
if (clasp == &js_FunctionClass) {
|
||||
v = vp[JSSLOT_PRIVATE];
|
||||
if (!JSVAL_IS_VOID(v)) {
|
||||
fun = JSVAL_TO_PRIVATE(v);
|
||||
if (fun) {
|
||||
if (fun->atom)
|
||||
GC_MARK_ATOM(rt, fun->atom, prev);
|
||||
if (fun->script)
|
||||
GC_MARK_SCRIPT(rt, fun->script, prev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (sprop = scope->props; sprop; sprop = sprop->next) {
|
||||
for (sym = sprop->symbols; sym; sym = sym->next) {
|
||||
if (JSVAL_IS_INT(sym_id(sym)))
|
||||
continue;
|
||||
GC_MARK_ATOM(rt, sym_atom(sym), prev);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!scope || scope->object == obj)
|
||||
end = vp + obj->map->freeslot;
|
||||
else
|
||||
end = vp + JS_INITIAL_NSLOTS;
|
||||
for (; vp < end; vp++) {
|
||||
v = *vp;
|
||||
if (JSVAL_IS_GCTHING(v)) {
|
||||
#ifdef GC_MARK_DEBUG
|
||||
char name[32];
|
||||
|
||||
if (scope) {
|
||||
uint32 slot;
|
||||
jsval nval;
|
||||
|
||||
slot = vp - obj->slots;
|
||||
for (sprop = scope->props; ; sprop = sprop->next) {
|
||||
if (!sprop) {
|
||||
switch (slot) {
|
||||
case JSSLOT_PROTO:
|
||||
strcpy(name, "__proto__");
|
||||
break;
|
||||
case JSSLOT_PARENT:
|
||||
strcpy(name, "__parent__");
|
||||
break;
|
||||
case JSSLOT_PRIVATE:
|
||||
strcpy(name, "__private__");
|
||||
break;
|
||||
default:
|
||||
JS_snprintf(name, sizeof name,
|
||||
"**UNKNOWN SLOT %ld**",
|
||||
(long)slot);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (sprop->slot == slot) {
|
||||
nval = sprop->symbols
|
||||
? js_IdToValue(sym_id(sprop->symbols))
|
||||
: sprop->id;
|
||||
if (JSVAL_IS_INT(nval)) {
|
||||
JS_snprintf(name, sizeof name, "%ld",
|
||||
(long)JSVAL_TO_INT(nval));
|
||||
} else if (JSVAL_IS_STRING(nval)) {
|
||||
JS_snprintf(name, sizeof name, "%s",
|
||||
JS_GetStringBytes(JSVAL_TO_STRING(nval)));
|
||||
} else {
|
||||
strcpy(name, "**FINALIZED ATOM KEY**");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
GC_MARK(rt, JSVAL_TO_GCTHING(v), name, prev);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
METER(rt->gcStats.depth--);
|
||||
}
|
||||
|
||||
static JSHashNumber
|
||||
gc_hash_root(const void *key)
|
||||
{
|
||||
JSHashNumber num = (JSHashNumber) key; /* help lame MSVC1.5 on Win16 */
|
||||
|
||||
return num >> 2;
|
||||
}
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(intN)
|
||||
gc_root_marker(JSHashEntry *he, intN i, void *arg)
|
||||
{
|
||||
void **rp = (void **)he->key;
|
||||
|
||||
if (*rp) {
|
||||
#ifdef DEBUG
|
||||
JSArena *a;
|
||||
JSRuntime *rt = (JSRuntime *)arg;
|
||||
JSBool root_points_to_gcArenaPool = JS_FALSE;
|
||||
|
||||
if (rp && *rp) {
|
||||
for (a = rt->gcArenaPool.first.next; a; a = a->next) {
|
||||
if (*rp >= (void *)a->base && *rp <= (void *)a->avail) {
|
||||
root_points_to_gcArenaPool = JS_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
JS_ASSERT(root_points_to_gcArenaPool);
|
||||
}
|
||||
#endif
|
||||
GC_MARK(arg, *rp, he->value ? he->value : "root", NULL);
|
||||
}
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
js_ForceGC(JSContext *cx)
|
||||
{
|
||||
cx->newborn[GCX_OBJECT] = NULL;
|
||||
cx->newborn[GCX_STRING] = NULL;
|
||||
cx->newborn[GCX_DOUBLE] = NULL;
|
||||
cx->runtime->gcPoke = JS_TRUE;
|
||||
js_GC(cx);
|
||||
JS_ArenaFinish();
|
||||
}
|
||||
|
||||
void
|
||||
js_GC(JSContext *cx)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
JSContext *iter, *acx;
|
||||
JSArena *a, *ma, *fa, **ap, **fap;
|
||||
jsval v, *vp, *sp;
|
||||
jsuword begin, end;
|
||||
JSStackFrame *fp, *chain;
|
||||
void *mark;
|
||||
uint8 flags, *flagp;
|
||||
JSGCThing *thing, *final, **flp, **oflp;
|
||||
GCFinalizeOp finalizer;
|
||||
JSBool a_all_clear, f_all_clear;
|
||||
|
||||
/*
|
||||
* XXX kludge for pre-ECMAv2 compile-time switch case expr eval, see
|
||||
* jsemit.c:js_EmitTree, under case TOK_SWITCH: (look for XXX).
|
||||
*/
|
||||
if (cx->gcDisabled)
|
||||
return;
|
||||
|
||||
rt = cx->runtime;
|
||||
#ifdef JS_THREADSAFE
|
||||
/* Avoid deadlock. */
|
||||
JS_ASSERT(!JS_IS_RUNTIME_LOCKED(rt));
|
||||
#endif
|
||||
|
||||
/* Let the API user decide to defer a GC if it wants to. */
|
||||
if (rt->gcCallback && !rt->gcCallback(cx, JSGC_BEGIN))
|
||||
return;
|
||||
|
||||
/* Lock out other GC allocator and collector invocations. */
|
||||
JS_LOCK_GC(rt);
|
||||
|
||||
/* Do nothing if no assignment has executed since the last GC. */
|
||||
if (!rt->gcPoke) {
|
||||
METER(rt->gcStats.nopoke++);
|
||||
JS_UNLOCK_GC(rt);
|
||||
return;
|
||||
}
|
||||
rt->gcPoke = JS_FALSE;
|
||||
METER(rt->gcStats.poke++);
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
/* Bump gcLevel and return rather than nest on this context. */
|
||||
if (cx->gcActive) {
|
||||
rt->gcLevel++;
|
||||
METER(if (rt->gcLevel > rt->gcStats.maxlevel)
|
||||
rt->gcStats.maxlevel = rt->gcLevel);
|
||||
if (rt->gcLevel > 1) {
|
||||
JS_UNLOCK_GC(rt);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we're in a request, indicate, temporarily, that we're inactive. */
|
||||
if (cx->requestDepth) {
|
||||
rt->requestCount--;
|
||||
JS_NOTIFY_REQUEST_DONE(rt);
|
||||
}
|
||||
|
||||
/* If another thread is already in GC, don't attempt GC; wait instead. */
|
||||
if (rt->gcLevel > 0) {
|
||||
while (rt->gcLevel > 0)
|
||||
JS_AWAIT_GC_DONE(rt);
|
||||
if (cx->requestDepth)
|
||||
rt->requestCount++;
|
||||
JS_UNLOCK_GC(rt);
|
||||
return;
|
||||
}
|
||||
|
||||
/* No other thread is in GC, so indicate that we're now in GC. */
|
||||
rt->gcLevel = 1;
|
||||
|
||||
/* Also indicate that GC is active on this context. */
|
||||
cx->gcActive = JS_TRUE;
|
||||
|
||||
/* Wait for all other requests to finish. */
|
||||
while (rt->requestCount > 0)
|
||||
JS_AWAIT_REQUEST_DONE(rt);
|
||||
|
||||
#else /* !JS_THREADSAFE */
|
||||
|
||||
/* Bump gcLevel and return rather than nest; the outer gc will restart. */
|
||||
rt->gcLevel++;
|
||||
METER(if (rt->gcLevel > rt->gcStats.maxlevel)
|
||||
rt->gcStats.maxlevel = rt->gcLevel);
|
||||
if (rt->gcLevel > 1)
|
||||
return;
|
||||
|
||||
#endif /* !JS_THREADSAFE */
|
||||
|
||||
/* Drop atoms held by the property cache, and clear property weak links. */
|
||||
js_FlushPropertyCache(cx);
|
||||
restart:
|
||||
rt->gcNumber++;
|
||||
|
||||
/* Mark phase. */
|
||||
JS_HashTableEnumerateEntries(rt->gcRootsHash, gc_root_marker, rt);
|
||||
js_MarkAtomState(&rt->atomState, gc_mark);
|
||||
iter = NULL;
|
||||
while ((acx = js_ContextIterator(rt, &iter)) != NULL) {
|
||||
/*
|
||||
* Iterate frame chain and dormant chains. Temporarily tack current
|
||||
* frame onto the head of the dormant list to ease iteration.
|
||||
*
|
||||
* (NOTE: see comment on this whole 'dormant' thing in js_Execute)
|
||||
*/
|
||||
chain = acx->fp;
|
||||
if (chain) {
|
||||
JS_ASSERT(!chain->dormantNext);
|
||||
chain->dormantNext = acx->dormantFrameChain;
|
||||
} else {
|
||||
chain = acx->dormantFrameChain;
|
||||
}
|
||||
for (fp=chain; fp; fp = chain = chain->dormantNext) {
|
||||
sp = fp->sp;
|
||||
if (sp) {
|
||||
for (a = acx->stackPool.first.next; a; a = a->next) {
|
||||
begin = a->base;
|
||||
end = a->avail;
|
||||
if (JS_UPTRDIFF(sp, begin) < JS_UPTRDIFF(end, begin))
|
||||
end = (jsuword)sp;
|
||||
for (vp = (jsval *)begin; vp < (jsval *)end; vp++) {
|
||||
v = *vp;
|
||||
if (JSVAL_IS_GCTHING(v))
|
||||
GC_MARK(rt, JSVAL_TO_GCTHING(v), "stack", NULL);
|
||||
}
|
||||
if (end == (jsuword)sp)
|
||||
break;
|
||||
}
|
||||
}
|
||||
do {
|
||||
GC_MARK(rt, fp->scopeChain, "scope chain", NULL);
|
||||
GC_MARK(rt, fp->thisp, "this", NULL);
|
||||
if (JSVAL_IS_GCTHING(fp->rval))
|
||||
GC_MARK(rt, JSVAL_TO_GCTHING(fp->rval), "rval", NULL);
|
||||
if (fp->callobj)
|
||||
GC_MARK(rt, fp->callobj, "call object", NULL);
|
||||
if (fp->argsobj)
|
||||
GC_MARK(rt, fp->argsobj, "arguments object", NULL);
|
||||
if (fp->script)
|
||||
GC_MARK_SCRIPT(rt, fp->script, NULL);
|
||||
if (fp->sharpArray)
|
||||
GC_MARK(rt, fp->sharpArray, "sharp array", NULL);
|
||||
} while ((fp = fp->down) != NULL);
|
||||
}
|
||||
/* cleanup temporary link */
|
||||
if (acx->fp)
|
||||
acx->fp->dormantNext = NULL;
|
||||
GC_MARK(rt, acx->globalObject, "global object", NULL);
|
||||
GC_MARK(rt, acx->newborn[GCX_OBJECT], "newborn object", NULL);
|
||||
GC_MARK(rt, acx->newborn[GCX_STRING], "newborn string", NULL);
|
||||
GC_MARK(rt, acx->newborn[GCX_DOUBLE], "newborn double", NULL);
|
||||
#if JS_HAS_EXCEPTIONS
|
||||
if (acx->throwing && JSVAL_IS_GCTHING(acx->exception))
|
||||
GC_MARK(rt, JSVAL_TO_GCTHING(acx->exception), "exception", NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Sweep phase. Mark in tempPool for release at label out:. */
|
||||
ma = cx->tempPool.current;
|
||||
mark = JS_ARENA_MARK(&cx->tempPool);
|
||||
js_SweepAtomState(&rt->atomState);
|
||||
fa = rt->gcFlagsPool.first.next;
|
||||
flagp = (uint8 *)fa->base;
|
||||
for (a = rt->gcArenaPool.first.next; a; a = a->next) {
|
||||
for (thing = (JSGCThing *)a->base; thing < (JSGCThing *)a->avail;
|
||||
thing++) {
|
||||
if (flagp >= (uint8 *)fa->avail) {
|
||||
fa = fa->next;
|
||||
JS_ASSERT(fa);
|
||||
if (!fa) {
|
||||
METER(rt->gcStats.badflag++);
|
||||
goto out;
|
||||
}
|
||||
flagp = (uint8 *)fa->base;
|
||||
}
|
||||
flags = *flagp;
|
||||
if (flags & GCF_MARK) {
|
||||
*flagp &= ~GCF_MARK;
|
||||
} else if (!(flags & (GCF_LOCKMASK | GCF_FINAL))) {
|
||||
JS_ARENA_ALLOCATE(final, &cx->tempPool, sizeof(JSGCThing));
|
||||
if (!final)
|
||||
goto out;
|
||||
final->next = thing;
|
||||
final->flagp = flagp;
|
||||
JS_ASSERT(rt->gcBytes >= sizeof(JSGCThing) + sizeof(uint8));
|
||||
rt->gcBytes -= sizeof(JSGCThing) + sizeof(uint8);
|
||||
}
|
||||
flagp++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Finalize phase. Don't hold the GC lock while running finalizers! */
|
||||
JS_UNLOCK_GC(rt);
|
||||
for (final = mark; ; final++) {
|
||||
if ((jsuword)final >= ma->avail) {
|
||||
ma = ma->next;
|
||||
if (!ma)
|
||||
break;
|
||||
final = (JSGCThing *)ma->base;
|
||||
}
|
||||
thing = final->next;
|
||||
flagp = final->flagp;
|
||||
flags = *flagp;
|
||||
finalizer = gc_finalizers[flags & GCF_TYPEMASK];
|
||||
if (finalizer) {
|
||||
*flagp |= GCF_FINAL;
|
||||
finalizer(cx, thing);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set flags to GCF_FINAL, signifying that thing is free, but don't
|
||||
* thread thing onto rt->gcFreeList. We need the GC lock to rebuild
|
||||
* the freelist below while also looking for free-able arenas.
|
||||
*/
|
||||
*flagp = GCF_FINAL;
|
||||
}
|
||||
JS_LOCK_GC(rt);
|
||||
|
||||
/* Free unused arenas and rebuild the freelist. */
|
||||
ap = &rt->gcArenaPool.first.next;
|
||||
a = *ap;
|
||||
if (!a)
|
||||
goto out;
|
||||
thing = (JSGCThing *)a->base;
|
||||
a_all_clear = f_all_clear = JS_TRUE;
|
||||
flp = oflp = &rt->gcFreeList;
|
||||
*flp = NULL;
|
||||
METER(rt->gcStats.freelen = 0);
|
||||
|
||||
fap = &rt->gcFlagsPool.first.next;
|
||||
while ((fa = *fap) != NULL) {
|
||||
/* XXX optimize by unrolling to use word loads */
|
||||
for (flagp = (uint8 *)fa->base; ; flagp++) {
|
||||
JS_ASSERT(a);
|
||||
if (!a) {
|
||||
METER(rt->gcStats.badarena++);
|
||||
goto out;
|
||||
}
|
||||
if (thing >= (JSGCThing *)a->avail) {
|
||||
if (a_all_clear) {
|
||||
JS_ARENA_DESTROY(&rt->gcArenaPool, a, ap);
|
||||
flp = oflp;
|
||||
METER(rt->gcStats.afree++);
|
||||
} else {
|
||||
ap = &a->next;
|
||||
a_all_clear = JS_TRUE;
|
||||
oflp = flp;
|
||||
}
|
||||
a = *ap;
|
||||
if (!a)
|
||||
break;
|
||||
thing = (JSGCThing *)a->base;
|
||||
}
|
||||
if (flagp >= (uint8 *)fa->avail)
|
||||
break;
|
||||
if (*flagp != GCF_FINAL) {
|
||||
a_all_clear = f_all_clear = JS_FALSE;
|
||||
} else {
|
||||
thing->flagp = flagp;
|
||||
*flp = thing;
|
||||
flp = &thing->next;
|
||||
METER(rt->gcStats.freelen++);
|
||||
}
|
||||
thing++;
|
||||
}
|
||||
if (f_all_clear) {
|
||||
JS_ARENA_DESTROY(&rt->gcFlagsPool, fa, fap);
|
||||
METER(rt->gcStats.fafree++);
|
||||
} else {
|
||||
fap = &fa->next;
|
||||
f_all_clear = JS_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Terminate the new freelist. */
|
||||
*flp = NULL;
|
||||
|
||||
out:
|
||||
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
||||
if (rt->gcLevel > 1) {
|
||||
rt->gcLevel = 1;
|
||||
goto restart;
|
||||
}
|
||||
rt->gcLevel = 0;
|
||||
rt->gcLastBytes = rt->gcBytes;
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
/* If we were invoked during a request, undo the temporary decrement. */
|
||||
if (cx->requestDepth)
|
||||
rt->requestCount++;
|
||||
cx->gcActive = JS_FALSE;
|
||||
JS_NOTIFY_GC_DONE(rt);
|
||||
JS_UNLOCK_GC(rt);
|
||||
#endif
|
||||
if (rt->gcCallback)
|
||||
(void) rt->gcCallback(cx, JSGC_END);
|
||||
}
|
||||
110
mozilla/js/src/jsgc.h
Normal file
110
mozilla/js/src/jsgc.h
Normal file
@@ -0,0 +1,110 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef jsgc_h___
|
||||
#define jsgc_h___
|
||||
/*
|
||||
* JS Garbage Collector.
|
||||
*/
|
||||
#include "jspubtd.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
/* GC thing type indexes. */
|
||||
#define GCX_OBJECT 0 /* JSObject */
|
||||
#define GCX_STRING 1 /* JSString */
|
||||
#define GCX_DOUBLE 2 /* jsdouble */
|
||||
#define GCX_DECIMAL 3 /* JSDecimal */
|
||||
#define GCX_NTYPES 4
|
||||
|
||||
/* GC flag definitions (type index goes in low bits). */
|
||||
#define GCF_TYPEMASK JS_BITMASK(2) /* use low bits for type */
|
||||
#define GCF_MARK JS_BIT(2) /* mark bit */
|
||||
#define GCF_FINAL JS_BIT(3) /* in finalization bit */
|
||||
#define GCF_LOCKBIT 4 /* lock bit shift and mask */
|
||||
#define GCF_LOCKMASK (JS_BITMASK(4) << GCF_LOCKBIT)
|
||||
#define GCF_LOCK JS_BIT(GCF_LOCKBIT) /* lock request bit in API */
|
||||
|
||||
#if 1
|
||||
/*
|
||||
* Since we're forcing a GC from JS_GC anyway, don't bother wasting cycles
|
||||
* loading oldval. XXX remove implied force, poke in addroot/removeroot, &c
|
||||
*/
|
||||
#define GC_POKE(cx, oldval) ((cx)->runtime->gcPoke = JS_TRUE)
|
||||
#else
|
||||
#define GC_POKE(cx, oldval) ((cx)->runtime->gcPoke = JSVAL_IS_GCTHING(oldval))
|
||||
#endif
|
||||
|
||||
extern JSBool
|
||||
js_InitGC(JSRuntime *rt, uint32 maxbytes);
|
||||
|
||||
extern void
|
||||
js_FinishGC(JSRuntime *rt);
|
||||
|
||||
extern JSBool
|
||||
js_AddRoot(JSContext *cx, void *rp, const char *name);
|
||||
|
||||
extern JSBool
|
||||
js_RemoveRoot(JSContext *cx, void *rp);
|
||||
|
||||
extern void *
|
||||
js_AllocGCThing(JSContext *cx, uintN flags);
|
||||
|
||||
extern JSBool
|
||||
js_LockGCThing(JSContext *cx, void *thing);
|
||||
|
||||
extern JSBool
|
||||
js_UnlockGCThing(JSContext *cx, void *thing);
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
js_ForceGC(JSContext *cx);
|
||||
|
||||
extern void
|
||||
js_GC(JSContext *cx);
|
||||
|
||||
#ifdef JS_GCMETER
|
||||
|
||||
typedef struct JSGCStats {
|
||||
uint32 alloc; /* number of allocation attempts */
|
||||
uint32 freelen; /* gcFreeList length */
|
||||
uint32 recycle; /* number of things recycled through gcFreeList */
|
||||
uint32 retry; /* allocation attempt retries after running the GC */
|
||||
uint32 fail; /* allocation failures */
|
||||
uint32 lock; /* valid lock calls */
|
||||
uint32 unlock; /* valid unlock calls */
|
||||
uint32 stuck; /* stuck reference counts seen by lock calls */
|
||||
uint32 unstuck; /* unlock calls that saw a stuck lock count */
|
||||
uint32 depth; /* mark recursion depth */
|
||||
uint32 maxdepth; /* maximum mark recursion depth */
|
||||
uint32 maxlevel; /* maximum GC nesting (indirect recursion) level */
|
||||
uint32 poke; /* number of potentially useful GC calls */
|
||||
uint32 nopoke; /* useless GC calls where js_PokeGC was not set */
|
||||
uint32 badarena; /* thing arena corruption */
|
||||
uint32 badflag; /* flags arena corruption */
|
||||
uint32 afree; /* thing arenas freed so far */
|
||||
uint32 fafree; /* flags arenas freed so far */
|
||||
} JSGCStats;
|
||||
|
||||
extern void
|
||||
js_DumpGCStats(JSRuntime *rt, FILE *fp);
|
||||
|
||||
#endif /* JS_GCMETER */
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsgc_h___ */
|
||||
450
mozilla/js/src/jshash.c
Normal file
450
mozilla/js/src/jshash.c
Normal file
@@ -0,0 +1,450 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* PR hash table package.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "jstypes.h"
|
||||
#include "jsbit.h"
|
||||
#include "jsutil.h" /* Added by JSIFY */
|
||||
#include "jshash.h" /* Added by JSIFY */
|
||||
|
||||
/* Compute the number of buckets in ht */
|
||||
#define NBUCKETS(ht) JS_BIT(JS_HASH_BITS - (ht)->shift)
|
||||
|
||||
/* The smallest table has 16 buckets */
|
||||
#define MINBUCKETSLOG2 4
|
||||
#define MINBUCKETS JS_BIT(MINBUCKETSLOG2)
|
||||
|
||||
/* Compute the maximum entries given n buckets that we will tolerate, ~90% */
|
||||
#define OVERLOADED(n) ((n) - ((n) >> 3))
|
||||
|
||||
/* Compute the number of entries below which we shrink the table by half */
|
||||
#define UNDERLOADED(n) (((n) > MINBUCKETS) ? ((n) >> 2) : 0)
|
||||
|
||||
/*
|
||||
** Stubs for default hash allocator ops.
|
||||
*/
|
||||
static void *
|
||||
DefaultAllocTable(void *pool, size_t size)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
static void
|
||||
DefaultFreeTable(void *pool, void *item)
|
||||
{
|
||||
free(item);
|
||||
}
|
||||
|
||||
static JSHashEntry *
|
||||
DefaultAllocEntry(void *pool, const void *key)
|
||||
{
|
||||
return malloc(sizeof(JSHashEntry));
|
||||
}
|
||||
|
||||
static void
|
||||
DefaultFreeEntry(void *pool, JSHashEntry *he, uintN flag)
|
||||
{
|
||||
if (flag == HT_FREE_ENTRY)
|
||||
free(he);
|
||||
}
|
||||
|
||||
static JSHashAllocOps defaultHashAllocOps = {
|
||||
DefaultAllocTable, DefaultFreeTable,
|
||||
DefaultAllocEntry, DefaultFreeEntry
|
||||
};
|
||||
|
||||
JS_EXPORT_API(JSHashTable *)
|
||||
JS_NewHashTable(uint32 n, JSHashFunction keyHash,
|
||||
JSHashComparator keyCompare, JSHashComparator valueCompare,
|
||||
JSHashAllocOps *allocOps, void *allocPriv)
|
||||
{
|
||||
JSHashTable *ht;
|
||||
size_t nb;
|
||||
|
||||
if (n <= MINBUCKETS) {
|
||||
n = MINBUCKETSLOG2;
|
||||
} else {
|
||||
n = JS_CeilingLog2(n);
|
||||
if ((int32)n < 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!allocOps) allocOps = &defaultHashAllocOps;
|
||||
|
||||
ht = (*allocOps->allocTable)(allocPriv, sizeof *ht);
|
||||
if (!ht)
|
||||
return NULL;
|
||||
memset(ht, 0, sizeof *ht);
|
||||
ht->shift = JS_HASH_BITS - n;
|
||||
n = JS_BIT(n);
|
||||
#if defined(XP_PC) && defined _MSC_VER && _MSC_VER <= 800
|
||||
if (n > 16000) {
|
||||
(*allocOps->freeTable)(allocPriv, ht);
|
||||
return NULL;
|
||||
}
|
||||
#endif /* WIN16 */
|
||||
nb = n * sizeof(JSHashEntry *);
|
||||
ht->buckets = (*allocOps->allocTable)(allocPriv, nb);
|
||||
if (!ht->buckets) {
|
||||
(*allocOps->freeTable)(allocPriv, ht);
|
||||
return NULL;
|
||||
}
|
||||
memset(ht->buckets, 0, nb);
|
||||
|
||||
ht->keyHash = keyHash;
|
||||
ht->keyCompare = keyCompare;
|
||||
ht->valueCompare = valueCompare;
|
||||
ht->allocOps = allocOps;
|
||||
ht->allocPriv = allocPriv;
|
||||
return ht;
|
||||
}
|
||||
|
||||
JS_EXPORT_API(void)
|
||||
JS_HashTableDestroy(JSHashTable *ht)
|
||||
{
|
||||
uint32 i, n;
|
||||
JSHashEntry *he, *next;
|
||||
JSHashAllocOps *allocOps = ht->allocOps;
|
||||
void *allocPriv = ht->allocPriv;
|
||||
|
||||
n = NBUCKETS(ht);
|
||||
for (i = 0; i < n; i++) {
|
||||
for (he = ht->buckets[i]; he; he = next) {
|
||||
next = he->next;
|
||||
(*allocOps->freeEntry)(allocPriv, he, HT_FREE_ENTRY);
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
memset(ht->buckets, 0xDB, n * sizeof ht->buckets[0]);
|
||||
#endif
|
||||
(*allocOps->freeTable)(allocPriv, ht->buckets);
|
||||
#ifdef DEBUG
|
||||
memset(ht, 0xDB, sizeof *ht);
|
||||
#endif
|
||||
(*allocOps->freeTable)(allocPriv, ht);
|
||||
}
|
||||
|
||||
/*
|
||||
** Multiplicative hash, from Knuth 6.4.
|
||||
*/
|
||||
JS_EXPORT_API(JSHashEntry **)
|
||||
JS_HashTableRawLookup(JSHashTable *ht, JSHashNumber keyHash, const void *key)
|
||||
{
|
||||
JSHashEntry *he, **hep, **hep0;
|
||||
JSHashNumber h;
|
||||
|
||||
#ifdef HASHMETER
|
||||
ht->nlookups++;
|
||||
#endif
|
||||
h = keyHash * JS_GOLDEN_RATIO;
|
||||
h >>= ht->shift;
|
||||
hep = hep0 = &ht->buckets[h];
|
||||
while ((he = *hep) != NULL) {
|
||||
if (he->keyHash == keyHash && (*ht->keyCompare)(key, he->key)) {
|
||||
/* Move to front of chain if not already there */
|
||||
if (hep != hep0) {
|
||||
*hep = he->next;
|
||||
he->next = *hep0;
|
||||
*hep0 = he;
|
||||
}
|
||||
return hep0;
|
||||
}
|
||||
hep = &he->next;
|
||||
#ifdef HASHMETER
|
||||
ht->nsteps++;
|
||||
#endif
|
||||
}
|
||||
return hep;
|
||||
}
|
||||
|
||||
JS_EXPORT_API(JSHashEntry *)
|
||||
JS_HashTableRawAdd(JSHashTable *ht, JSHashEntry **hep,
|
||||
JSHashNumber keyHash, const void *key, void *value)
|
||||
{
|
||||
uint32 i, n;
|
||||
JSHashEntry *he, *next, **oldbuckets;
|
||||
size_t nb;
|
||||
|
||||
/* Grow the table if it is overloaded */
|
||||
n = NBUCKETS(ht);
|
||||
if (ht->nentries >= OVERLOADED(n)) {
|
||||
#ifdef HASHMETER
|
||||
ht->ngrows++;
|
||||
#endif
|
||||
ht->shift--;
|
||||
oldbuckets = ht->buckets;
|
||||
#if defined(XP_PC) && defined _MSC_VER && _MSC_VER <= 800
|
||||
if (2 * n > 16000)
|
||||
return NULL;
|
||||
#endif /* WIN16 */
|
||||
nb = 2 * n * sizeof(JSHashEntry *);
|
||||
ht->buckets = (*ht->allocOps->allocTable)(ht->allocPriv, nb);
|
||||
if (!ht->buckets) {
|
||||
ht->buckets = oldbuckets;
|
||||
return NULL;
|
||||
}
|
||||
memset(ht->buckets, 0, nb);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
for (he = oldbuckets[i]; he; he = next) {
|
||||
next = he->next;
|
||||
hep = JS_HashTableRawLookup(ht, he->keyHash, he->key);
|
||||
JS_ASSERT(*hep == NULL);
|
||||
he->next = NULL;
|
||||
*hep = he;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
memset(oldbuckets, 0xDB, n * sizeof oldbuckets[0]);
|
||||
#endif
|
||||
(*ht->allocOps->freeTable)(ht->allocPriv, oldbuckets);
|
||||
hep = JS_HashTableRawLookup(ht, keyHash, key);
|
||||
}
|
||||
|
||||
/* Make a new key value entry */
|
||||
he = (*ht->allocOps->allocEntry)(ht->allocPriv, key);
|
||||
if (!he)
|
||||
return NULL;
|
||||
he->keyHash = keyHash;
|
||||
he->key = key;
|
||||
he->value = value;
|
||||
he->next = *hep;
|
||||
*hep = he;
|
||||
ht->nentries++;
|
||||
return he;
|
||||
}
|
||||
|
||||
JS_EXPORT_API(JSHashEntry *)
|
||||
JS_HashTableAdd(JSHashTable *ht, const void *key, void *value)
|
||||
{
|
||||
JSHashNumber keyHash;
|
||||
JSHashEntry *he, **hep;
|
||||
|
||||
keyHash = (*ht->keyHash)(key);
|
||||
hep = JS_HashTableRawLookup(ht, keyHash, key);
|
||||
if ((he = *hep) != NULL) {
|
||||
/* Hit; see if values match */
|
||||
if ((*ht->valueCompare)(he->value, value)) {
|
||||
/* key,value pair is already present in table */
|
||||
return he;
|
||||
}
|
||||
if (he->value)
|
||||
(*ht->allocOps->freeEntry)(ht->allocPriv, he, HT_FREE_VALUE);
|
||||
he->value = value;
|
||||
return he;
|
||||
}
|
||||
return JS_HashTableRawAdd(ht, hep, keyHash, key, value);
|
||||
}
|
||||
|
||||
JS_EXPORT_API(void)
|
||||
JS_HashTableRawRemove(JSHashTable *ht, JSHashEntry **hep, JSHashEntry *he)
|
||||
{
|
||||
uint32 i, n;
|
||||
JSHashEntry *next, **oldbuckets;
|
||||
size_t nb;
|
||||
|
||||
*hep = he->next;
|
||||
(*ht->allocOps->freeEntry)(ht->allocPriv, he, HT_FREE_ENTRY);
|
||||
|
||||
/* Shrink table if it's underloaded */
|
||||
n = NBUCKETS(ht);
|
||||
if (--ht->nentries < UNDERLOADED(n)) {
|
||||
#ifdef HASHMETER
|
||||
ht->nshrinks++;
|
||||
#endif
|
||||
ht->shift++;
|
||||
oldbuckets = ht->buckets;
|
||||
nb = n * sizeof(JSHashEntry*) / 2;
|
||||
ht->buckets = (*ht->allocOps->allocTable)(ht->allocPriv, nb);
|
||||
if (!ht->buckets) {
|
||||
ht->buckets = oldbuckets;
|
||||
return;
|
||||
}
|
||||
memset(ht->buckets, 0, nb);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
for (he = oldbuckets[i]; he; he = next) {
|
||||
next = he->next;
|
||||
hep = JS_HashTableRawLookup(ht, he->keyHash, he->key);
|
||||
JS_ASSERT(*hep == NULL);
|
||||
he->next = NULL;
|
||||
*hep = he;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
memset(oldbuckets, 0xDB, n * sizeof oldbuckets[0]);
|
||||
#endif
|
||||
(*ht->allocOps->freeTable)(ht->allocPriv, oldbuckets);
|
||||
}
|
||||
}
|
||||
|
||||
JS_EXPORT_API(JSBool)
|
||||
JS_HashTableRemove(JSHashTable *ht, const void *key)
|
||||
{
|
||||
JSHashNumber keyHash;
|
||||
JSHashEntry *he, **hep;
|
||||
|
||||
keyHash = (*ht->keyHash)(key);
|
||||
hep = JS_HashTableRawLookup(ht, keyHash, key);
|
||||
if ((he = *hep) == NULL)
|
||||
return JS_FALSE;
|
||||
|
||||
/* Hit; remove element */
|
||||
JS_HashTableRawRemove(ht, hep, he);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_EXPORT_API(void *)
|
||||
JS_HashTableLookup(JSHashTable *ht, const void *key)
|
||||
{
|
||||
JSHashNumber keyHash;
|
||||
JSHashEntry *he, **hep;
|
||||
|
||||
keyHash = (*ht->keyHash)(key);
|
||||
hep = JS_HashTableRawLookup(ht, keyHash, key);
|
||||
if ((he = *hep) != NULL) {
|
||||
return he->value;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
** Iterate over the entries in the hash table calling func for each
|
||||
** entry found. Stop if "f" says to (return value & JS_ENUMERATE_STOP).
|
||||
** Return a count of the number of elements scanned.
|
||||
*/
|
||||
JS_EXPORT_API(int)
|
||||
JS_HashTableEnumerateEntries(JSHashTable *ht, JSHashEnumerator f, void *arg)
|
||||
{
|
||||
JSHashEntry *he, **hep;
|
||||
uint32 i, nbuckets;
|
||||
int rv, n = 0;
|
||||
JSHashEntry *todo = NULL;
|
||||
|
||||
nbuckets = NBUCKETS(ht);
|
||||
for (i = 0; i < nbuckets; i++) {
|
||||
hep = &ht->buckets[i];
|
||||
while ((he = *hep) != NULL) {
|
||||
rv = (*f)(he, n, arg);
|
||||
n++;
|
||||
if (rv & (HT_ENUMERATE_REMOVE | HT_ENUMERATE_UNHASH)) {
|
||||
*hep = he->next;
|
||||
if (rv & HT_ENUMERATE_REMOVE) {
|
||||
he->next = todo;
|
||||
todo = he;
|
||||
}
|
||||
} else {
|
||||
hep = &he->next;
|
||||
}
|
||||
if (rv & HT_ENUMERATE_STOP) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
hep = &todo;
|
||||
while ((he = *hep) != NULL) {
|
||||
JS_HashTableRawRemove(ht, hep, he);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
#ifdef HASHMETER
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
JS_EXPORT_API(void)
|
||||
JS_HashTableDumpMeter(JSHashTable *ht, JSHashEnumerator dump, FILE *fp)
|
||||
{
|
||||
double mean, variance;
|
||||
uint32 nchains, nbuckets;
|
||||
uint32 i, n, maxChain, maxChainLen;
|
||||
JSHashEntry *he;
|
||||
|
||||
variance = 0;
|
||||
nchains = 0;
|
||||
maxChainLen = 0;
|
||||
nbuckets = NBUCKETS(ht);
|
||||
for (i = 0; i < nbuckets; i++) {
|
||||
he = ht->buckets[i];
|
||||
if (!he)
|
||||
continue;
|
||||
nchains++;
|
||||
for (n = 0; he; he = he->next)
|
||||
n++;
|
||||
variance += n * n;
|
||||
if (n > maxChainLen) {
|
||||
maxChainLen = n;
|
||||
maxChain = i;
|
||||
}
|
||||
}
|
||||
mean = (double)ht->nentries / nchains;
|
||||
variance = fabs(variance / nchains - mean * mean);
|
||||
|
||||
fprintf(fp, "\nHash table statistics:\n");
|
||||
fprintf(fp, " number of lookups: %u\n", ht->nlookups);
|
||||
fprintf(fp, " number of entries: %u\n", ht->nentries);
|
||||
fprintf(fp, " number of grows: %u\n", ht->ngrows);
|
||||
fprintf(fp, " number of shrinks: %u\n", ht->nshrinks);
|
||||
fprintf(fp, " mean steps per hash: %g\n", (double)ht->nsteps
|
||||
/ ht->nlookups);
|
||||
fprintf(fp, "mean hash chain length: %g\n", mean);
|
||||
fprintf(fp, " standard deviation: %g\n", sqrt(variance));
|
||||
fprintf(fp, " max hash chain length: %u\n", maxChainLen);
|
||||
fprintf(fp, " max hash chain: [%u]\n", maxChain);
|
||||
|
||||
for (he = ht->buckets[maxChain], i = 0; he; he = he->next, i++)
|
||||
if ((*dump)(he, i, fp) != HT_ENUMERATE_NEXT)
|
||||
break;
|
||||
}
|
||||
#endif /* HASHMETER */
|
||||
|
||||
JS_EXPORT_API(int)
|
||||
JS_HashTableDump(JSHashTable *ht, JSHashEnumerator dump, FILE *fp)
|
||||
{
|
||||
int count;
|
||||
|
||||
count = JS_HashTableEnumerateEntries(ht, dump, fp);
|
||||
#ifdef HASHMETER
|
||||
JS_HashTableDumpMeter(ht, dump, fp);
|
||||
#endif
|
||||
return count;
|
||||
}
|
||||
|
||||
JS_EXPORT_API(JSHashNumber)
|
||||
JS_HashString(const void *key)
|
||||
{
|
||||
JSHashNumber h;
|
||||
const unsigned char *s;
|
||||
|
||||
h = 0;
|
||||
for (s = key; *s; s++)
|
||||
h = (h >> 28) ^ (h << 4) ^ *s;
|
||||
return h;
|
||||
}
|
||||
|
||||
JS_EXPORT_API(int)
|
||||
JS_CompareValues(const void *v1, const void *v2)
|
||||
{
|
||||
return v1 == v2;
|
||||
}
|
||||
131
mozilla/js/src/jshash.h
Normal file
131
mozilla/js/src/jshash.h
Normal file
@@ -0,0 +1,131 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef jshash_h___
|
||||
#define jshash_h___
|
||||
/*
|
||||
* API to portable hash table code.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include "jstypes.h"
|
||||
#include "jscompat.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
typedef uint32 JSHashNumber;
|
||||
typedef struct JSHashEntry JSHashEntry;
|
||||
typedef struct JSHashTable JSHashTable;
|
||||
|
||||
#define JS_HASH_BITS 32
|
||||
#define JS_GOLDEN_RATIO 0x9E3779B9U
|
||||
|
||||
typedef JSHashNumber (*JSHashFunction)(const void *key);
|
||||
typedef intN (*JSHashComparator)(const void *v1, const void *v2);
|
||||
typedef intN (*JSHashEnumerator)(JSHashEntry *he, intN i, void *arg);
|
||||
|
||||
/* Flag bits in JSHashEnumerator's return value */
|
||||
#define HT_ENUMERATE_NEXT 0 /* continue enumerating entries */
|
||||
#define HT_ENUMERATE_STOP 1 /* stop enumerating entries */
|
||||
#define HT_ENUMERATE_REMOVE 2 /* remove and free the current entry */
|
||||
#define HT_ENUMERATE_UNHASH 4 /* just unhash the current entry */
|
||||
|
||||
typedef struct JSHashAllocOps {
|
||||
void * (*allocTable)(void *pool, size_t size);
|
||||
void (*freeTable)(void *pool, void *item);
|
||||
JSHashEntry * (*allocEntry)(void *pool, const void *key);
|
||||
void (*freeEntry)(void *pool, JSHashEntry *he, uintN flag);
|
||||
} JSHashAllocOps;
|
||||
|
||||
#define HT_FREE_VALUE 0 /* just free the entry's value */
|
||||
#define HT_FREE_ENTRY 1 /* free value and entire entry */
|
||||
|
||||
struct JSHashEntry {
|
||||
JSHashEntry *next; /* hash chain linkage */
|
||||
JSHashNumber keyHash; /* key hash function result */
|
||||
const void *key; /* ptr to opaque key */
|
||||
void *value; /* ptr to opaque value */
|
||||
};
|
||||
|
||||
struct JSHashTable {
|
||||
JSHashEntry **buckets; /* vector of hash buckets */
|
||||
uint32 nentries; /* number of entries in table */
|
||||
uint32 shift; /* multiplicative hash shift */
|
||||
JSHashFunction keyHash; /* key hash function */
|
||||
JSHashComparator keyCompare; /* key comparison function */
|
||||
JSHashComparator valueCompare; /* value comparison function */
|
||||
JSHashAllocOps *allocOps; /* allocation operations */
|
||||
void *allocPriv; /* allocation private data */
|
||||
#ifdef HASHMETER
|
||||
uint32 nlookups; /* total number of lookups */
|
||||
uint32 nsteps; /* number of hash chains traversed */
|
||||
uint32 ngrows; /* number of table expansions */
|
||||
uint32 nshrinks; /* number of table contractions */
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* Create a new hash table.
|
||||
* If allocOps is null, use default allocator ops built on top of malloc().
|
||||
*/
|
||||
JS_EXTERN_API(JSHashTable *)
|
||||
JS_NewHashTable(uint32 n, JSHashFunction keyHash,
|
||||
JSHashComparator keyCompare, JSHashComparator valueCompare,
|
||||
JSHashAllocOps *allocOps, void *allocPriv);
|
||||
|
||||
JS_EXTERN_API(void)
|
||||
JS_HashTableDestroy(JSHashTable *ht);
|
||||
|
||||
/* Low level access methods */
|
||||
JS_EXTERN_API(JSHashEntry **)
|
||||
JS_HashTableRawLookup(JSHashTable *ht, JSHashNumber keyHash, const void *key);
|
||||
|
||||
JS_EXTERN_API(JSHashEntry *)
|
||||
JS_HashTableRawAdd(JSHashTable *ht, JSHashEntry **hep, JSHashNumber keyHash,
|
||||
const void *key, void *value);
|
||||
|
||||
JS_EXTERN_API(void)
|
||||
JS_HashTableRawRemove(JSHashTable *ht, JSHashEntry **hep, JSHashEntry *he);
|
||||
|
||||
/* Higher level access methods */
|
||||
JS_EXTERN_API(JSHashEntry *)
|
||||
JS_HashTableAdd(JSHashTable *ht, const void *key, void *value);
|
||||
|
||||
JS_EXTERN_API(JSBool)
|
||||
JS_HashTableRemove(JSHashTable *ht, const void *key);
|
||||
|
||||
JS_EXTERN_API(intN)
|
||||
JS_HashTableEnumerateEntries(JSHashTable *ht, JSHashEnumerator f, void *arg);
|
||||
|
||||
JS_EXTERN_API(void *)
|
||||
JS_HashTableLookup(JSHashTable *ht, const void *key);
|
||||
|
||||
JS_EXTERN_API(intN)
|
||||
JS_HashTableDump(JSHashTable *ht, JSHashEnumerator dump, FILE *fp);
|
||||
|
||||
/* General-purpose C string hash function. */
|
||||
JS_EXTERN_API(JSHashNumber)
|
||||
JS_HashString(const void *key);
|
||||
|
||||
/* Stub function just returns v1 == v2 */
|
||||
JS_EXTERN_API(intN)
|
||||
JS_CompareValues(const void *v1, const void *v2);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jshash_h___ */
|
||||
485
mozilla/js/src/jsify.pl
Normal file
485
mozilla/js/src/jsify.pl
Normal file
@@ -0,0 +1,485 @@
|
||||
#!/usr/local/bin/perl
|
||||
|
||||
# This script modifies C code to use the hijacked NSPR routines that are
|
||||
# now baked into the JavaScript engine rather than using the NSPR
|
||||
# routines that they were based on, i.e. types like PRArenaPool are changed
|
||||
# to JSArenaPool.
|
||||
#
|
||||
# This script was used in 9/98 to facilitate the incorporation of some NSPR
|
||||
# code into the JS engine so as to minimize dependency on NSPR.
|
||||
#
|
||||
|
||||
# Command-line: jsify.pl [options] [filename]*
|
||||
#
|
||||
# Options:
|
||||
# -r Reverse direction of transformation, i.e. JS ==> NSPR2
|
||||
# -outdir Directory in which to place output files
|
||||
|
||||
|
||||
# NSPR2 symbols that will be modified to JS symbols, e.g.
|
||||
# PRArena <==> JSArena
|
||||
|
||||
@NSPR_symbols = (
|
||||
"PRArena",
|
||||
"PRArenaPool",
|
||||
"PRArenaStats",
|
||||
"PR_ARENAMETER",
|
||||
"PR_ARENA_",
|
||||
"PR_ARENA_ALIGN",
|
||||
"PR_ARENA_ALLOCATE",
|
||||
"PR_ARENA_CONST_ALIGN_MASK",
|
||||
"PR_ARENA_DEFAULT_ALIGN",
|
||||
"PR_ARENA_DESTROY",
|
||||
"PR_ARENA_GROW",
|
||||
"PR_ARENA_MARK",
|
||||
"PR_ARENA_RELEASE",
|
||||
|
||||
"PR_smprintf",
|
||||
"PR_smprintf_free",
|
||||
"PR_snprintf",
|
||||
"PR_sprintf_append",
|
||||
"PR_sscanf",
|
||||
"PR_sxprintf",
|
||||
"PR_vsmprintf",
|
||||
"PR_vsnprintf",
|
||||
"PR_vsprintf_append",
|
||||
"PR_vsxprintf",
|
||||
|
||||
"PRCList",
|
||||
"PRCListStr",
|
||||
"PRCLists",
|
||||
|
||||
"PRDestroyEventProc",
|
||||
"PREvent",
|
||||
"PREventFunProc",
|
||||
"PREventQueue",
|
||||
"PRHandleEventProc",
|
||||
"PR_PostEvent",
|
||||
"PR_PostSynchronousEvent",
|
||||
"PR_ProcessPendingEvents",
|
||||
"PR_CreateEventQueue",
|
||||
"PR_DequeueEvent",
|
||||
"PR_DestroyEvent",
|
||||
"PR_DestroyEventQueue",
|
||||
"PR_EventAvailable",
|
||||
"PR_EventLoop",
|
||||
"PR_GetEvent",
|
||||
"PR_GetEventOwner",
|
||||
"PR_GetEventQueueMonitor",
|
||||
"PR_GetEventQueueSelectFD",
|
||||
"PR_GetMainEventQueue",
|
||||
"PR_HandleEvent",
|
||||
"PR_InitEvent",
|
||||
"PR_ENTER_EVENT_QUEUE_MONITOR",
|
||||
"PR_EXIT_EVENT_QUEUE_MONITOR",
|
||||
"PR_MapEvents",
|
||||
"PR_RevokeEvents",
|
||||
|
||||
"PR_cnvtf",
|
||||
"PR_dtoa",
|
||||
"PR_strtod",
|
||||
|
||||
"PRFileDesc",
|
||||
|
||||
"PR_HASH_BITS",
|
||||
"PR_GOLDEN_RATIO",
|
||||
"PRHashAllocOps",
|
||||
"PRHashComparator",
|
||||
"PRHashEntry",
|
||||
"PRHashEnumerator",
|
||||
"PRHashFunction",
|
||||
"PRHashNumber",
|
||||
"PRHashTable",
|
||||
"PR_HashString",
|
||||
"PR_HashTableAdd",
|
||||
"PR_HashTableDestroy",
|
||||
"PR_HashTableDump",
|
||||
"PR_HashTableEnumerateEntries",
|
||||
"PR_HashTableLookup",
|
||||
"PR_HashTableRawAdd",
|
||||
"PR_HashTableRawLookup",
|
||||
"PR_HashTableRawRemove",
|
||||
"PR_HashTableRemove",
|
||||
|
||||
"PRBool",
|
||||
"PRFloat64",
|
||||
"PRInt16",
|
||||
"PRInt32",
|
||||
"PRInt64",
|
||||
"PRInt8",
|
||||
"PRIntn",
|
||||
"PRUint16",
|
||||
"PRUint32",
|
||||
"PRUint64",
|
||||
"PRUint8",
|
||||
"PRUintn",
|
||||
"PRPtrDiff",
|
||||
"PRPtrdiff",
|
||||
"PRUptrdiff",
|
||||
"PRUword",
|
||||
"PRWord",
|
||||
"PRPackedBool",
|
||||
"PRSize",
|
||||
"PRStatus",
|
||||
"pruword",
|
||||
"prword",
|
||||
"prword_t",
|
||||
|
||||
"PR_ALIGN_OF_DOUBLE",
|
||||
"PR_ALIGN_OF_FLOAT",
|
||||
"PR_ALIGN_OF_INT",
|
||||
"PR_ALIGN_OF_INT64",
|
||||
"PR_ALIGN_OF_LONG",
|
||||
"PR_ALIGN_OF_POINTER",
|
||||
"PR_ALIGN_OF_SHORT",
|
||||
"PR_ALIGN_OF_WORD",
|
||||
"PR_BITS_PER_BYTE",
|
||||
"PR_BITS_PER_BYTE_LOG2",
|
||||
"PR_BITS_PER_DOUBLE",
|
||||
"PR_BITS_PER_DOUBLE_LOG2",
|
||||
"PR_BITS_PER_FLOAT",
|
||||
"PR_BITS_PER_FLOAT_LOG2",
|
||||
"PR_BITS_PER_INT",
|
||||
"PR_BITS_PER_INT64",
|
||||
"PR_BITS_PER_INT64_LOG2",
|
||||
"PR_BITS_PER_INT_LOG2",
|
||||
"PR_BITS_PER_LONG",
|
||||
"PR_BITS_PER_LONG_LOG2",
|
||||
"PR_BITS_PER_SHORT",
|
||||
"PR_BITS_PER_SHORT_LOG2",
|
||||
"PR_BITS_PER_WORD",
|
||||
"PR_BITS_PER_WORD_LOG2",
|
||||
"PR_BYTES_PER_BYTE",
|
||||
"PR_BYTES_PER_DOUBLE",
|
||||
"PR_BYTES_PER_DWORD",
|
||||
"PR_BYTES_PER_DWORD_LOG2",
|
||||
"PR_BYTES_PER_FLOAT",
|
||||
"PR_BYTES_PER_INT",
|
||||
"PR_BYTES_PER_INT64",
|
||||
"PR_BYTES_PER_LONG",
|
||||
"PR_BYTES_PER_SHORT",
|
||||
"PR_BYTES_PER_WORD",
|
||||
"PR_BYTES_PER_WORD_LOG2",
|
||||
|
||||
"PRSegment",
|
||||
"PRSegmentAccess",
|
||||
"PRStuffFunc",
|
||||
"PRThread",
|
||||
|
||||
"PR_APPEND_LINK",
|
||||
|
||||
"PR_ASSERT",
|
||||
|
||||
"PR_ATOMIC_DWORD_LOAD",
|
||||
"PR_ATOMIC_DWORD_STORE",
|
||||
|
||||
"PR_Abort",
|
||||
|
||||
"PR_ArenaAllocate",
|
||||
"PR_ArenaCountAllocation",
|
||||
"PR_ArenaCountGrowth",
|
||||
"PR_ArenaCountInplaceGrowth",
|
||||
"PR_ArenaCountRelease",
|
||||
"PR_ArenaCountRetract",
|
||||
"PR_ArenaFinish",
|
||||
"PR_ArenaGrow",
|
||||
"PR_ArenaRelease",
|
||||
"PR_CompactArenaPool",
|
||||
"PR_DumpArenaStats",
|
||||
"PR_FinishArenaPool",
|
||||
"PR_FreeArenaPool",
|
||||
"PR_InitArenaPool",
|
||||
|
||||
"PR_Assert",
|
||||
|
||||
"PR_AttachThread",
|
||||
|
||||
"PR_BEGIN_EXTERN_C",
|
||||
"PR_BEGIN_MACRO",
|
||||
|
||||
"PR_BIT",
|
||||
"PR_BITMASK",
|
||||
|
||||
"PR_BUFFER_OVERFLOW_ERROR",
|
||||
|
||||
"PR_CALLBACK",
|
||||
"PR_CALLBACK_DECL",
|
||||
"PR_CALLOC",
|
||||
"PR_CEILING_LOG2",
|
||||
"PR_CLEAR_ARENA",
|
||||
"PR_CLEAR_BIT",
|
||||
"PR_CLEAR_UNUSED",
|
||||
"PR_CLIST_IS_EMPTY",
|
||||
"PR_COUNT_ARENA",
|
||||
"PR_CURRENT_THREAD",
|
||||
|
||||
"PR_GetSegmentAccess",
|
||||
"PR_GetSegmentSize",
|
||||
"PR_GetSegmentVaddr",
|
||||
"PR_GrowSegment",
|
||||
"PR_DestroySegment",
|
||||
"PR_MapSegment",
|
||||
"PR_NewSegment",
|
||||
"PR_Segment",
|
||||
"PR_Seg",
|
||||
"PR_SEGMENT_NONE",
|
||||
"PR_SEGMENT_RDONLY",
|
||||
"PR_SEGMENT_RDWR",
|
||||
|
||||
"PR_Calloc",
|
||||
"PR_CeilingLog2",
|
||||
"PR_CompareStrings",
|
||||
"PR_CompareValues",
|
||||
"PR_DELETE",
|
||||
"PR_END_EXTERN_C",
|
||||
"PR_END_MACRO",
|
||||
"PR_ENUMERATE_STOP",
|
||||
"PR_FAILURE",
|
||||
"PR_FALSE",
|
||||
"PR_FLOOR_LOG2",
|
||||
"PR_FREEIF",
|
||||
"PR_FREE_PATTERN",
|
||||
"PR_FloorLog2",
|
||||
"PR_FormatTime",
|
||||
"PR_Free",
|
||||
|
||||
"PR_GetEnv",
|
||||
"PR_GetError",
|
||||
"PR_INIT_ARENA_POOL",
|
||||
"PR_INIT_CLIST",
|
||||
"PR_INIT_STATIC_CLIST",
|
||||
"PR_INLINE",
|
||||
"PR_INSERT_AFTER",
|
||||
"PR_INSERT_BEFORE",
|
||||
"PR_INSERT_LINK",
|
||||
"PR_INT32",
|
||||
"PR_INTERVAL_NO_TIMEOUT",
|
||||
"PR_INTERVAL_NO_WAIT",
|
||||
"PR_Init",
|
||||
"PR_LIST_HEAD",
|
||||
"PR_LIST_TAIL",
|
||||
"PR_LOG",
|
||||
"PR_LOGGING",
|
||||
"PR_LOG_ALWAYS",
|
||||
"PR_LOG_BEGIN",
|
||||
"PR_LOG_DEBUG",
|
||||
"PR_LOG_DEFINE",
|
||||
"PR_LOG_END",
|
||||
"PR_LOG_ERROR",
|
||||
"PR_LOG_MAX",
|
||||
"PR_LOG_MIN",
|
||||
"PR_LOG_NONE",
|
||||
"PR_LOG_NOTICE",
|
||||
"PR_LOG_TEST",
|
||||
"PR_LOG_WARN",
|
||||
"PR_LOG_WARNING",
|
||||
"PR_LogFlush",
|
||||
"PR_LogPrint",
|
||||
"PR_MALLOC",
|
||||
"PR_MAX",
|
||||
"PR_MD_calloc",
|
||||
"PR_MD_free",
|
||||
"PR_MD_malloc",
|
||||
"PR_MD_realloc",
|
||||
"PR_MIN",
|
||||
"PR_Malloc",
|
||||
"PR_NEW",
|
||||
"PR_NEWZAP",
|
||||
"PR_NEXT_LINK",
|
||||
"PR_NOT_REACHED",
|
||||
"PR_NewCondVar",
|
||||
"PR_NewHashTable",
|
||||
"PR_NewLogModule",
|
||||
"PR_PREV_LINK",
|
||||
"PR_PUBLIC_API",
|
||||
"PR_PUBLIC_DATA",
|
||||
"PR_RANGE_ERROR",
|
||||
"PR_REALLOC",
|
||||
"PR_REMOVE_AND_INIT_LINK",
|
||||
"PR_REMOVE_LINK",
|
||||
"PR_ROUNDUP",
|
||||
"PR_Realloc",
|
||||
|
||||
"PR_SET_BIT",
|
||||
"PR_STATIC_CALLBACK",
|
||||
"PR_SUCCESS",
|
||||
"PR_SetError",
|
||||
"PR_SetLogBuffering",
|
||||
"PR_SetLogFile",
|
||||
|
||||
"PR_TEST_BIT",
|
||||
"PR_TRUE",
|
||||
"PR_UINT32",
|
||||
"PR_UPTRDIFF",
|
||||
|
||||
"prarena_h___",
|
||||
"prbit_h___",
|
||||
"prclist_h___",
|
||||
"prdtoa_h___",
|
||||
"prlog_h___",
|
||||
"prlong_h___",
|
||||
"prmacos_h___",
|
||||
"prmem_h___",
|
||||
"prprf_h___",
|
||||
"prtypes_h___",
|
||||
|
||||
"prarena",
|
||||
"prbit",
|
||||
"prbitmap_t",
|
||||
"prclist",
|
||||
"prcpucfg",
|
||||
"prdtoa",
|
||||
"prhash",
|
||||
"plhash",
|
||||
"prlong",
|
||||
"prmacos",
|
||||
"prmem",
|
||||
"prosdep",
|
||||
"protypes",
|
||||
"prprf",
|
||||
"prtypes"
|
||||
);
|
||||
|
||||
while ($ARGV[0] =~ /^-/) {
|
||||
if ($ARGV[0] eq "-r") {
|
||||
shift;
|
||||
$reverse_conversion = 1;
|
||||
} elsif ($ARGV[0] eq "-outdir") {
|
||||
shift;
|
||||
$outdir = shift;
|
||||
}
|
||||
}
|
||||
|
||||
# Given an NSPR symbol compute the JS equivalent or
|
||||
# vice-versa
|
||||
sub subst {
|
||||
local ($replacement);
|
||||
local ($sym) = @_;
|
||||
|
||||
$replacement = substr($sym,0,2) eq "pr" ? "js" : "JS";
|
||||
$replacement .= substr($sym, 2);
|
||||
return $replacement;
|
||||
}
|
||||
|
||||
# Build the regular expression that will convert between the NSPR
|
||||
# types and the JS types
|
||||
if ($reverse_conversion) {
|
||||
die "Not implemented yet";
|
||||
} else {
|
||||
foreach $sym (@NSPR_symbols) {
|
||||
$regexp .= $sym . "|"
|
||||
}
|
||||
# Get rid of the last "!"
|
||||
chop $regexp;
|
||||
|
||||
# Replace PR* with JS* and replace pr* with js*
|
||||
$regexp = 's/(^|\\W)(' . $regexp . ')/$1 . &subst($2)/eg';
|
||||
# print $regexp;
|
||||
}
|
||||
|
||||
# Pre-compile a little subroutine to perform the regexp substitution
|
||||
# between NSPR types and JS types
|
||||
eval('sub convert_from_NSPR {($line) = @_; $line =~ ' . $regexp . ';}');
|
||||
|
||||
sub convert_mallocs {
|
||||
($line) = @_;
|
||||
$line =~ s/PR_MALLOC/malloc/g;
|
||||
$line =~ s/PR_REALLOC/realloc/g;
|
||||
$line =~ s/PR_FREE/free/g;
|
||||
return $line;
|
||||
}
|
||||
|
||||
sub convert_includes {
|
||||
($line) = @_;
|
||||
if ($line !~ /include/) {
|
||||
return $line;
|
||||
}
|
||||
|
||||
if ($line =~ /prlog\.h/) {
|
||||
$line = '#include "jsutil.h"'. " /* Added by JSIFY */\n";
|
||||
} elsif ($line =~ /plhash\.h/) {
|
||||
$line = '#include "jshash.h"'. " /* Added by JSIFY */\n";
|
||||
} elsif ($line =~ /plarena\.h/) {
|
||||
$line = '#include "jsarena.h"'. " /* Added by JSIFY */\n";
|
||||
} elsif ($line =~ /prmem\.h/) {
|
||||
$line = "";
|
||||
} elsif ($line =~ /jsmsg\.def/) {
|
||||
$line = '#include "js.msg"' . "\n";
|
||||
} elsif ($line =~ /shellmsg\.def/) {
|
||||
$line = '#include "jsshell.msg"' . "\n";
|
||||
} elsif ($line =~ /jsopcode\.def/) {
|
||||
$line = '#include "jsopcode.tbl"' . "\n";
|
||||
}
|
||||
return $line;
|
||||
}
|
||||
|
||||
sub convert_declarations {
|
||||
($line) = @_;
|
||||
$line =~ s/PR_EXTERN/JS_EXTERN_API/g;
|
||||
$line =~ s/PR_IMPLEMENT_DATA/JS_EXPORT_DATA/g;
|
||||
$line =~ s/PR_IMPLEMENT/JS_EXPORT_API/g;
|
||||
$line =~ s/PR_CALLBACK/JS_DLL_CALLBACK/g;
|
||||
$line =~ s/PR_STATIC_CALLBACK/JS_STATIC_DLL_CALLBACK/g;
|
||||
$line =~ s/PR_IMPORT/JS_IMPORT/g;
|
||||
$line =~ s/PR_PUBLIC_API/JS_EXPORT_API/g;
|
||||
$line =~ s/PR_PUBLIC_DATA/JS_EXPORT_DATA/g;
|
||||
return $line;
|
||||
}
|
||||
|
||||
sub convert_long_long_macros {
|
||||
($line) = @_;
|
||||
$line =~ s/\b(LL_)/JSLL_/g;
|
||||
return $line;
|
||||
}
|
||||
|
||||
sub convert_asserts {
|
||||
($line) = @_;
|
||||
$line =~ s/\bPR_ASSERT/JS_ASSERT/g;
|
||||
return $line;
|
||||
}
|
||||
|
||||
while ($#ARGV >= 0) {
|
||||
$infile = shift;
|
||||
|
||||
# Change filename, e.g. prtime.h to jsprtime.h, except for legacy
|
||||
# files that start with 'prmj', like prmjtime.h.
|
||||
$outfile = $infile;
|
||||
if ($infile !~ /^prmj/) {
|
||||
$outfile =~ s/^pr/js/;
|
||||
$outfile =~ s/^pl/js/;
|
||||
}
|
||||
|
||||
if ($outdir) {
|
||||
$outfile = $outdir . '/' . $outfile;
|
||||
}
|
||||
|
||||
if ($infile eq $outfile) {
|
||||
die "Error: refuse to overwrite $outfile, use -outdir option."
|
||||
}
|
||||
die "Can't open $infile" if !open(INFILE, "<$infile");
|
||||
die "Can't open $outfile for writing" if !open(OUTFILE, ">$outfile");
|
||||
|
||||
while (<INFILE>) {
|
||||
$line = $_;
|
||||
|
||||
#Get rid of #include "prlog.h"
|
||||
&convert_includes($line);
|
||||
|
||||
# Rename PR_EXTERN, PR_IMPORT, etc.
|
||||
&convert_declarations($line);
|
||||
|
||||
# Convert from PR_MALLOC to malloc, etc.
|
||||
&convert_mallocs($line);
|
||||
|
||||
# Convert from PR_ASSERT to JS_ASSERT
|
||||
# &convert_asserts($line);
|
||||
|
||||
# Convert from, e.g. PRArena to JSPRArena
|
||||
&convert_from_NSPR($line);
|
||||
|
||||
# Change LL_* macros to JSLL_*
|
||||
&convert_long_long_macros($line);
|
||||
|
||||
print OUTFILE $line;
|
||||
}
|
||||
}
|
||||
2853
mozilla/js/src/jsinterp.c
Normal file
2853
mozilla/js/src/jsinterp.c
Normal file
File diff suppressed because it is too large
Load Diff
209
mozilla/js/src/jsinterp.h
Normal file
209
mozilla/js/src/jsinterp.h
Normal file
@@ -0,0 +1,209 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef jsinterp_h___
|
||||
#define jsinterp_h___
|
||||
/*
|
||||
* JS interpreter interface.
|
||||
*/
|
||||
#include "jsprvtd.h"
|
||||
#include "jspubtd.h"
|
||||
|
||||
/*
|
||||
* JS stack frame, allocated on the C stack.
|
||||
*/
|
||||
struct JSStackFrame {
|
||||
JSObject *callobj; /* lazily created Call object */
|
||||
JSObject *argsobj; /* lazily created arguments object */
|
||||
JSScript *script; /* script being interpreted */
|
||||
JSFunction *fun; /* function being called or null */
|
||||
JSObject *thisp; /* "this" pointer if in method */
|
||||
uintN argc; /* actual argument count */
|
||||
jsval *argv; /* base of argument stack slots */
|
||||
jsval rval; /* function return value */
|
||||
uintN nvars; /* local variable count */
|
||||
jsval *vars; /* base of variable stack slots */
|
||||
JSStackFrame *down; /* previous frame */
|
||||
void *annotation; /* used by Java security */
|
||||
JSObject *scopeChain; /* scope chain */
|
||||
jsbytecode *pc; /* program counter */
|
||||
jsval *sp; /* stack pointer */
|
||||
uintN sharpDepth; /* array/object initializer depth */
|
||||
JSObject *sharpArray; /* scope for #n= initializer vars */
|
||||
JSPackedBool constructing; /* true if called via new operator */
|
||||
uint8 overrides; /* bit-set of overridden Call properties */
|
||||
JSPackedBool debugging; /* true if for JS_EvaluateInStackFrame */
|
||||
JSStackFrame *dormantNext; /* next dormant frame chain */
|
||||
};
|
||||
|
||||
/*
|
||||
* Property cache for quickened get/set property opcodes.
|
||||
*/
|
||||
#define PROPERTY_CACHE_LOG2 10
|
||||
#define PROPERTY_CACHE_SIZE JS_BIT(PROPERTY_CACHE_LOG2)
|
||||
#define PROPERTY_CACHE_MASK JS_BITMASK(PROPERTY_CACHE_LOG2)
|
||||
|
||||
#define PROPERTY_CACHE_HASH(obj, id) \
|
||||
((((jsuword)(obj) >> JSVAL_TAGBITS) ^ (jsuword)(id)) & PROPERTY_CACHE_MASK)
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
|
||||
#if HAVE_ATOMIC_DWORD_ACCESS
|
||||
|
||||
#define PCE_LOAD(cache, pce, entry) JS_ATOMIC_DWORD_LOAD(pce, entry)
|
||||
#define PCE_STORE(cache, pce, entry) JS_ATOMIC_DWORD_STORE(pce, entry)
|
||||
|
||||
#else /* !HAVE_ATOMIC_DWORD_ACCESS */
|
||||
|
||||
#define PCE_LOAD(cache, pce, entry) \
|
||||
JS_BEGIN_MACRO \
|
||||
uint32 _prefills; \
|
||||
uint32 _fills = (cache)->fills; \
|
||||
do { \
|
||||
/* Load until cache->fills is stable (see FILL macro below). */ \
|
||||
_prefills = _fills; \
|
||||
(entry) = *(pce); \
|
||||
} while ((_fills = (cache)->fills) != _prefills); \
|
||||
JS_END_MACRO
|
||||
|
||||
#define PCE_STORE(cache, pce, entry) \
|
||||
JS_BEGIN_MACRO \
|
||||
do { \
|
||||
/* Store until no racing collider stores half or all of pce. */ \
|
||||
*(pce) = (entry); \
|
||||
} while (PCE_OBJECT(*pce) != PCE_OBJECT(entry) || \
|
||||
PCE_PROPERTY(*pce) != PCE_PROPERTY(entry)); \
|
||||
JS_END_MACRO
|
||||
|
||||
#endif /* !HAVE_ATOMIC_DWORD_ACCESS */
|
||||
|
||||
#else /* !JS_THREADSAFE */
|
||||
|
||||
#define PCE_LOAD(cache, pce, entry) ((entry) = *(pce))
|
||||
#define PCE_STORE(cache, pce, entry) (*(pce) = (entry))
|
||||
|
||||
#endif /* !JS_THREADSAFE */
|
||||
|
||||
typedef union JSPropertyCacheEntry {
|
||||
struct {
|
||||
JSObject *object; /* weak link to object */
|
||||
JSProperty *property; /* weak link to property, or not-found id */
|
||||
} s;
|
||||
#ifdef HAVE_ATOMIC_DWORD_ACCESS
|
||||
prdword align;
|
||||
#endif
|
||||
} JSPropertyCacheEntry;
|
||||
|
||||
/* These may be called in lvalue or rvalue position. */
|
||||
#define PCE_OBJECT(entry) ((entry).s.object)
|
||||
#define PCE_PROPERTY(entry) ((entry).s.property)
|
||||
|
||||
typedef struct JSPropertyCache {
|
||||
JSPropertyCacheEntry table[PROPERTY_CACHE_SIZE];
|
||||
JSBool empty;
|
||||
uint32 fills;
|
||||
uint32 recycles;
|
||||
uint32 tests;
|
||||
uint32 misses;
|
||||
uint32 flushes;
|
||||
} JSPropertyCache;
|
||||
|
||||
/* Property-not-found lookup results are cached using this invalid pointer. */
|
||||
#define PROP_NOT_FOUND(obj,id) ((JSProperty *) ((jsword)(id) | 1))
|
||||
#define PROP_NOT_FOUND_ID(prop) ((jsid) ((jsword)(prop) & ~1))
|
||||
#define PROP_FOUND(prop) ((prop) && ((jsword)(prop) & 1) == 0)
|
||||
|
||||
#define PROPERTY_CACHE_FILL(cx, cache, obj, id, prop) \
|
||||
JS_BEGIN_MACRO \
|
||||
uintN _hashIndex = (uintN)PROPERTY_CACHE_HASH(obj, id); \
|
||||
JSPropertyCache *_cache = (cache); \
|
||||
JSPropertyCacheEntry *_pce = &_cache->table[_hashIndex]; \
|
||||
JSPropertyCacheEntry _entry; \
|
||||
JSProperty *_pce_prop; \
|
||||
PCE_LOAD(_cache, _pce, _entry); \
|
||||
_pce_prop = PCE_PROPERTY(_entry); \
|
||||
if (_pce_prop && _pce_prop != prop) \
|
||||
_cache->recycles++; \
|
||||
PCE_OBJECT(_entry) = obj; \
|
||||
PCE_PROPERTY(_entry) = prop; \
|
||||
_cache->empty = JS_FALSE; \
|
||||
_cache->fills++; \
|
||||
PCE_STORE(_cache, _pce, _entry); \
|
||||
JS_END_MACRO
|
||||
|
||||
#define PROPERTY_CACHE_TEST(cache, obj, id, prop) \
|
||||
JS_BEGIN_MACRO \
|
||||
uintN _hashIndex = (uintN)PROPERTY_CACHE_HASH(obj, id); \
|
||||
JSPropertyCache *_cache = (cache); \
|
||||
JSPropertyCacheEntry *_pce = &_cache->table[_hashIndex]; \
|
||||
JSPropertyCacheEntry _entry; \
|
||||
JSProperty *_pce_prop; \
|
||||
PCE_LOAD(_cache, _pce, _entry); \
|
||||
_pce_prop = PCE_PROPERTY(_entry); \
|
||||
_cache->tests++; \
|
||||
if (_pce_prop && \
|
||||
(((jsword)_pce_prop & 1) \
|
||||
? PROP_NOT_FOUND_ID(_pce_prop) \
|
||||
: sym_id(((JSScopeProperty *)_pce_prop)->symbols)) == id && \
|
||||
PCE_OBJECT(_entry) == obj) { \
|
||||
prop = _pce_prop; \
|
||||
} else { \
|
||||
_cache->misses++; \
|
||||
prop = NULL; \
|
||||
} \
|
||||
JS_END_MACRO
|
||||
|
||||
extern void
|
||||
js_FlushPropertyCache(JSContext *cx);
|
||||
|
||||
extern void
|
||||
js_FlushPropertyCacheByProp(JSContext *cx, JSProperty *prop);
|
||||
|
||||
extern jsval *
|
||||
js_AllocStack(JSContext *cx, uintN nslots, void **markp);
|
||||
|
||||
extern void
|
||||
js_FreeStack(JSContext *cx, void *mark);
|
||||
|
||||
extern JSBool
|
||||
js_GetArgument(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
||||
|
||||
extern JSBool
|
||||
js_SetArgument(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
||||
|
||||
extern JSBool
|
||||
js_GetLocalVariable(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
||||
|
||||
extern JSBool
|
||||
js_SetLocalVariable(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
||||
|
||||
extern JSBool
|
||||
js_Invoke(JSContext *cx, uintN argc, JSBool constructing);
|
||||
|
||||
extern JSBool
|
||||
js_CallFunctionValue(JSContext *cx, JSObject *obj, jsval fval,
|
||||
uintN argc, jsval *argv, jsval *rval);
|
||||
|
||||
extern JSBool
|
||||
js_Execute(JSContext *cx, JSObject *chain, JSScript *script, JSFunction *fun,
|
||||
JSStackFrame *down, JSBool debugging, jsval *result);
|
||||
|
||||
extern JSBool
|
||||
js_Interpret(JSContext *cx, jsval *result);
|
||||
|
||||
#endif /* jsinterp_h___ */
|
||||
272
mozilla/js/src/jslibmath.h
Normal file
272
mozilla/js/src/jslibmath.h
Normal file
@@ -0,0 +1,272 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* By default all math calls go to fdlibm. The defines for each platform
|
||||
* remap the math calls to native routines.
|
||||
*/
|
||||
|
||||
#ifndef _LIBMATH_H
|
||||
#define _LIBMATH_H
|
||||
|
||||
#include <math.h>
|
||||
#include "jsconfig.h"
|
||||
|
||||
/*
|
||||
* Define which platforms on which to use fdlibm. Not used
|
||||
* by default since there can be problems with endian-ness and such.
|
||||
*/
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define JS_USE_FDLIBM_MATH 1
|
||||
|
||||
#elif defined(SUNOS4)
|
||||
#define JS_USE_FDLIBM_MATH 1
|
||||
|
||||
#elif defined(IRIX)
|
||||
#define JS_USE_FDLIBM_MATH 1
|
||||
|
||||
#elif defined(SOLARIS)
|
||||
#define JS_USE_FDLIBM_MATH 1
|
||||
|
||||
#elif defined(HPUX)
|
||||
#define JS_USE_FDLIBM_MATH 1
|
||||
|
||||
#elif defined(linux)
|
||||
#define JS_USE_FDLIBM_MATH 1
|
||||
|
||||
#elif defined(OSF1)
|
||||
/* Want to use some fdlibm functions but fdlibm broken on OSF1/alpha. */
|
||||
#define JS_USE_FDLIBM_MATH 0
|
||||
|
||||
#elif defined(AIX)
|
||||
#define JS_USE_FDLIBM_MATH 1
|
||||
|
||||
#else
|
||||
#define JS_USE_FDLIBM_MATH 0
|
||||
#endif
|
||||
|
||||
#if !JS_USE_FDLIBM_MATH
|
||||
|
||||
/*
|
||||
* Use system provided math routines.
|
||||
*/
|
||||
|
||||
#define fd_acos acos
|
||||
#define fd_asin asin
|
||||
#define fd_atan atan
|
||||
#define fd_atan2 atan2
|
||||
#define fd_ceil ceil
|
||||
#define fd_copysign copysign
|
||||
#define fd_cos cos
|
||||
#define fd_exp exp
|
||||
#define fd_fabs fabs
|
||||
#define fd_floor floor
|
||||
#define fd_fmod fmod
|
||||
#define fd_log log
|
||||
#define fd_pow pow
|
||||
#define fd_sin sin
|
||||
#define fd_sqrt sqrt
|
||||
#define fd_tan tan
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* Use math routines in fdlibm.
|
||||
*/
|
||||
|
||||
#ifdef __STDC__
|
||||
#define __P(p) p
|
||||
#else
|
||||
#define __P(p) ()
|
||||
#endif
|
||||
|
||||
#if defined _WIN32 || defined SUNOS4
|
||||
|
||||
#define fd_acos acos
|
||||
#define fd_asin asin
|
||||
#define fd_atan atan
|
||||
#define fd_cos cos
|
||||
#define fd_sin sin
|
||||
#define fd_tan tan
|
||||
#define fd_exp exp
|
||||
#define fd_log log
|
||||
#define fd_sqrt sqrt
|
||||
#define fd_ceil ceil
|
||||
#define fd_fabs fabs
|
||||
#define fd_floor floor
|
||||
#define fd_fmod fmod
|
||||
|
||||
extern double fd_atan2 __P((double, double));
|
||||
extern double fd_copysign __P((double, double));
|
||||
|
||||
#ifdef DEBUG
|
||||
extern double fd_pow __P((double, double));
|
||||
#else
|
||||
#define fd_pow pow
|
||||
#endif
|
||||
|
||||
#elif defined IRIX
|
||||
|
||||
#define fd_acos acos
|
||||
#define fd_asin asin
|
||||
#define fd_atan atan
|
||||
#define fd_exp exp
|
||||
#define fd_log log
|
||||
#define fd_log10 log10
|
||||
#define fd_sqrt sqrt
|
||||
#define fd_fabs fabs
|
||||
#define fd_floor floor
|
||||
#define fd_fmod fmod
|
||||
|
||||
extern double fd_cos __P((double));
|
||||
extern double fd_sin __P((double));
|
||||
extern double fd_tan __P((double));
|
||||
extern double fd_atan2 __P((double, double));
|
||||
extern double fd_pow __P((double, double));
|
||||
extern double fd_ceil __P((double));
|
||||
extern double fd_copysign __P((double, double));
|
||||
|
||||
#elif defined SOLARIS
|
||||
|
||||
#define fd_atan atan
|
||||
#define fd_cos cos
|
||||
#define fd_sin sin
|
||||
#define fd_tan tan
|
||||
#define fd_exp exp
|
||||
#define fd_sqrt sqrt
|
||||
#define fd_ceil ceil
|
||||
#define fd_fabs fabs
|
||||
#define fd_floor floor
|
||||
#define fd_fmod fmod
|
||||
|
||||
extern double fd_acos __P((double));
|
||||
extern double fd_asin __P((double));
|
||||
extern double fd_log __P((double));
|
||||
extern double fd_atan2 __P((double, double));
|
||||
extern double fd_pow __P((double, double));
|
||||
extern double fd_copysign __P((double, double));
|
||||
|
||||
#elif defined HPUX
|
||||
|
||||
#define fd_cos cos
|
||||
#define fd_sin sin
|
||||
#define fd_exp exp
|
||||
#define fd_sqrt sqrt
|
||||
#define fd_fabs fabs
|
||||
#define fd_floor floor
|
||||
#define fd_fmod fmod
|
||||
|
||||
extern double fd_ceil __P((double));
|
||||
extern double fd_acos __P((double));
|
||||
extern double fd_log __P((double));
|
||||
extern double fd_atan2 __P((double, double));
|
||||
extern double fd_tan __P((double));
|
||||
extern double fd_pow __P((double, double));
|
||||
extern double fd_asin __P((double));
|
||||
extern double fd_atan __P((double));
|
||||
extern double fd_copysign __P((double, double));
|
||||
|
||||
#elif defined(linux)
|
||||
|
||||
#define fd_atan atan
|
||||
#define fd_atan2 atan2
|
||||
#define fd_ceil ceil
|
||||
#define fd_cos cos
|
||||
#define fd_fabs fabs
|
||||
#define fd_floor floor
|
||||
#define fd_fmod fmod
|
||||
#define fd_sin sin
|
||||
#define fd_sqrt sqrt
|
||||
#define fd_tan tan
|
||||
|
||||
extern double fd_asin __P((double));
|
||||
extern double fd_acos __P((double));
|
||||
extern double fd_exp __P((double));
|
||||
extern double fd_log __P((double));
|
||||
extern double fd_pow __P((double, double));
|
||||
extern double fd_copysign __P((double, double));
|
||||
|
||||
#elif defined(OSF1)
|
||||
|
||||
#define fd_acos acos
|
||||
#define fd_asin asin
|
||||
#define fd_atan atan
|
||||
#define fd_copysign copysign
|
||||
#define fd_cos cos
|
||||
#define fd_exp exp
|
||||
#define fd_fabs fabs
|
||||
#define fd_fmod fmod
|
||||
#define fd_sin sin
|
||||
#define fd_sqrt sqrt
|
||||
#define fd_tan tan
|
||||
|
||||
extern double fd_atan2 __P((double, double));
|
||||
extern double fd_ceil __P((double));
|
||||
extern double fd_floor __P((double));
|
||||
extern double fd_log __P((double));
|
||||
extern double fd_pow __P((double, double));
|
||||
|
||||
#elif defined(AIX)
|
||||
|
||||
#define fd_acos acos
|
||||
#define fd_asin asin
|
||||
#define fd_atan2 atan2
|
||||
#define fd_copysign copysign
|
||||
#define fd_cos cos
|
||||
#define fd_exp exp
|
||||
#define fd_fabs fabs
|
||||
#define fd_floor floor
|
||||
#define fd_fmod fmod
|
||||
#define fd_log log
|
||||
#define fd_sin sin
|
||||
#define fd_sqrt sqrt
|
||||
|
||||
extern double fd_atan __P((double));
|
||||
extern double fd_ceil __P((double));
|
||||
extern double fd_pow __P((double,double));
|
||||
extern double fd_tan __P((double));
|
||||
|
||||
#else /* other platform.. generic paranoid slow fdlibm */
|
||||
|
||||
extern double fd_acos __P((double));
|
||||
extern double fd_asin __P((double));
|
||||
extern double fd_atan __P((double));
|
||||
extern double fd_cos __P((double));
|
||||
extern double fd_sin __P((double));
|
||||
extern double fd_tan __P((double));
|
||||
|
||||
extern double fd_exp __P((double));
|
||||
extern double fd_log __P((double));
|
||||
extern double fd_sqrt __P((double));
|
||||
|
||||
extern double fd_ceil __P((double));
|
||||
extern double fd_fabs __P((double));
|
||||
extern double fd_floor __P((double));
|
||||
extern double fd_fmod __P((double, double));
|
||||
|
||||
extern double fd_atan2 __P((double, double));
|
||||
extern double fd_pow __P((double, double));
|
||||
extern double fd_copysign __P((double, double));
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* JS_USE_FDLIBM_MATH */
|
||||
|
||||
#endif /* _LIBMATH_H */
|
||||
|
||||
781
mozilla/js/src/jslock.c
Normal file
781
mozilla/js/src/jslock.c
Normal file
@@ -0,0 +1,781 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
|
||||
/*
|
||||
* JS locking stubs.
|
||||
*/
|
||||
#include "jsstddef.h"
|
||||
#include <stdlib.h>
|
||||
#include "jspubtd.h"
|
||||
#include "prthread.h"
|
||||
#include "pratom.h"
|
||||
#include "jsutil.h" /* Added by JSIFY */
|
||||
#include "jscntxt.h"
|
||||
#include "jsscope.h"
|
||||
#include "jspubtd.h"
|
||||
#include "jslock.h"
|
||||
|
||||
static PRLock *_global_lock;
|
||||
|
||||
static void
|
||||
js_LockGlobal()
|
||||
{
|
||||
PR_Lock(_global_lock);
|
||||
}
|
||||
|
||||
static void
|
||||
js_UnlockGlobal()
|
||||
{
|
||||
PR_Unlock(_global_lock);
|
||||
}
|
||||
|
||||
#define ReadWord(W) (W)
|
||||
#define AtomicAddBody(P,I)\
|
||||
jsword n;\
|
||||
do {\
|
||||
n = ReadWord(*(P));\
|
||||
} while (!js_CompareAndSwap(P, n, n + I));
|
||||
|
||||
#if defined(_WIN32) && !defined(NSPR_LOCK)
|
||||
#pragma warning( disable : 4035 )
|
||||
|
||||
JS_INLINE int
|
||||
js_CompareAndSwap(jsword *w, jsword ov, jsword nv)
|
||||
{
|
||||
__asm {
|
||||
mov eax,ov
|
||||
mov ecx, nv
|
||||
mov ebx, w
|
||||
lock cmpxchg [ebx], ecx
|
||||
sete al
|
||||
and eax,1h
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(SOLARIS) && !defined(NSPR_LOCK)
|
||||
|
||||
#ifndef ULTRA_SPARC
|
||||
JS_INLINE jsword
|
||||
js_ReadWord(jsword *p)
|
||||
{
|
||||
jsword n;
|
||||
while ((n = *p) == -1)
|
||||
;
|
||||
return n;
|
||||
}
|
||||
|
||||
#undef ReadWord
|
||||
#define ReadWord(W) js_ReadWord(&(W))
|
||||
|
||||
static PRLock *_counter_lock;
|
||||
#define UsingCounterLock 1
|
||||
|
||||
#undef AtomicAddBody
|
||||
#define AtomicAddBody(P,I) \
|
||||
PR_Lock(_counter_lock);\
|
||||
*(P) += I;\
|
||||
PR_Unlock(_counter_lock);
|
||||
|
||||
#endif /* !ULTRA_SPARC */
|
||||
|
||||
JS_INLINE int
|
||||
js_CompareAndSwap(jsword *w, jsword ov, jsword nv)
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
unsigned int res;
|
||||
#ifndef ULTRA_SPARC
|
||||
JS_ASSERT(nv != -1);
|
||||
asm volatile ("\
|
||||
stbar\n\
|
||||
swap [%1],%4\n\
|
||||
1: cmp %4,-1\n\
|
||||
be,a 1b\n\
|
||||
swap [%1],%4\n\
|
||||
cmp %2,%4\n\
|
||||
be,a 2f\n\
|
||||
swap [%1],%3\n\
|
||||
swap [%1],%4\n\
|
||||
ba 3f\n\
|
||||
mov 0,%0\n\
|
||||
2: mov 1,%0\n\
|
||||
3:"
|
||||
: "=r" (res)
|
||||
: "r" (w), "r" (ov), "r" (nv), "r" (-1));
|
||||
#else /* ULTRA_SPARC */
|
||||
JS_ASSERT(ov != nv);
|
||||
asm volatile ("\
|
||||
stbar\n\
|
||||
cas [%1],%2,%3\n\
|
||||
cmp %2,%3\n\
|
||||
be,a 1f\n\
|
||||
mov 1,%0\n\
|
||||
mov 0,%0\n\
|
||||
1:"
|
||||
: "=r" (res)
|
||||
: "r" (w), "r" (ov), "r" (nv));
|
||||
#endif /* ULTRA_SPARC */
|
||||
return (int)res;
|
||||
#else /* !__GNUC__ */
|
||||
extern int compare_and_swap(jsword*,jsword,jsword);
|
||||
#ifndef ULTRA_SPARC
|
||||
JS_ASSERT(nv != -1);
|
||||
#else
|
||||
JS_ASSERT(ov != nv);
|
||||
#endif
|
||||
return compare_and_swap(w,ov,nv);
|
||||
#endif
|
||||
}
|
||||
|
||||
#elif defined(AIX) && !defined(NSPR_LOCK)
|
||||
#include <sys/atomic_op.h>
|
||||
|
||||
JS_INLINE int
|
||||
js_CompareAndSwap(jsword *w, jsword ov, jsword nv)
|
||||
{
|
||||
return !_check_lock(w,ov,nv);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static PRLock *_counter_lock;
|
||||
#define UsingCounterLock 1
|
||||
|
||||
#undef AtomicAddBody
|
||||
#define AtomicAddBody(P,I) \
|
||||
PR_Lock(_counter_lock);\
|
||||
*(P) += I;\
|
||||
PR_Unlock(_counter_lock);
|
||||
|
||||
static PRLock *_compare_and_swap_lock;
|
||||
#define UsingCompareAndSwapLock 1
|
||||
|
||||
JS_INLINE int
|
||||
js_CompareAndSwap(jsword *w, jsword ov, jsword nv)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
PR_Lock(_compare_and_swap_lock);
|
||||
if (*w == ov) {
|
||||
*w = nv;
|
||||
res = 1;
|
||||
}
|
||||
PR_Unlock(_compare_and_swap_lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif /* arch-tests */
|
||||
|
||||
JS_INLINE void
|
||||
js_AtomicAdd(jsword *p, jsword i)
|
||||
{
|
||||
AtomicAddBody(p,i);
|
||||
}
|
||||
|
||||
static JS_INLINE jsword
|
||||
js_AtomicSet(jsword *p, jsword n)
|
||||
{
|
||||
jsword o;
|
||||
do {
|
||||
o = ReadWord(*p);
|
||||
} while (!js_CompareAndSwap(p,o,n));
|
||||
return o;
|
||||
}
|
||||
|
||||
jsword
|
||||
js_CurrentThreadId()
|
||||
{
|
||||
return CurrentThreadId();
|
||||
}
|
||||
|
||||
void
|
||||
js_NewLock(JSThinLock *p)
|
||||
{
|
||||
#ifdef NSPR_LOCK
|
||||
p->owner = 0;
|
||||
p->fat = (JSFatLock*)JS_NEW_LOCK();
|
||||
#else
|
||||
memset(p, 0, sizeof(JSThinLock));
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
js_DestroyLock(JSThinLock *p)
|
||||
{
|
||||
#ifdef NSPR_LOCK
|
||||
p->owner = 0xdeadbeef;
|
||||
JS_DESTROY_LOCK(((JSLock*)p->fat));
|
||||
#else
|
||||
JS_ASSERT(p->owner == 0);
|
||||
JS_ASSERT(p->fat == NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void js_Dequeue(JSThinLock *);
|
||||
|
||||
JS_INLINE jsval
|
||||
js_GetSlotWhileLocked(JSContext *cx, JSObject *obj, uint32 slot)
|
||||
{
|
||||
jsval v;
|
||||
#ifndef NSPR_LOCK
|
||||
JSScope *scp = (JSScope *)obj->map;
|
||||
JSThinLock *p = &scp->lock;
|
||||
jsword me = cx->thread;
|
||||
#endif
|
||||
|
||||
JS_ASSERT(obj->slots && slot < obj->map->freeslot);
|
||||
#ifndef NSPR_LOCK
|
||||
JS_ASSERT(me == CurrentThreadId());
|
||||
if (js_CompareAndSwap(&p->owner, 0, me)) {
|
||||
if (scp == (JSScope *)obj->map) {
|
||||
v = obj->slots[slot];
|
||||
if (!js_CompareAndSwap(&p->owner, me, 0)) {
|
||||
scp->count = 1;
|
||||
js_UnlockObj(cx,obj);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
if (!js_CompareAndSwap(&p->owner, me, 0))
|
||||
js_Dequeue(p);
|
||||
}
|
||||
else if (Thin_RemoveWait(ReadWord(p->owner)) == me) {
|
||||
return obj->slots[slot];
|
||||
}
|
||||
#endif
|
||||
js_LockObj(cx,obj);
|
||||
v = obj->slots[slot];
|
||||
js_UnlockObj(cx,obj);
|
||||
return v;
|
||||
}
|
||||
|
||||
JS_INLINE void
|
||||
js_SetSlotWhileLocked(JSContext *cx, JSObject *obj, uint32 slot, jsval v)
|
||||
{
|
||||
#ifndef NSPR_LOCK
|
||||
JSScope *scp = (JSScope *)obj->map;
|
||||
JSThinLock *p = &scp->lock;
|
||||
jsword me = cx->thread;
|
||||
#endif
|
||||
|
||||
JS_ASSERT(obj->slots && slot < obj->map->freeslot);
|
||||
#ifndef NSPR_LOCK
|
||||
JS_ASSERT(me == CurrentThreadId());
|
||||
if (js_CompareAndSwap(&p->owner, 0, me)) {
|
||||
if (scp == (JSScope *)obj->map) {
|
||||
obj->slots[slot] = v;
|
||||
if (!js_CompareAndSwap(&p->owner, me, 0)) {
|
||||
scp->count = 1;
|
||||
js_UnlockObj(cx,obj);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!js_CompareAndSwap(&p->owner, me, 0))
|
||||
js_Dequeue(p);
|
||||
}
|
||||
else if (Thin_RemoveWait(ReadWord(p->owner)) == me) {
|
||||
obj->slots[slot] = v;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
js_LockObj(cx,obj);
|
||||
obj->slots[slot] = v;
|
||||
js_UnlockObj(cx,obj);
|
||||
}
|
||||
|
||||
static JSFatLock *
|
||||
mallocFatlock()
|
||||
{
|
||||
JSFatLock *fl = (JSFatLock *)malloc(sizeof(JSFatLock)); /* for now */
|
||||
JS_ASSERT(fl);
|
||||
fl->susp = 0;
|
||||
fl->next = NULL;
|
||||
fl->prev = NULL;
|
||||
fl->slock = PR_NewLock();
|
||||
fl->svar = PR_NewCondVar(fl->slock);
|
||||
return fl;
|
||||
}
|
||||
|
||||
static void
|
||||
freeFatlock(JSFatLock *fl)
|
||||
{
|
||||
PR_DestroyLock(fl->slock);
|
||||
PR_DestroyCondVar(fl->svar);
|
||||
free(fl);
|
||||
}
|
||||
|
||||
static int
|
||||
js_SuspendThread(JSThinLock *p)
|
||||
{
|
||||
JSFatLock *fl;
|
||||
JSStatus stat;
|
||||
|
||||
while ((fl = (JSFatLock*)js_AtomicSet((jsword*)&p->fat,1)) == (JSFatLock*)1) /* busy wait */
|
||||
PR_Sleep(PR_INTERVAL_NO_WAIT);
|
||||
if (fl == NULL)
|
||||
return 1;
|
||||
PR_Lock(fl->slock);
|
||||
js_AtomicSet((jsword*)&p->fat,(jsword)fl);
|
||||
fl->susp++;
|
||||
if (fl->susp < 1) {
|
||||
PR_Unlock(fl->slock);
|
||||
return 1;
|
||||
}
|
||||
stat = PR_WaitCondVar(fl->svar,PR_INTERVAL_NO_TIMEOUT);
|
||||
if (stat == JS_FAILURE) {
|
||||
fl->susp--;
|
||||
return 0;
|
||||
}
|
||||
PR_Unlock(fl->slock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
js_ResumeThread(JSThinLock *p)
|
||||
{
|
||||
JSFatLock *fl;
|
||||
JSStatus stat;
|
||||
|
||||
while ((fl = (JSFatLock*)js_AtomicSet((jsword*)&p->fat,1)) == (JSFatLock*)1)
|
||||
PR_Sleep(PR_INTERVAL_NO_WAIT);
|
||||
if (fl == NULL)
|
||||
return;
|
||||
PR_Lock(fl->slock);
|
||||
js_AtomicSet((jsword*)&p->fat,(jsword)fl);
|
||||
fl->susp--;
|
||||
if (fl->susp < 0) {
|
||||
PR_Unlock(fl->slock);
|
||||
return;
|
||||
}
|
||||
stat = PR_NotifyCondVar(fl->svar);
|
||||
JS_ASSERT(stat != JS_FAILURE);
|
||||
PR_Unlock(fl->slock);
|
||||
}
|
||||
|
||||
static JSFatLock *
|
||||
listOfFatlocks(int l)
|
||||
{
|
||||
JSFatLock *m;
|
||||
JSFatLock *m0;
|
||||
int i;
|
||||
|
||||
JS_ASSERT(l>0);
|
||||
m0 = m = mallocFatlock();
|
||||
for (i=1; i<l; i++) {
|
||||
m->next = mallocFatlock();
|
||||
m = m->next;
|
||||
}
|
||||
return m0;
|
||||
}
|
||||
|
||||
static void
|
||||
deleteListOfFatlocks(JSFatLock *m)
|
||||
{
|
||||
JSFatLock *m0;
|
||||
for (; m; m=m0) {
|
||||
m0 = m->next;
|
||||
freeFatlock(m);
|
||||
}
|
||||
}
|
||||
|
||||
static JSFatLockTable _fl_table;
|
||||
|
||||
static JSFatLock *
|
||||
allocateFatlock()
|
||||
{
|
||||
JSFatLock *m;
|
||||
|
||||
js_LockGlobal();
|
||||
if (_fl_table.free == NULL) {
|
||||
#ifdef DEBUG
|
||||
printf("Ran out of fat locks!\n");
|
||||
#endif
|
||||
_fl_table.free = listOfFatlocks(10);
|
||||
}
|
||||
m = _fl_table.free;
|
||||
_fl_table.free = m->next;
|
||||
_fl_table.free->prev = NULL;
|
||||
m->susp = 0;
|
||||
m->next = _fl_table.taken;
|
||||
m->prev = NULL;
|
||||
if (_fl_table.taken != NULL)
|
||||
_fl_table.taken->prev = m;
|
||||
_fl_table.taken = m;
|
||||
js_UnlockGlobal();
|
||||
return m;
|
||||
}
|
||||
|
||||
static void
|
||||
deallocateFatlock(JSFatLock *m)
|
||||
{
|
||||
if (m == NULL)
|
||||
return;
|
||||
js_LockGlobal();
|
||||
if (m->prev != NULL)
|
||||
m->prev->next = m->next;
|
||||
if (m->next != NULL)
|
||||
m->next->prev = m->prev;
|
||||
if (m == _fl_table.taken)
|
||||
_fl_table.taken = m->next;
|
||||
m->next = _fl_table.free;
|
||||
_fl_table.free = m;
|
||||
js_UnlockGlobal();
|
||||
}
|
||||
|
||||
int
|
||||
js_SetupLocks(int l)
|
||||
{
|
||||
if (l > 10000) /* l equals number of initially allocated fat locks */
|
||||
#ifdef DEBUG
|
||||
printf("Number %d very large in js_SetupLocks()!\n",l);
|
||||
#endif
|
||||
if (_global_lock)
|
||||
return 1;
|
||||
_global_lock = PR_NewLock();
|
||||
JS_ASSERT(_global_lock);
|
||||
#ifdef UsingCounterLock
|
||||
_counter_lock = PR_NewLock();
|
||||
JS_ASSERT(_counter_lock);
|
||||
#endif
|
||||
#ifdef UsingCompareAndSwapLock
|
||||
_compare_and_swap_lock = PR_NewLock();
|
||||
JS_ASSERT(_compare_and_swap_lock);
|
||||
#endif
|
||||
_fl_table.free = listOfFatlocks(l);
|
||||
_fl_table.taken = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
js_CleanupLocks()
|
||||
{
|
||||
if (_global_lock != NULL) {
|
||||
deleteListOfFatlocks(_fl_table.free);
|
||||
_fl_table.free = NULL;
|
||||
deleteListOfFatlocks(_fl_table.taken);
|
||||
_fl_table.taken = NULL;
|
||||
PR_DestroyLock(_global_lock);
|
||||
_global_lock = NULL;
|
||||
#ifdef UsingCounterLock
|
||||
PR_DestroyLock(_counter_lock);
|
||||
_counter_lock = NULL;
|
||||
#endif
|
||||
#ifdef UsingCompareAndSwapLock
|
||||
PR_DestroyLock(_compare_and_swap_lock);
|
||||
_compare_and_swap_lock = NULL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
js_InitContextForLocking(JSContext *cx)
|
||||
{
|
||||
cx->thread = CurrentThreadId();
|
||||
JS_ASSERT(Thin_GetWait(cx->thread) == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
It is important that emptyFatlock() clears p->fat in the empty case
|
||||
while holding p->slock. This serializes the access of p->fat wrt
|
||||
js_SuspendThread(), which also requires p->slock. There would
|
||||
otherwise be a race condition as follows. Thread A is about to
|
||||
clear p->fat, having woken up after being suspended in a situation
|
||||
where no other thread has yet suspended on p. However, suppose
|
||||
thread B is about to suspend on p, having just released the global
|
||||
lock, and is currently calling js_SuspendThread(). In the unfortunate
|
||||
case where A precedes B ever so slightly, A will think that it
|
||||
should clear p->fat (being currently empty but not for long), at the
|
||||
same time as B is about to suspend on p->fat. Now, A deallocates
|
||||
p->fat while B is about to suspend on it. Thus, the suspension of B
|
||||
is lost and B will not be properly activated.
|
||||
|
||||
Using p->slock as below (and correspondingly in js_SuspendThread()),
|
||||
js_SuspendThread() will notice that p->fat is empty, and hence return
|
||||
immediately.
|
||||
|
||||
*/
|
||||
|
||||
static int
|
||||
emptyFatlock(JSThinLock *p)
|
||||
{
|
||||
JSFatLock *fl;
|
||||
int i;
|
||||
PRLock* lck;
|
||||
|
||||
while ((fl = (JSFatLock*)js_AtomicSet((jsword*)&p->fat,1)) == (JSFatLock*)1)
|
||||
PR_Sleep(PR_INTERVAL_NO_WAIT);
|
||||
if (fl == NULL) {
|
||||
js_AtomicSet((jsword*)&p->fat,(jsword)fl);
|
||||
return 1;
|
||||
}
|
||||
lck = fl->slock;
|
||||
PR_Lock(lck);
|
||||
i = fl->susp;
|
||||
if (i < 1) {
|
||||
fl->susp = -1;
|
||||
deallocateFatlock(fl);
|
||||
fl = NULL;
|
||||
}
|
||||
js_AtomicSet((jsword*)&p->fat,(jsword)fl);
|
||||
PR_Unlock(lck);
|
||||
return i < 1;
|
||||
}
|
||||
|
||||
/*
|
||||
Fast locking and unlocking is implemented by delaying the
|
||||
allocation of a system lock (fat lock) until contention. As long as
|
||||
a locking thread A runs uncontended, the lock is represented solely
|
||||
by storing A's identity in the object being locked.
|
||||
|
||||
If another thread B tries to lock the object currently locked by A,
|
||||
B is enqueued into a fat lock structure (which might have to be
|
||||
allocated and pointed to by the object), and suspended using NSPR
|
||||
conditional variables (wait). A wait bit (Bacon bit) is set in the
|
||||
lock word of the object, signalling to A that when releasing the
|
||||
lock, B must be dequeued and notified.
|
||||
|
||||
The basic operation of the locking primitives (js_Lock(),
|
||||
js_Unlock(), js_Enqueue(), and js_Dequeue()) is
|
||||
compare-and-swap. Hence, when locking into p, if
|
||||
compare-and-swap(p,NULL,me) succeeds this implies that p is
|
||||
unlocked. Similarly, when unlocking p, if
|
||||
compare-and-swap(p,me,NULL) succeeds this implies that p is
|
||||
uncontended (no one is waiting because the wait bit is not set).
|
||||
|
||||
Furthermore, when enqueueing (after the compare-and-swap has failed
|
||||
to lock the object), p->fat is used to serialize the different
|
||||
accesses to the fat lock. The four function thus synchronized are
|
||||
js_Enqueue, emptyFatLock, js_SuspendThread, and js_ResumeThread.
|
||||
|
||||
When dequeueing, the lock is released, and one of the threads
|
||||
suspended on the lock is notified. If other threads still are
|
||||
waiting, the wait bit is kept (in js_Enqueue), and if not, the fat
|
||||
lock is deallocated (in emptyFatlock()).
|
||||
|
||||
p->fat is set to 1 by enqueue and emptyFatlock to signal that the pointer
|
||||
is being accessed.
|
||||
|
||||
*/
|
||||
|
||||
static void
|
||||
js_Enqueue(JSThinLock *p, jsword me)
|
||||
{
|
||||
jsword o, n;
|
||||
|
||||
while (1) {
|
||||
o = ReadWord(p->owner);
|
||||
n = Thin_SetWait(o);
|
||||
if (o != 0 && js_CompareAndSwap(&p->owner,o,n)) {
|
||||
JSFatLock* fl;
|
||||
while ((fl = (JSFatLock*)js_AtomicSet((jsword*)&p->fat,1)) == (JSFatLock*)1)
|
||||
PR_Sleep(PR_INTERVAL_NO_WAIT);
|
||||
if (fl == NULL)
|
||||
fl = allocateFatlock();
|
||||
js_AtomicSet((jsword*)&p->fat,(jsword)fl);
|
||||
js_SuspendThread(p);
|
||||
if (emptyFatlock(p))
|
||||
me = Thin_RemoveWait(me);
|
||||
else
|
||||
me = Thin_SetWait(me);
|
||||
}
|
||||
else if (js_CompareAndSwap(&p->owner,0,me)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
js_Dequeue(JSThinLock *p)
|
||||
{
|
||||
int o = ReadWord(p->owner);
|
||||
JS_ASSERT(Thin_GetWait(o));
|
||||
if (!js_CompareAndSwap(&p->owner,o,0)) /* release it */
|
||||
JS_ASSERT(0);
|
||||
js_ResumeThread(p);
|
||||
}
|
||||
|
||||
JS_INLINE void
|
||||
js_Lock(JSThinLock *p, jsword me)
|
||||
{
|
||||
JS_ASSERT(me == CurrentThreadId());
|
||||
if (js_CompareAndSwap(&p->owner, 0, me))
|
||||
return;
|
||||
if (Thin_RemoveWait(ReadWord(p->owner)) != me)
|
||||
js_Enqueue(p, me);
|
||||
#ifdef DEBUG
|
||||
else
|
||||
JS_ASSERT(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
JS_INLINE void
|
||||
js_Unlock(JSThinLock *p, jsword me)
|
||||
{
|
||||
JS_ASSERT(me == CurrentThreadId());
|
||||
if (js_CompareAndSwap(&p->owner, me, 0))
|
||||
return;
|
||||
if (Thin_RemoveWait(ReadWord(p->owner)) == me)
|
||||
js_Dequeue(p);
|
||||
#ifdef DEBUG
|
||||
else
|
||||
JS_ASSERT(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
js_LockRuntime(JSRuntime *rt)
|
||||
{
|
||||
jsword me = CurrentThreadId();
|
||||
JSThinLock *p;
|
||||
|
||||
JS_ASSERT(Thin_RemoveWait(ReadWord(rt->rtLock.owner)) != me);
|
||||
p = &rt->rtLock;
|
||||
JS_LOCK0(p,me);
|
||||
}
|
||||
|
||||
void
|
||||
js_UnlockRuntime(JSRuntime *rt)
|
||||
{
|
||||
jsword me = CurrentThreadId();
|
||||
JSThinLock *p;
|
||||
|
||||
JS_ASSERT(Thin_RemoveWait(ReadWord(rt->rtLock.owner)) == me);
|
||||
p = &rt->rtLock;
|
||||
JS_UNLOCK0(p,me);
|
||||
}
|
||||
|
||||
static JS_INLINE void
|
||||
js_LockScope1(JSContext *cx, JSScope *scope, jsword me)
|
||||
{
|
||||
JSThinLock *p;
|
||||
|
||||
if (Thin_RemoveWait(ReadWord(scope->lock.owner)) == me) {
|
||||
JS_ASSERT(scope->count > 0);
|
||||
scope->count++;
|
||||
} else {
|
||||
p = &scope->lock;
|
||||
JS_LOCK0(p,me);
|
||||
JS_ASSERT(scope->count == 0);
|
||||
scope->count = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
js_LockScope(JSContext *cx, JSScope *scope)
|
||||
{
|
||||
JS_ASSERT(cx->thread == CurrentThreadId());
|
||||
js_LockScope1(cx,scope,cx->thread);
|
||||
}
|
||||
|
||||
void
|
||||
js_UnlockScope(JSContext *cx, JSScope *scope)
|
||||
{
|
||||
jsword me = cx->thread;
|
||||
JSThinLock *p;
|
||||
|
||||
JS_ASSERT(scope->count > 0);
|
||||
if (Thin_RemoveWait(ReadWord(scope->lock.owner)) != me) {
|
||||
JS_ASSERT(0);
|
||||
return;
|
||||
}
|
||||
if (--scope->count == 0) {
|
||||
p = &scope->lock;
|
||||
JS_UNLOCK0(p,me);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
js_TransferScopeLock(JSContext *cx, JSScope *oldscope, JSScope *newscope)
|
||||
{
|
||||
jsword me;
|
||||
JSThinLock *p;
|
||||
|
||||
JS_ASSERT(JS_IS_SCOPE_LOCKED(newscope));
|
||||
/*
|
||||
* If the last reference to oldscope went away, newscope needs no lock
|
||||
* state update.
|
||||
*/
|
||||
if (!oldscope) {
|
||||
return;
|
||||
}
|
||||
JS_ASSERT(JS_IS_SCOPE_LOCKED(oldscope));
|
||||
/*
|
||||
* Transfer oldscope's entry count to newscope, as it will be unlocked
|
||||
* now via JS_UNLOCK_OBJ(cx,obj) calls made while we unwind the C stack
|
||||
* from the current point (under js_GetMutableScope).
|
||||
*/
|
||||
newscope->count = oldscope->count;
|
||||
/*
|
||||
* Reset oldscope's lock state so that it is completely unlocked.
|
||||
*/
|
||||
oldscope->count = 0;
|
||||
p = &oldscope->lock;
|
||||
me = cx->thread;
|
||||
JS_UNLOCK0(p,me);
|
||||
}
|
||||
|
||||
void
|
||||
js_LockObj(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JSScope *scope;
|
||||
jsword me = cx->thread;
|
||||
JS_ASSERT(me == CurrentThreadId());
|
||||
for (;;) {
|
||||
scope = (JSScope *) obj->map;
|
||||
js_LockScope1(cx, scope, me);
|
||||
|
||||
/* If obj still has this scope, we're done. */
|
||||
if (scope == (JSScope *) obj->map)
|
||||
return;
|
||||
|
||||
/* Lost a race with a mutator; retry with obj's new scope. */
|
||||
js_UnlockScope(cx, scope);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
js_UnlockObj(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
js_UnlockScope(cx, (JSScope *) obj->map);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
JSBool
|
||||
js_IsRuntimeLocked(JSRuntime *rt)
|
||||
{
|
||||
return CurrentThreadId() == Thin_RemoveWait(ReadWord(rt->rtLock.owner));
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_IsObjLocked(JSObject *obj)
|
||||
{
|
||||
JSObjectMap *map = obj->map;
|
||||
|
||||
return MAP_IS_NATIVE(map) && CurrentThreadId() == Thin_RemoveWait(ReadWord(((JSScope *)map)->lock.owner));
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_IsScopeLocked(JSScope *scope)
|
||||
{
|
||||
return CurrentThreadId() == Thin_RemoveWait(ReadWord(scope->lock.owner));
|
||||
}
|
||||
#endif
|
||||
|
||||
#undef ReadWord
|
||||
#endif /* JS_THREADSAFE */
|
||||
213
mozilla/js/src/jslock.h
Normal file
213
mozilla/js/src/jslock.h
Normal file
@@ -0,0 +1,213 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
#ifndef jslock_h__
|
||||
#define jslock_h__
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
|
||||
#include "jstypes.h"
|
||||
#include "prlock.h"
|
||||
#include "prcvar.h"
|
||||
#include "jshash.h" /* Added by JSIFY */
|
||||
|
||||
#define Thin_GetWait(W) ((jsword)(W) & 0x1)
|
||||
#define Thin_SetWait(W) ((jsword)(W) | 0x1)
|
||||
#define Thin_RemoveWait(W) ((jsword)(W) & ~0x1)
|
||||
|
||||
typedef struct JSFatLock {
|
||||
int susp;
|
||||
PRLock* slock;
|
||||
PRCondVar* svar;
|
||||
struct JSFatLock *next;
|
||||
struct JSFatLock *prev;
|
||||
} JSFatLock;
|
||||
|
||||
typedef struct JSThinLock {
|
||||
jsword owner;
|
||||
JSFatLock *fat;
|
||||
} JSThinLock;
|
||||
|
||||
typedef PRLock JSLock;
|
||||
|
||||
typedef struct JSFatLockTable {
|
||||
JSFatLock *free;
|
||||
JSFatLock *taken;
|
||||
} JSFatLockTable;
|
||||
|
||||
#define JS_ATOMIC_ADDREF(p, i) js_AtomicAdd(p,i)
|
||||
|
||||
#define CurrentThreadId() (jsword)PR_GetCurrentThread()
|
||||
#define JS_CurrentThreadId() js_CurrentThreadId()
|
||||
#define JS_NEW_LOCK() PR_NewLock()
|
||||
#define JS_DESTROY_LOCK(l) PR_DestroyLock(l)
|
||||
#define JS_ACQUIRE_LOCK(l) PR_Lock(l)
|
||||
#define JS_RELEASE_LOCK(l) PR_Unlock(l)
|
||||
#define JS_LOCK0(P,M) js_Lock(P,M)
|
||||
#define JS_UNLOCK0(P,M) js_Unlock(P,M)
|
||||
|
||||
#define JS_NEW_CONDVAR(l) PR_NewCondVar(l)
|
||||
#define JS_DESTROY_CONDVAR(cv) PR_DestroyCondVar(cv)
|
||||
#define JS_WAIT_CONDVAR(cv,to) PR_WaitCondVar(cv,to)
|
||||
#define JS_NO_TIMEOUT PR_INTERVAL_NO_TIMEOUT
|
||||
#define JS_NOTIFY_CONDVAR(cv) PR_NotifyCondVar(cv)
|
||||
#define JS_NOTIFY_ALL_CONDVAR(cv) PR_NotifyAllCondVar(cv)
|
||||
|
||||
#ifdef DEBUG
|
||||
#include "jsscope.h"
|
||||
|
||||
#define _SET_OBJ_INFO(obj,f,l) \
|
||||
_SET_SCOPE_INFO(((JSScope*)obj->map),f,l)
|
||||
|
||||
#define _SET_SCOPE_INFO(scope,f,l) \
|
||||
(JS_ASSERT(scope->count > 0 && scope->count <= 4), \
|
||||
scope->file[scope->count-1] = f, \
|
||||
scope->line[scope->count-1] = l)
|
||||
#endif /* DEBUG */
|
||||
|
||||
#define JS_LOCK_RUNTIME(rt) js_LockRuntime(rt)
|
||||
#define JS_UNLOCK_RUNTIME(rt) js_UnlockRuntime(rt)
|
||||
#define JS_LOCK_OBJ(cx,obj) (js_LockObj(cx, obj), \
|
||||
_SET_OBJ_INFO(obj,__FILE__,__LINE__))
|
||||
#define JS_UNLOCK_OBJ(cx,obj) js_UnlockObj(cx, obj)
|
||||
#define JS_LOCK_SCOPE(cx,scope) (js_LockScope(cx, scope), \
|
||||
_SET_SCOPE_INFO(scope,__FILE__,__LINE__))
|
||||
#define JS_UNLOCK_SCOPE(cx,scope) js_UnlockScope(cx, scope)
|
||||
#define JS_TRANSFER_SCOPE_LOCK(cx, scope, newscope) js_TransferScopeLock(cx, scope, newscope)
|
||||
|
||||
extern jsword js_CurrentThreadId();
|
||||
extern JS_INLINE void js_Lock(JSThinLock *, jsword);
|
||||
extern JS_INLINE void js_Unlock(JSThinLock *, jsword);
|
||||
extern int js_CompareAndSwap(jsword *, jsword, jsword);
|
||||
extern void js_AtomicAdd(jsword*, jsword);
|
||||
extern void js_LockRuntime(JSRuntime *rt);
|
||||
extern void js_UnlockRuntime(JSRuntime *rt);
|
||||
extern void js_LockObj(JSContext *cx, JSObject *obj);
|
||||
extern void js_UnlockObj(JSContext *cx, JSObject *obj);
|
||||
extern void js_LockScope(JSContext *cx, JSScope *scope);
|
||||
extern void js_UnlockScope(JSContext *cx, JSScope *scope);
|
||||
extern int js_SetupLocks(int);
|
||||
extern void js_CleanupLocks();
|
||||
extern JS_PUBLIC_API(void) js_InitContextForLocking(JSContext *);
|
||||
extern void js_TransferScopeLock(JSContext *, JSScope *, JSScope *);
|
||||
extern JS_PUBLIC_API(jsval) js_GetSlotWhileLocked(JSContext *, JSObject *, uint32);
|
||||
extern JS_PUBLIC_API(void) js_SetSlotWhileLocked(JSContext *, JSObject *, uint32, jsval);
|
||||
extern void js_NewLock(JSThinLock *);
|
||||
extern void js_DestroyLock(JSThinLock *);
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
#define JS_IS_RUNTIME_LOCKED(rt) js_IsRuntimeLocked(rt)
|
||||
#define JS_IS_OBJ_LOCKED(obj) js_IsObjLocked(obj)
|
||||
#define JS_IS_SCOPE_LOCKED(scope) js_IsScopeLocked(scope)
|
||||
|
||||
extern JSBool js_IsRuntimeLocked(JSRuntime *rt);
|
||||
extern JSBool js_IsObjLocked(JSObject *obj);
|
||||
extern JSBool js_IsScopeLocked(JSScope *scope);
|
||||
|
||||
#else
|
||||
|
||||
#define JS_IS_RUNTIME_LOCKED(rt) 0
|
||||
#define JS_IS_OBJ_LOCKED(obj) 1
|
||||
#define JS_IS_SCOPE_LOCKED(scope) 1
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
||||
#define JS_LOCK_OBJ_VOID(cx, obj, e) \
|
||||
JS_BEGIN_MACRO \
|
||||
js_LockObj(cx, obj); \
|
||||
e; \
|
||||
js_UnlockObj(cx, obj); \
|
||||
JS_END_MACRO
|
||||
|
||||
#define JS_LOCK_VOID(cx, e) \
|
||||
JS_BEGIN_MACRO \
|
||||
JSRuntime *_rt = (cx)->runtime; \
|
||||
JS_LOCK_RUNTIME_VOID(_rt, e); \
|
||||
JS_END_MACRO
|
||||
|
||||
#if defined(JS_USE_ONLY_NSPR_LOCKS) || !(defined(_WIN32) || defined(SOLARIS) || defined(AIX))
|
||||
|
||||
#undef JS_LOCK0
|
||||
#undef JS_UNLOCK0
|
||||
#define JS_LOCK0(P,M) JS_ACQUIRE_LOCK(((JSLock*)(P)->fat)); (P)->owner = (M)
|
||||
#define JS_UNLOCK0(P,M) (P)->owner = 0; JS_RELEASE_LOCK(((JSLock*)(P)->fat))
|
||||
#define NSPR_LOCK 1
|
||||
|
||||
#endif /* arch-tests */
|
||||
|
||||
#else /* !JS_THREADSAFE */
|
||||
|
||||
#define JS_ATOMIC_ADDREF(p,i) (*(p) += i)
|
||||
|
||||
#define JS_CurrentThreadId() 0
|
||||
#define JS_NEW_LOCK() NULL
|
||||
#define JS_DESTROY_LOCK(l) ((void)0)
|
||||
#define JS_ACQUIRE_LOCK(l) ((void)0)
|
||||
#define JS_RELEASE_LOCK(l) ((void)0)
|
||||
#define JS_LOCK0(P,M) ((void)0)
|
||||
#define JS_UNLOCK0(P,M) ((void)0)
|
||||
|
||||
#define JS_NEW_CONDVAR(l) NULL
|
||||
#define JS_DESTROY_CONDVAR(cv) ((void)0)
|
||||
#define JS_WAIT_CONDVAR(cv,to) ((void)0)
|
||||
#define JS_NOTIFY_CONDVAR(cv) ((void)0)
|
||||
#define JS_NOTIFY_ALL_CONDVAR(cv) ((void)0)
|
||||
|
||||
#define JS_LOCK_RUNTIME(rt) ((void)0)
|
||||
#define JS_UNLOCK_RUNTIME(rt) ((void)0)
|
||||
#define JS_LOCK_OBJ(cx,obj) ((void)0)
|
||||
#define JS_UNLOCK_OBJ(cx,obj) ((void)0)
|
||||
#define JS_LOCK_OBJ_VOID(cx,obj,e) (e)
|
||||
#define JS_LOCK_SCOPE(cx,scope) ((void)0)
|
||||
#define JS_UNLOCK_SCOPE(cx,scope) ((void)0)
|
||||
#define JS_TRANSFER_SCOPE_LOCK(c,o,n) ((void)0)
|
||||
|
||||
#define JS_IS_RUNTIME_LOCKED(rt) 1
|
||||
#define JS_IS_OBJ_LOCKED(obj) 1
|
||||
#define JS_IS_SCOPE_LOCKED(scope) 1
|
||||
#define JS_LOCK_VOID(cx, e) JS_LOCK_RUNTIME_VOID((cx)->runtime, e)
|
||||
|
||||
#endif /* !JS_THREADSAFE */
|
||||
|
||||
#define JS_LOCK_RUNTIME_VOID(rt,e) \
|
||||
JS_BEGIN_MACRO \
|
||||
JS_LOCK_RUNTIME(rt); \
|
||||
e; \
|
||||
JS_UNLOCK_RUNTIME(rt); \
|
||||
JS_END_MACRO
|
||||
|
||||
#define JS_LOCK_GC(rt) JS_ACQUIRE_LOCK((rt)->gcLock)
|
||||
#define JS_UNLOCK_GC(rt) JS_RELEASE_LOCK((rt)->gcLock)
|
||||
#define JS_LOCK_GC_VOID(rt,e) (JS_LOCK_GC(rt), (e), JS_UNLOCK_GC(rt))
|
||||
#define JS_AWAIT_GC_DONE(rt) JS_WAIT_CONDVAR((rt)->gcDone, JS_NO_TIMEOUT)
|
||||
#define JS_NOTIFY_GC_DONE(rt) JS_NOTIFY_ALL_CONDVAR((rt)->gcDone)
|
||||
#define JS_AWAIT_REQUEST_DONE(rt) JS_WAIT_CONDVAR((rt)->requestDone, \
|
||||
JS_NO_TIMEOUT)
|
||||
#define JS_NOTIFY_REQUEST_DONE(rt) JS_NOTIFY_CONDVAR((rt)->requestDone)
|
||||
|
||||
#define JS_LOCK(P,CX) JS_LOCK0(P,(CX)->thread)
|
||||
#define JS_UNLOCK(P,CX) JS_UNLOCK0(P,(CX)->thread)
|
||||
|
||||
#ifndef _SET_OBJ_INFO
|
||||
#define _SET_OBJ_INFO(obj,f,l) ((void)0)
|
||||
#endif
|
||||
#ifndef _SET_SCOPE_INFO
|
||||
#define _SET_SCOPE_INFO(scope,f,l) ((void)0)
|
||||
#endif
|
||||
|
||||
#endif /* jslock_h___ */
|
||||
62
mozilla/js/src/jslog2.c
Normal file
62
mozilla/js/src/jslog2.c
Normal file
@@ -0,0 +1,62 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "jsbit.h"
|
||||
|
||||
/*
|
||||
** Compute the log of the least power of 2 greater than or equal to n
|
||||
*/
|
||||
JS_EXPORT_API(JSIntn) JS_CeilingLog2(JSUint32 n)
|
||||
{
|
||||
JSIntn log2 = 0;
|
||||
|
||||
if (n & (n-1))
|
||||
log2++;
|
||||
if (n >> 16)
|
||||
log2 += 16, n >>= 16;
|
||||
if (n >> 8)
|
||||
log2 += 8, n >>= 8;
|
||||
if (n >> 4)
|
||||
log2 += 4, n >>= 4;
|
||||
if (n >> 2)
|
||||
log2 += 2, n >>= 2;
|
||||
if (n >> 1)
|
||||
log2++;
|
||||
return log2;
|
||||
}
|
||||
|
||||
/*
|
||||
** Compute the log of the greatest power of 2 less than or equal to n.
|
||||
** This really just finds the highest set bit in the word.
|
||||
*/
|
||||
JS_EXPORT_API(JSIntn) JS_FloorLog2(JSUint32 n)
|
||||
{
|
||||
JSIntn log2 = 0;
|
||||
|
||||
if (n >> 16)
|
||||
log2 += 16, n >>= 16;
|
||||
if (n >> 8)
|
||||
log2 += 8, n >>= 8;
|
||||
if (n >> 4)
|
||||
log2 += 4, n >>= 4;
|
||||
if (n >> 2)
|
||||
log2 += 2, n >>= 2;
|
||||
if (n >> 1)
|
||||
log2++;
|
||||
return log2;
|
||||
}
|
||||
260
mozilla/js/src/jslong.c
Normal file
260
mozilla/js/src/jslong.c
Normal file
@@ -0,0 +1,260 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "jstypes.h"
|
||||
#include "jslong.h"
|
||||
|
||||
static JSInt64 ll_zero = JSLL_INIT( 0x00000000,0x00000000 );
|
||||
static JSInt64 ll_maxint = JSLL_INIT( 0x7fffffff, 0xffffffff );
|
||||
static JSInt64 ll_minint = JSLL_INIT( 0x80000000, 0x00000000 );
|
||||
|
||||
#ifdef HAVE_WATCOM_BUG_2
|
||||
JSInt64 __pascal __loadds __export
|
||||
JSLL_Zero(void) { return ll_zero; }
|
||||
JSInt64 __pascal __loadds __export
|
||||
JSLL_MaxInt(void) { return ll_maxint; }
|
||||
JSInt64 __pascal __loadds __export
|
||||
JSLL_MinInt(void) { return ll_minint; }
|
||||
#else
|
||||
JS_EXPORT_API(JSInt64) JSLL_Zero(void) { return ll_zero; }
|
||||
JS_EXPORT_API(JSInt64) JSLL_MaxInt(void) { return ll_maxint; }
|
||||
JS_EXPORT_API(JSInt64) JSLL_MinInt(void) { return ll_minint; }
|
||||
#endif
|
||||
|
||||
#ifndef JS_HAVE_LONG_LONG
|
||||
/*
|
||||
** Divide 64-bit a by 32-bit b, which must be normalized so its high bit is 1.
|
||||
*/
|
||||
static void norm_udivmod32(JSUint32 *qp, JSUint32 *rp, JSUint64 a, JSUint32 b)
|
||||
{
|
||||
JSUint32 d1, d0, q1, q0;
|
||||
JSUint32 r1, r0, m;
|
||||
|
||||
d1 = jshi16(b);
|
||||
d0 = jslo16(b);
|
||||
r1 = a.hi % d1;
|
||||
q1 = a.hi / d1;
|
||||
m = q1 * d0;
|
||||
r1 = (r1 << 16) | jshi16(a.lo);
|
||||
if (r1 < m) {
|
||||
q1--, r1 += b;
|
||||
if (r1 >= b /* i.e., we didn't get a carry when adding to r1 */
|
||||
&& r1 < m) {
|
||||
q1--, r1 += b;
|
||||
}
|
||||
}
|
||||
r1 -= m;
|
||||
r0 = r1 % d1;
|
||||
q0 = r1 / d1;
|
||||
m = q0 * d0;
|
||||
r0 = (r0 << 16) | jslo16(a.lo);
|
||||
if (r0 < m) {
|
||||
q0--, r0 += b;
|
||||
if (r0 >= b
|
||||
&& r0 < m) {
|
||||
q0--, r0 += b;
|
||||
}
|
||||
}
|
||||
*qp = (q1 << 16) | q0;
|
||||
*rp = r0 - m;
|
||||
}
|
||||
|
||||
static JSUint32 CountLeadingZeros(JSUint32 a)
|
||||
{
|
||||
JSUint32 t;
|
||||
JSUint32 r = 32;
|
||||
|
||||
if ((t = a >> 16) != 0)
|
||||
r -= 16, a = t;
|
||||
if ((t = a >> 8) != 0)
|
||||
r -= 8, a = t;
|
||||
if ((t = a >> 4) != 0)
|
||||
r -= 4, a = t;
|
||||
if ((t = a >> 2) != 0)
|
||||
r -= 2, a = t;
|
||||
if ((t = a >> 1) != 0)
|
||||
r -= 1, a = t;
|
||||
if (a & 1)
|
||||
r--;
|
||||
return r;
|
||||
}
|
||||
|
||||
JS_EXPORT_API(void) jsll_udivmod(JSUint64 *qp, JSUint64 *rp, JSUint64 a, JSUint64 b)
|
||||
{
|
||||
JSUint32 n0, n1, n2;
|
||||
JSUint32 q0, q1;
|
||||
JSUint32 rsh, lsh;
|
||||
|
||||
n0 = a.lo;
|
||||
n1 = a.hi;
|
||||
|
||||
if (b.hi == 0) {
|
||||
if (b.lo > n1) {
|
||||
/* (0 q0) = (n1 n0) / (0 D0) */
|
||||
|
||||
lsh = CountLeadingZeros(b.lo);
|
||||
|
||||
if (lsh) {
|
||||
/*
|
||||
* Normalize, i.e. make the most significant bit of the
|
||||
* denominator be set.
|
||||
*/
|
||||
b.lo = b.lo << lsh;
|
||||
n1 = (n1 << lsh) | (n0 >> (32 - lsh));
|
||||
n0 = n0 << lsh;
|
||||
}
|
||||
|
||||
a.lo = n0, a.hi = n1;
|
||||
norm_udivmod32(&q0, &n0, a, b.lo);
|
||||
q1 = 0;
|
||||
|
||||
/* remainder is in n0 >> lsh */
|
||||
} else {
|
||||
/* (q1 q0) = (n1 n0) / (0 d0) */
|
||||
|
||||
if (b.lo == 0) /* user wants to divide by zero! */
|
||||
b.lo = 1 / b.lo; /* so go ahead and crash */
|
||||
|
||||
lsh = CountLeadingZeros(b.lo);
|
||||
|
||||
if (lsh == 0) {
|
||||
/*
|
||||
* From (n1 >= b.lo)
|
||||
* && (the most significant bit of b.lo is set),
|
||||
* conclude that
|
||||
* (the most significant bit of n1 is set)
|
||||
* && (the leading quotient digit q1 = 1).
|
||||
*
|
||||
* This special case is necessary, not an optimization
|
||||
* (Shifts counts of 32 are undefined).
|
||||
*/
|
||||
n1 -= b.lo;
|
||||
q1 = 1;
|
||||
} else {
|
||||
/*
|
||||
* Normalize.
|
||||
*/
|
||||
rsh = 32 - lsh;
|
||||
|
||||
b.lo = b.lo << lsh;
|
||||
n2 = n1 >> rsh;
|
||||
n1 = (n1 << lsh) | (n0 >> rsh);
|
||||
n0 = n0 << lsh;
|
||||
|
||||
a.lo = n1, a.hi = n2;
|
||||
norm_udivmod32(&q1, &n1, a, b.lo);
|
||||
}
|
||||
|
||||
/* n1 != b.lo... */
|
||||
|
||||
a.lo = n0, a.hi = n1;
|
||||
norm_udivmod32(&q0, &n0, a, b.lo);
|
||||
|
||||
/* remainder in n0 >> lsh */
|
||||
}
|
||||
|
||||
if (rp) {
|
||||
rp->lo = n0 >> lsh;
|
||||
rp->hi = 0;
|
||||
}
|
||||
} else {
|
||||
if (b.hi > n1) {
|
||||
/* (0 0) = (n1 n0) / (D1 d0) */
|
||||
|
||||
q0 = 0;
|
||||
q1 = 0;
|
||||
|
||||
/* remainder in (n1 n0) */
|
||||
if (rp) {
|
||||
rp->lo = n0;
|
||||
rp->hi = n1;
|
||||
}
|
||||
} else {
|
||||
/* (0 q0) = (n1 n0) / (d1 d0) */
|
||||
|
||||
lsh = CountLeadingZeros(b.hi);
|
||||
if (lsh == 0) {
|
||||
/*
|
||||
* From (n1 >= b.hi)
|
||||
* && (the most significant bit of b.hi is set),
|
||||
* conclude that
|
||||
* (the most significant bit of n1 is set)
|
||||
* && (the quotient digit q0 = 0 or 1).
|
||||
*
|
||||
* This special case is necessary, not an optimization.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The condition on the next line takes advantage of that
|
||||
* n1 >= b.hi (true due to control flow).
|
||||
*/
|
||||
if (n1 > b.hi || n0 >= b.lo) {
|
||||
q0 = 1;
|
||||
a.lo = n0, a.hi = n1;
|
||||
JSLL_SUB(a, a, b);
|
||||
} else {
|
||||
q0 = 0;
|
||||
}
|
||||
q1 = 0;
|
||||
|
||||
if (rp) {
|
||||
rp->lo = n0;
|
||||
rp->hi = n1;
|
||||
}
|
||||
} else {
|
||||
JSInt64 m;
|
||||
|
||||
/*
|
||||
* Normalize.
|
||||
*/
|
||||
rsh = 32 - lsh;
|
||||
|
||||
b.hi = (b.hi << lsh) | (b.lo >> rsh);
|
||||
b.lo = b.lo << lsh;
|
||||
n2 = n1 >> rsh;
|
||||
n1 = (n1 << lsh) | (n0 >> rsh);
|
||||
n0 = n0 << lsh;
|
||||
|
||||
a.lo = n1, a.hi = n2;
|
||||
norm_udivmod32(&q0, &n1, a, b.hi);
|
||||
JSLL_MUL32(m, q0, b.lo);
|
||||
|
||||
if ((m.hi > n1) || ((m.hi == n1) && (m.lo > n0))) {
|
||||
q0--;
|
||||
JSLL_SUB(m, m, b);
|
||||
}
|
||||
|
||||
q1 = 0;
|
||||
|
||||
/* Remainder is ((n1 n0) - (m1 m0)) >> lsh */
|
||||
if (rp) {
|
||||
a.lo = n0, a.hi = n1;
|
||||
JSLL_SUB(a, a, m);
|
||||
rp->lo = (a.hi << rsh) | (a.lo >> lsh);
|
||||
rp->hi = a.hi >> lsh;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (qp) {
|
||||
qp->lo = q0;
|
||||
qp->hi = q1;
|
||||
}
|
||||
}
|
||||
#endif /* !JS_HAVE_LONG_LONG */
|
||||
409
mozilla/js/src/jslong.h
Normal file
409
mozilla/js/src/jslong.h
Normal file
@@ -0,0 +1,409 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
** File: jslong.h
|
||||
** Description: Portable access to 64 bit numerics
|
||||
**
|
||||
** Long-long (64-bit signed integer type) support. Some C compilers
|
||||
** don't support 64 bit integers yet, so we use these macros to
|
||||
** support both machines that do and don't.
|
||||
**/
|
||||
#ifndef jslong_h___
|
||||
#define jslong_h___
|
||||
|
||||
#include "jstypes.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
/***********************************************************************
|
||||
** DEFINES: JSLL_MaxInt
|
||||
** JSLL_MinInt
|
||||
** JSLL_Zero
|
||||
** DESCRIPTION:
|
||||
** Various interesting constants and static variable
|
||||
** initializer
|
||||
***********************************************************************/
|
||||
#ifdef HAVE_WATCOM_BUG_2
|
||||
JSInt64 __pascal __loadds __export
|
||||
JSLL_MaxInt(void);
|
||||
JSInt64 __pascal __loadds __export
|
||||
JSLL_MinInt(void);
|
||||
JSInt64 __pascal __loadds __export
|
||||
JSLL_Zero(void);
|
||||
#else
|
||||
JS_EXTERN_API(JSInt64) JSLL_MaxInt(void);
|
||||
JS_EXTERN_API(JSInt64) JSLL_MinInt(void);
|
||||
JS_EXTERN_API(JSInt64) JSLL_Zero(void);
|
||||
#endif
|
||||
|
||||
#define JSLL_MAXINT JSLL_MaxInt()
|
||||
#define JSLL_MININT JSLL_MinInt()
|
||||
#define JSLL_ZERO JSLL_Zero()
|
||||
|
||||
#ifdef JS_HAVE_LONG_LONG
|
||||
|
||||
#if JS_BYTES_PER_LONG == 8
|
||||
#define JSLL_INIT(hi, lo) ((hi ## L << 32) + lo ## L)
|
||||
#elif defined(WIN32) || defined(WIN16)
|
||||
#define JSLL_INIT(hi, lo) ((hi ## i64 << 32) + lo ## i64)
|
||||
#else
|
||||
#define JSLL_INIT(hi, lo) ((hi ## LL << 32) + lo ## LL)
|
||||
#endif
|
||||
|
||||
/***********************************************************************
|
||||
** MACROS: JSLL_*
|
||||
** DESCRIPTION:
|
||||
** The following macros define portable access to the 64 bit
|
||||
** math facilities.
|
||||
**
|
||||
***********************************************************************/
|
||||
|
||||
/***********************************************************************
|
||||
** MACROS: JSLL_<relational operators>
|
||||
**
|
||||
** JSLL_IS_ZERO Test for zero
|
||||
** JSLL_EQ Test for equality
|
||||
** JSLL_NE Test for inequality
|
||||
** JSLL_GE_ZERO Test for zero or positive
|
||||
** JSLL_CMP Compare two values
|
||||
***********************************************************************/
|
||||
#define JSLL_IS_ZERO(a) ((a) == 0)
|
||||
#define JSLL_EQ(a, b) ((a) == (b))
|
||||
#define JSLL_NE(a, b) ((a) != (b))
|
||||
#define JSLL_GE_ZERO(a) ((a) >= 0)
|
||||
#define JSLL_CMP(a, op, b) ((JSInt64)(a) op (JSInt64)(b))
|
||||
#define JSLL_UCMP(a, op, b) ((JSUint64)(a) op (JSUint64)(b))
|
||||
|
||||
/***********************************************************************
|
||||
** MACROS: JSLL_<logical operators>
|
||||
**
|
||||
** JSLL_AND Logical and
|
||||
** JSLL_OR Logical or
|
||||
** JSLL_XOR Logical exclusion
|
||||
** JSLL_OR2 A disgusting deviation
|
||||
** JSLL_NOT Negation (one's compliment)
|
||||
***********************************************************************/
|
||||
#define JSLL_AND(r, a, b) ((r) = (a) & (b))
|
||||
#define JSLL_OR(r, a, b) ((r) = (a) | (b))
|
||||
#define JSLL_XOR(r, a, b) ((r) = (a) ^ (b))
|
||||
#define JSLL_OR2(r, a) ((r) = (r) | (a))
|
||||
#define JSLL_NOT(r, a) ((r) = ~(a))
|
||||
|
||||
/***********************************************************************
|
||||
** MACROS: JSLL_<mathematical operators>
|
||||
**
|
||||
** JSLL_NEG Negation (two's compliment)
|
||||
** JSLL_ADD Summation (two's compliment)
|
||||
** JSLL_SUB Difference (two's compliment)
|
||||
***********************************************************************/
|
||||
#define JSLL_NEG(r, a) ((r) = -(a))
|
||||
#define JSLL_ADD(r, a, b) ((r) = (a) + (b))
|
||||
#define JSLL_SUB(r, a, b) ((r) = (a) - (b))
|
||||
|
||||
/***********************************************************************
|
||||
** MACROS: JSLL_<mathematical operators>
|
||||
**
|
||||
** JSLL_MUL Product (two's compliment)
|
||||
** JSLL_DIV Quotient (two's compliment)
|
||||
** JSLL_MOD Modulus (two's compliment)
|
||||
***********************************************************************/
|
||||
#define JSLL_MUL(r, a, b) ((r) = (a) * (b))
|
||||
#define JSLL_DIV(r, a, b) ((r) = (a) / (b))
|
||||
#define JSLL_MOD(r, a, b) ((r) = (a) % (b))
|
||||
|
||||
/***********************************************************************
|
||||
** MACROS: JSLL_<shifting operators>
|
||||
**
|
||||
** JSLL_SHL Shift left [0..64] bits
|
||||
** JSLL_SHR Shift right [0..64] bits with sign extension
|
||||
** JSLL_USHR Unsigned shift right [0..64] bits
|
||||
** JSLL_ISHL Signed shift left [0..64] bits
|
||||
***********************************************************************/
|
||||
#define JSLL_SHL(r, a, b) ((r) = (JSInt64)(a) << (b))
|
||||
#define JSLL_SHR(r, a, b) ((r) = (JSInt64)(a) >> (b))
|
||||
#define JSLL_USHR(r, a, b) ((r) = (JSUint64)(a) >> (b))
|
||||
#define JSLL_ISHL(r, a, b) ((r) = (JSInt64)(a) << (b))
|
||||
|
||||
/***********************************************************************
|
||||
** MACROS: JSLL_<conversion operators>
|
||||
**
|
||||
** JSLL_L2I Convert to signed 32 bit
|
||||
** JSLL_L2UI Convert to unsigned 32 bit
|
||||
** JSLL_L2F Convert to floating point
|
||||
** JSLL_L2D Convert to floating point
|
||||
** JSLL_I2L Convert signed to 64 bit
|
||||
** JSLL_UI2L Convert unsigned to 64 bit
|
||||
** JSLL_F2L Convert float to 64 bit
|
||||
** JSLL_D2L Convert float to 64 bit
|
||||
***********************************************************************/
|
||||
#define JSLL_L2I(i, l) ((i) = (JSInt32)(l))
|
||||
#define JSLL_L2UI(ui, l) ((ui) = (JSUint32)(l))
|
||||
#define JSLL_L2F(f, l) ((f) = (JSFloat64)(l))
|
||||
#define JSLL_L2D(d, l) ((d) = (JSFloat64)(l))
|
||||
|
||||
#define JSLL_I2L(l, i) ((l) = (JSInt64)(i))
|
||||
#define JSLL_UI2L(l, ui) ((l) = (JSInt64)(ui))
|
||||
#define JSLL_F2L(l, f) ((l) = (JSInt64)(f))
|
||||
#define JSLL_D2L(l, d) ((l) = (JSInt64)(d))
|
||||
|
||||
/***********************************************************************
|
||||
** MACROS: JSLL_UDIVMOD
|
||||
** DESCRIPTION:
|
||||
** Produce both a quotient and a remainder given an unsigned
|
||||
** INPUTS: JSUint64 a: The dividend of the operation
|
||||
** JSUint64 b: The quotient of the operation
|
||||
** OUTPUTS: JSUint64 *qp: pointer to quotient
|
||||
** JSUint64 *rp: pointer to remainder
|
||||
***********************************************************************/
|
||||
#define JSLL_UDIVMOD(qp, rp, a, b) \
|
||||
(*(qp) = ((JSUint64)(a) / (b)), \
|
||||
*(rp) = ((JSUint64)(a) % (b)))
|
||||
|
||||
#else /* !JS_HAVE_LONG_LONG */
|
||||
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
#define JSLL_INIT(hi, lo) {JS_INT32(lo), JS_INT32(hi)}
|
||||
#else
|
||||
#define JSLL_INIT(hi, lo) {JS_INT32(hi), JS_INT32(lo)}
|
||||
#endif
|
||||
|
||||
#define JSLL_IS_ZERO(a) (((a).hi == 0) && ((a).lo == 0))
|
||||
#define JSLL_EQ(a, b) (((a).hi == (b).hi) && ((a).lo == (b).lo))
|
||||
#define JSLL_NE(a, b) (((a).hi != (b).hi) || ((a).lo != (b).lo))
|
||||
#define JSLL_GE_ZERO(a) (((a).hi >> 31) == 0)
|
||||
|
||||
#define JSLL_CMP(a, op, b) (((JSInt32)(a).hi op (JSInt32)(b).hi) || \
|
||||
(((a).hi == (b).hi) && ((a).lo op (b).lo)))
|
||||
#define JSLL_UCMP(a, op, b) (((a).hi op (b).hi) || \
|
||||
(((a).hi == (b).hi) && ((a).lo op (b).lo)))
|
||||
|
||||
#define JSLL_AND(r, a, b) ((r).lo = (a).lo & (b).lo, \
|
||||
(r).hi = (a).hi & (b).hi)
|
||||
#define JSLL_OR(r, a, b) ((r).lo = (a).lo | (b).lo, \
|
||||
(r).hi = (a).hi | (b).hi)
|
||||
#define JSLL_XOR(r, a, b) ((r).lo = (a).lo ^ (b).lo, \
|
||||
(r).hi = (a).hi ^ (b).hi)
|
||||
#define JSLL_OR2(r, a) ((r).lo = (r).lo | (a).lo, \
|
||||
(r).hi = (r).hi | (a).hi)
|
||||
#define JSLL_NOT(r, a) ((r).lo = ~(a).lo, \
|
||||
(r).hi = ~(a).hi)
|
||||
|
||||
#define JSLL_NEG(r, a) ((r).lo = -(JSInt32)(a).lo, \
|
||||
(r).hi = -(JSInt32)(a).hi - ((r).lo != 0))
|
||||
#define JSLL_ADD(r, a, b) { \
|
||||
JSInt64 _a, _b; \
|
||||
_a = a; _b = b; \
|
||||
(r).lo = _a.lo + _b.lo; \
|
||||
(r).hi = _a.hi + _b.hi + ((r).lo < _b.lo); \
|
||||
}
|
||||
|
||||
#define JSLL_SUB(r, a, b) { \
|
||||
JSInt64 _a, _b; \
|
||||
_a = a; _b = b; \
|
||||
(r).lo = _a.lo - _b.lo; \
|
||||
(r).hi = _a.hi - _b.hi - (_a.lo < _b.lo); \
|
||||
}
|
||||
|
||||
#define JSLL_MUL(r, a, b) { \
|
||||
JSInt64 _a, _b; \
|
||||
_a = a; _b = b; \
|
||||
JSLL_MUL32(r, _a.lo, _b.lo); \
|
||||
(r).hi += _a.hi * _b.lo + _a.lo * _b.hi; \
|
||||
}
|
||||
|
||||
#define jslo16(a) ((a) & JS_BITMASK(16))
|
||||
#define jshi16(a) ((a) >> 16)
|
||||
|
||||
#define JSLL_MUL32(r, a, b) { \
|
||||
JSUint32 _a1, _a0, _b1, _b0, _y0, _y1, _y2, _y3; \
|
||||
_a1 = jshi16(a), _a0 = jslo16(a); \
|
||||
_b1 = jshi16(b), _b0 = jslo16(b); \
|
||||
_y0 = _a0 * _b0; \
|
||||
_y1 = _a0 * _b1; \
|
||||
_y2 = _a1 * _b0; \
|
||||
_y3 = _a1 * _b1; \
|
||||
_y1 += jshi16(_y0); /* can't carry */ \
|
||||
_y1 += _y2; /* might carry */ \
|
||||
if (_y1 < _y2) \
|
||||
_y3 += (JSUint32)(JS_BIT(16)); /* propagate */ \
|
||||
(r).lo = (jslo16(_y1) << 16) + jslo16(_y0); \
|
||||
(r).hi = _y3 + jshi16(_y1); \
|
||||
}
|
||||
|
||||
#define JSLL_UDIVMOD(qp, rp, a, b) jsll_udivmod(qp, rp, a, b)
|
||||
|
||||
JS_EXTERN_API(void) jsll_udivmod(JSUint64 *qp, JSUint64 *rp, JSUint64 a, JSUint64 b);
|
||||
|
||||
#define JSLL_DIV(r, a, b) { \
|
||||
JSInt64 _a, _b; \
|
||||
JSUint32 _negative = (JSInt32)(a).hi < 0; \
|
||||
if (_negative) { \
|
||||
JSLL_NEG(_a, a); \
|
||||
} else { \
|
||||
_a = a; \
|
||||
} \
|
||||
if ((JSInt32)(b).hi < 0) { \
|
||||
_negative ^= 1; \
|
||||
JSLL_NEG(_b, b); \
|
||||
} else { \
|
||||
_b = b; \
|
||||
} \
|
||||
JSLL_UDIVMOD(&(r), 0, _a, _b); \
|
||||
if (_negative) \
|
||||
JSLL_NEG(r, r); \
|
||||
}
|
||||
|
||||
#define JSLL_MOD(r, a, b) { \
|
||||
JSInt64 _a, _b; \
|
||||
JSUint32 _negative = (JSInt32)(a).hi < 0; \
|
||||
if (_negative) { \
|
||||
JSLL_NEG(_a, a); \
|
||||
} else { \
|
||||
_a = a; \
|
||||
} \
|
||||
if ((JSInt32)(b).hi < 0) { \
|
||||
JSLL_NEG(_b, b); \
|
||||
} else { \
|
||||
_b = b; \
|
||||
} \
|
||||
JSLL_UDIVMOD(0, &(r), _a, _b); \
|
||||
if (_negative) \
|
||||
JSLL_NEG(r, r); \
|
||||
}
|
||||
|
||||
#define JSLL_SHL(r, a, b) { \
|
||||
if (b) { \
|
||||
JSInt64 _a; \
|
||||
_a = a; \
|
||||
if ((b) < 32) { \
|
||||
(r).lo = _a.lo << ((b) & 31); \
|
||||
(r).hi = (_a.hi << ((b) & 31)) | (_a.lo >> (32 - (b))); \
|
||||
} else { \
|
||||
(r).lo = 0; \
|
||||
(r).hi = _a.lo << ((b) & 31); \
|
||||
} \
|
||||
} else { \
|
||||
(r) = (a); \
|
||||
} \
|
||||
}
|
||||
|
||||
/* a is an JSInt32, b is JSInt32, r is JSInt64 */
|
||||
#define JSLL_ISHL(r, a, b) { \
|
||||
if (b) { \
|
||||
JSInt64 _a; \
|
||||
_a.lo = (a); \
|
||||
_a.hi = 0; \
|
||||
if ((b) < 32) { \
|
||||
(r).lo = (a) << ((b) & 31); \
|
||||
(r).hi = ((a) >> (32 - (b))); \
|
||||
} else { \
|
||||
(r).lo = 0; \
|
||||
(r).hi = (a) << ((b) & 31); \
|
||||
} \
|
||||
} else { \
|
||||
(r).lo = (a); \
|
||||
(r).hi = 0; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define JSLL_SHR(r, a, b) { \
|
||||
if (b) { \
|
||||
JSInt64 _a; \
|
||||
_a = a; \
|
||||
if ((b) < 32) { \
|
||||
(r).lo = (_a.hi << (32 - (b))) | (_a.lo >> ((b) & 31)); \
|
||||
(r).hi = (JSInt32)_a.hi >> ((b) & 31); \
|
||||
} else { \
|
||||
(r).lo = (JSInt32)_a.hi >> ((b) & 31); \
|
||||
(r).hi = (JSInt32)_a.hi >> 31; \
|
||||
} \
|
||||
} else { \
|
||||
(r) = (a); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define JSLL_USHR(r, a, b) { \
|
||||
if (b) { \
|
||||
JSInt64 _a; \
|
||||
_a = a; \
|
||||
if ((b) < 32) { \
|
||||
(r).lo = (_a.hi << (32 - (b))) | (_a.lo >> ((b) & 31)); \
|
||||
(r).hi = _a.hi >> ((b) & 31); \
|
||||
} else { \
|
||||
(r).lo = _a.hi >> ((b) & 31); \
|
||||
(r).hi = 0; \
|
||||
} \
|
||||
} else { \
|
||||
(r) = (a); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define JSLL_L2I(i, l) ((i) = (l).lo)
|
||||
#define JSLL_L2UI(ui, l) ((ui) = (l).lo)
|
||||
#define JSLL_L2F(f, l) { double _d; JSLL_L2D(_d, l); (f) = (JSFloat64)_d; }
|
||||
|
||||
#define JSLL_L2D(d, l) { \
|
||||
int _negative; \
|
||||
JSInt64 _absval; \
|
||||
\
|
||||
_negative = (l).hi >> 31; \
|
||||
if (_negative) { \
|
||||
JSLL_NEG(_absval, l); \
|
||||
} else { \
|
||||
_absval = l; \
|
||||
} \
|
||||
(d) = (double)_absval.hi * 4.294967296e9 + _absval.lo; \
|
||||
if (_negative) \
|
||||
(d) = -(d); \
|
||||
}
|
||||
|
||||
#define JSLL_I2L(l, i) { JSInt32 _i = (i) >> 31; (l).lo = (i); (l).hi = _i; }
|
||||
#define JSLL_UI2L(l, ui) ((l).lo = (ui), (l).hi = 0)
|
||||
#define JSLL_F2L(l, f) { double _d = (double)f; JSLL_D2L(l, _d); }
|
||||
|
||||
#define JSLL_D2L(l, d) { \
|
||||
int _negative; \
|
||||
double _absval, _d_hi; \
|
||||
JSInt64 _lo_d; \
|
||||
\
|
||||
_negative = ((d) < 0); \
|
||||
_absval = _negative ? -(d) : (d); \
|
||||
\
|
||||
(l).hi = _absval / 4.294967296e9; \
|
||||
(l).lo = 0; \
|
||||
JSLL_L2D(_d_hi, l); \
|
||||
_absval -= _d_hi; \
|
||||
_lo_d.hi = 0; \
|
||||
if (_absval < 0) { \
|
||||
_lo_d.lo = -_absval; \
|
||||
JSLL_SUB(l, l, _lo_d); \
|
||||
} else { \
|
||||
_lo_d.lo = _absval; \
|
||||
JSLL_ADD(l, l, _lo_d); \
|
||||
} \
|
||||
\
|
||||
if (_negative) \
|
||||
JSLL_NEG(l, l); \
|
||||
}
|
||||
|
||||
#endif /* !JS_HAVE_LONG_LONG */
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jslong_h___ */
|
||||
427
mozilla/js/src/jsmath.c
Normal file
427
mozilla/js/src/jsmath.c
Normal file
@@ -0,0 +1,427 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* JS math package.
|
||||
*/
|
||||
#include "jsstddef.h"
|
||||
#include "jslibmath.h"
|
||||
#include <stdlib.h>
|
||||
#include "jstypes.h"
|
||||
#include "jslong.h"
|
||||
#include "prmjtime.h"
|
||||
#include "jsapi.h"
|
||||
#include "jsatom.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsconfig.h"
|
||||
#include "jslock.h"
|
||||
#include "jsmath.h"
|
||||
#include "jsnum.h"
|
||||
#include "jsobj.h"
|
||||
|
||||
#ifndef M_E
|
||||
#define M_E 2.7182818284590452354
|
||||
#endif
|
||||
#ifndef M_LOG2E
|
||||
#define M_LOG2E 1.4426950408889634074
|
||||
#endif
|
||||
#ifndef M_LOG10E
|
||||
#define M_LOG10E 0.43429448190325182765
|
||||
#endif
|
||||
#ifndef M_LN2
|
||||
#define M_LN2 0.69314718055994530942
|
||||
#endif
|
||||
#ifndef M_LN10
|
||||
#define M_LN10 2.30258509299404568402
|
||||
#endif
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
#ifndef M_SQRT2
|
||||
#define M_SQRT2 1.41421356237309504880
|
||||
#endif
|
||||
#ifndef M_SQRT1_2
|
||||
#define M_SQRT1_2 0.70710678118654752440
|
||||
#endif
|
||||
|
||||
static JSConstDoubleSpec math_constants[] = {
|
||||
{M_E, "E"},
|
||||
{M_LOG2E, "LOG2E"},
|
||||
{M_LOG10E, "LOG10E"},
|
||||
{M_LN2, "LN2"},
|
||||
{M_LN10, "LN10"},
|
||||
{M_PI, "PI"},
|
||||
{M_SQRT2, "SQRT2"},
|
||||
{M_SQRT1_2, "SQRT1_2"},
|
||||
{0}
|
||||
};
|
||||
|
||||
static JSClass math_class = {
|
||||
"Math",
|
||||
0,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
|
||||
};
|
||||
|
||||
static JSBool
|
||||
math_abs(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
jsdouble x, z;
|
||||
|
||||
if (!js_ValueToNumber(cx, argv[0], &x))
|
||||
return JS_FALSE;
|
||||
z = fd_fabs(x);
|
||||
return js_NewNumberValue(cx, z, rval);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
math_acos(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
jsdouble x, z;
|
||||
|
||||
if (!js_ValueToNumber(cx, argv[0], &x))
|
||||
return JS_FALSE;
|
||||
z = fd_acos(x);
|
||||
return js_NewNumberValue(cx, z, rval);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
math_asin(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
jsdouble x, z;
|
||||
|
||||
if (!js_ValueToNumber(cx, argv[0], &x))
|
||||
return JS_FALSE;
|
||||
z = fd_asin(x);
|
||||
return js_NewNumberValue(cx, z, rval);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
math_atan(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
jsdouble x, z;
|
||||
|
||||
if (!js_ValueToNumber(cx, argv[0], &x))
|
||||
return JS_FALSE;
|
||||
z = fd_atan(x);
|
||||
return js_NewNumberValue(cx, z, rval);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
math_atan2(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
jsdouble x, y, z;
|
||||
|
||||
if (!js_ValueToNumber(cx, argv[0], &x))
|
||||
return JS_FALSE;
|
||||
if (!js_ValueToNumber(cx, argv[1], &y))
|
||||
return JS_FALSE;
|
||||
z = fd_atan2(x, y);
|
||||
return js_NewNumberValue(cx, z, rval);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
math_ceil(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
jsdouble x, z;
|
||||
|
||||
if (!js_ValueToNumber(cx, argv[0], &x))
|
||||
return JS_FALSE;
|
||||
z = fd_ceil(x);
|
||||
return js_NewNumberValue(cx, z, rval);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
math_cos(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
jsdouble x, z;
|
||||
|
||||
if (!js_ValueToNumber(cx, argv[0], &x))
|
||||
return JS_FALSE;
|
||||
z = fd_cos(x);
|
||||
return js_NewNumberValue(cx, z, rval);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
math_exp(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
jsdouble x, z;
|
||||
|
||||
if (!js_ValueToNumber(cx, argv[0], &x))
|
||||
return JS_FALSE;
|
||||
z = fd_exp(x);
|
||||
return js_NewNumberValue(cx, z, rval);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
math_floor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
jsdouble x, z;
|
||||
|
||||
if (!js_ValueToNumber(cx, argv[0], &x))
|
||||
return JS_FALSE;
|
||||
z = fd_floor(x);
|
||||
return js_NewNumberValue(cx, z, rval);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
math_log(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
jsdouble x, z;
|
||||
|
||||
if (!js_ValueToNumber(cx, argv[0], &x))
|
||||
return JS_FALSE;
|
||||
z = fd_log(x);
|
||||
return js_NewNumberValue(cx, z, rval);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
math_max(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
jsdouble x, y, z;
|
||||
|
||||
if (!js_ValueToNumber(cx, argv[0], &x))
|
||||
return JS_FALSE;
|
||||
if (!js_ValueToNumber(cx, argv[1], &y))
|
||||
return JS_FALSE;
|
||||
if (JSDOUBLE_IS_NaN(y)||JSDOUBLE_IS_NaN(x))
|
||||
{
|
||||
*rval = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
|
||||
return JS_TRUE;
|
||||
}
|
||||
if ((x==0)&&(x==y)&&(fd_copysign(1,y)==-1))
|
||||
z = x;
|
||||
else
|
||||
z = (x > y) ? x : y;
|
||||
return js_NewNumberValue(cx, z, rval);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
math_min(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
jsdouble x, y, z;
|
||||
|
||||
if (!js_ValueToNumber(cx, argv[0], &x))
|
||||
return JS_FALSE;
|
||||
if (!js_ValueToNumber(cx, argv[1], &y))
|
||||
return JS_FALSE;
|
||||
if (JSDOUBLE_IS_NaN(y)||JSDOUBLE_IS_NaN(x))
|
||||
{
|
||||
*rval = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
|
||||
return JS_TRUE;
|
||||
}
|
||||
if ((x==0)&&(x==y)&&(fd_copysign(1,y)==-1))
|
||||
z = y;
|
||||
else
|
||||
z = (x < y) ? x : y;
|
||||
return js_NewNumberValue(cx, z, rval);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
math_pow(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
jsdouble x, y, z;
|
||||
|
||||
if (!js_ValueToNumber(cx, argv[0], &x))
|
||||
return JS_FALSE;
|
||||
if (!js_ValueToNumber(cx, argv[1], &y))
|
||||
return JS_FALSE;
|
||||
z = fd_pow(x, y);
|
||||
return js_NewNumberValue(cx, z, rval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Math.random() support, lifted from java.util.Random.java.
|
||||
*/
|
||||
static void
|
||||
random_setSeed(JSRuntime *rt, int64 seed)
|
||||
{
|
||||
int64 tmp;
|
||||
|
||||
JSLL_I2L(tmp, 1000);
|
||||
JSLL_DIV(seed, seed, tmp);
|
||||
JSLL_XOR(tmp, seed, rt->rngMultiplier);
|
||||
JSLL_AND(rt->rngSeed, tmp, rt->rngMask);
|
||||
}
|
||||
|
||||
static void
|
||||
random_init(JSRuntime *rt)
|
||||
{
|
||||
int64 tmp, tmp2;
|
||||
|
||||
/* Do at most once. */
|
||||
if (rt->rngInitialized)
|
||||
return;
|
||||
rt->rngInitialized = JS_TRUE;
|
||||
|
||||
/* rt->rngMultiplier = 0x5DEECE66DL */
|
||||
JSLL_ISHL(tmp, 0x5D, 32);
|
||||
JSLL_UI2L(tmp2, 0xEECE66DL);
|
||||
JSLL_OR(rt->rngMultiplier, tmp, tmp2);
|
||||
|
||||
/* rt->rngAddend = 0xBL */
|
||||
JSLL_I2L(rt->rngAddend, 0xBL);
|
||||
|
||||
/* rt->rngMask = (1L << 48) - 1 */
|
||||
JSLL_I2L(tmp, 1);
|
||||
JSLL_SHL(tmp2, tmp, 48);
|
||||
JSLL_SUB(rt->rngMask, tmp2, tmp);
|
||||
|
||||
/* rt->rngDscale = (jsdouble)(1L << 54) */
|
||||
JSLL_SHL(tmp2, tmp, 54);
|
||||
JSLL_L2D(rt->rngDscale, tmp2);
|
||||
|
||||
/* Finally, set the seed from current time. */
|
||||
random_setSeed(rt, PRMJ_Now());
|
||||
}
|
||||
|
||||
static uint32
|
||||
random_next(JSRuntime *rt, int bits)
|
||||
{
|
||||
int64 nextseed, tmp;
|
||||
uint32 retval;
|
||||
|
||||
JSLL_MUL(nextseed, rt->rngSeed, rt->rngMultiplier);
|
||||
JSLL_ADD(nextseed, nextseed, rt->rngAddend);
|
||||
JSLL_AND(nextseed, nextseed, rt->rngMask);
|
||||
rt->rngSeed = nextseed;
|
||||
JSLL_USHR(tmp, nextseed, 48 - bits);
|
||||
JSLL_L2I(retval, tmp);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static jsdouble
|
||||
random_nextDouble(JSRuntime *rt)
|
||||
{
|
||||
int64 tmp, tmp2;
|
||||
jsdouble d;
|
||||
|
||||
JSLL_ISHL(tmp, random_next(rt, 27), 27);
|
||||
JSLL_UI2L(tmp2, random_next(rt, 27));
|
||||
JSLL_ADD(tmp, tmp, tmp2);
|
||||
JSLL_L2D(d, tmp);
|
||||
return d / rt->rngDscale;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
math_random(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
jsdouble z;
|
||||
|
||||
rt = cx->runtime;
|
||||
JS_LOCK_RUNTIME(rt);
|
||||
random_init(rt);
|
||||
z = random_nextDouble(rt);
|
||||
JS_UNLOCK_RUNTIME(rt);
|
||||
return js_NewNumberValue(cx, z, rval);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
math_round(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
jsdouble x, z;
|
||||
|
||||
if (!js_ValueToNumber(cx, argv[0], &x))
|
||||
return JS_FALSE;
|
||||
z = fd_copysign(fd_floor(x + 0.5), x);
|
||||
return js_NewNumberValue(cx, z, rval);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
math_sin(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
jsdouble x, z;
|
||||
|
||||
if (!js_ValueToNumber(cx, argv[0], &x))
|
||||
return JS_FALSE;
|
||||
z = fd_sin(x);
|
||||
return js_NewNumberValue(cx, z, rval);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
math_sqrt(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
jsdouble x, z;
|
||||
|
||||
if (!js_ValueToNumber(cx, argv[0], &x))
|
||||
return JS_FALSE;
|
||||
z = fd_sqrt(x);
|
||||
return js_NewNumberValue(cx, z, rval);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
math_tan(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
jsdouble x, z;
|
||||
|
||||
if (!js_ValueToNumber(cx, argv[0], &x))
|
||||
return JS_FALSE;
|
||||
z = fd_tan(x);
|
||||
return js_NewNumberValue(cx, z, rval);
|
||||
}
|
||||
|
||||
#if JS_HAS_TOSOURCE
|
||||
static JSBool
|
||||
math_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
{
|
||||
*rval = ATOM_KEY(cx->runtime->atomState.MathAtom);
|
||||
return JS_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static JSFunctionSpec math_static_methods[] = {
|
||||
#ifdef JS_HAS_TOSOURCE
|
||||
{js_toSource_str, math_toSource, 0},
|
||||
#endif
|
||||
{"abs", math_abs, 1},
|
||||
{"acos", math_acos, 1},
|
||||
{"asin", math_asin, 1},
|
||||
{"atan", math_atan, 1},
|
||||
{"atan2", math_atan2, 2},
|
||||
{"ceil", math_ceil, 1},
|
||||
{"cos", math_cos, 1},
|
||||
{"exp", math_exp, 1},
|
||||
{"floor", math_floor, 1},
|
||||
{"log", math_log, 1},
|
||||
{"max", math_max, 2},
|
||||
{"min", math_min, 2},
|
||||
{"pow", math_pow, 2},
|
||||
{"random", math_random, 0},
|
||||
{"round", math_round, 1},
|
||||
{"sin", math_sin, 1},
|
||||
{"sqrt", math_sqrt, 1},
|
||||
{"tan", math_tan, 1},
|
||||
{0}
|
||||
};
|
||||
|
||||
JSObject *
|
||||
js_InitMathClass(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JSObject *Math;
|
||||
|
||||
Math = JS_DefineObject(cx, obj, "Math", &math_class, NULL, 0);
|
||||
if (!Math)
|
||||
return NULL;
|
||||
if (!JS_DefineFunctions(cx, Math, math_static_methods))
|
||||
return NULL;
|
||||
if (!JS_DefineConstDoubles(cx, Math, math_constants))
|
||||
return NULL;
|
||||
return Math;
|
||||
}
|
||||
18
mozilla/js/src/jsmath.h
Normal file
18
mozilla/js/src/jsmath.h
Normal file
@@ -0,0 +1,18 @@
|
||||
/* -*- Mode: C; tab-width: 8 -*-
|
||||
* Copyright (C) 1998 Netscape Communications Corporation, All Rights Reserved.
|
||||
*/
|
||||
|
||||
#ifndef jsmath_h___
|
||||
#define jsmath_h___
|
||||
/*
|
||||
* JS math functions.
|
||||
*/
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
extern JSObject *
|
||||
js_InitMathClass(JSContext *cx, JSObject *obj);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsmath_h___ */
|
||||
840
mozilla/js/src/jsnum.c
Normal file
840
mozilla/js/src/jsnum.c
Normal file
@@ -0,0 +1,840 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* JS number type and wrapper class.
|
||||
*/
|
||||
#include "jsstddef.h"
|
||||
#include <errno.h>
|
||||
#ifdef XP_PC
|
||||
#include <float.h>
|
||||
#endif
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "jstypes.h"
|
||||
#include "jsutil.h" /* Added by JSIFY */
|
||||
#include "jsdtoa.h"
|
||||
#include "jsprf.h"
|
||||
#include "jsapi.h"
|
||||
#include "jsatom.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsconfig.h"
|
||||
#include "jsgc.h"
|
||||
#include "jsinterp.h"
|
||||
#include "jsnum.h"
|
||||
#include "jsobj.h"
|
||||
#include "jsopcode.h"
|
||||
#include "jsstr.h"
|
||||
|
||||
union dpun {
|
||||
struct {
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
uint32 lo, hi;
|
||||
#else
|
||||
uint32 hi, lo;
|
||||
#endif
|
||||
} s;
|
||||
jsdouble d;
|
||||
};
|
||||
|
||||
static JSBool
|
||||
num_isNaN(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
jsdouble x;
|
||||
|
||||
if (!js_ValueToNumber(cx, argv[0], &x))
|
||||
return JS_FALSE;
|
||||
*rval = BOOLEAN_TO_JSVAL(JSDOUBLE_IS_NaN(x));
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
num_isFinite(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
jsdouble x;
|
||||
|
||||
if (!js_ValueToNumber(cx, argv[0], &x))
|
||||
return JS_FALSE;
|
||||
*rval = BOOLEAN_TO_JSVAL(JSDOUBLE_IS_FINITE(x));
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
num_parseFloat(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
JSString *str;
|
||||
jsdouble d;
|
||||
const jschar *ep;
|
||||
|
||||
str = js_ValueToString(cx, argv[0]);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
if (!js_strtod(cx, str->chars, &ep, &d))
|
||||
return JS_FALSE;
|
||||
if (ep == str->chars) {
|
||||
*rval = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
|
||||
return JS_TRUE;
|
||||
}
|
||||
return js_NewNumberValue(cx, d, rval);
|
||||
}
|
||||
|
||||
/* See ECMA 15.1.2.2. */
|
||||
static JSBool
|
||||
num_parseInt(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
JSString *str;
|
||||
jsint radix;
|
||||
jsdouble d;
|
||||
const jschar *ep;
|
||||
|
||||
str = js_ValueToString(cx, argv[0]);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
|
||||
if (argc > 1) {
|
||||
if (!js_ValueToECMAInt32(cx, argv[1], &radix))
|
||||
return JS_FALSE;
|
||||
} else
|
||||
radix = 0;
|
||||
|
||||
if (radix != 0 && (radix < 2 || radix > 36)) {
|
||||
*rval = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
|
||||
return JS_TRUE;
|
||||
}
|
||||
if (!js_strtointeger(cx, str->chars, &ep, radix, &d))
|
||||
return JS_FALSE;
|
||||
if (ep == str->chars) {
|
||||
*rval = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
|
||||
return JS_TRUE;
|
||||
}
|
||||
return js_NewNumberValue(cx, d, rval);
|
||||
}
|
||||
|
||||
|
||||
static JSFunctionSpec number_functions[] = {
|
||||
{"isNaN", num_isNaN, 1},
|
||||
{"isFinite", num_isFinite, 1},
|
||||
{"parseFloat", num_parseFloat, 1},
|
||||
{"parseInt", num_parseInt, 2},
|
||||
{0}
|
||||
};
|
||||
|
||||
static JSClass number_class = {
|
||||
"Number",
|
||||
JSCLASS_HAS_PRIVATE,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
|
||||
};
|
||||
|
||||
static JSBool
|
||||
Number(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
jsdouble d;
|
||||
jsval v;
|
||||
|
||||
if (argc != 0) {
|
||||
if (!js_ValueToNumber(cx, argv[0], &d))
|
||||
return JS_FALSE;
|
||||
} else {
|
||||
d = 0.0;
|
||||
}
|
||||
if (!js_NewNumberValue(cx, d, &v))
|
||||
return JS_FALSE;
|
||||
if (!cx->fp->constructing) {
|
||||
*rval = v;
|
||||
return JS_TRUE;
|
||||
}
|
||||
OBJ_SET_SLOT(cx, obj, JSSLOT_PRIVATE, v);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
#if JS_HAS_TOSOURCE
|
||||
static JSBool
|
||||
num_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
jsval v;
|
||||
jsdouble d;
|
||||
size_t i;
|
||||
char buf[64];
|
||||
JSString *str;
|
||||
|
||||
if (!JS_InstanceOf(cx, obj, &number_class, argv))
|
||||
return JS_FALSE;
|
||||
v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
|
||||
if (!JSVAL_IS_NUMBER(v))
|
||||
return js_obj_toSource(cx, obj, argc, argv, rval);
|
||||
d = JSVAL_IS_INT(v) ? (jsdouble)JSVAL_TO_INT(v) : *JSVAL_TO_DOUBLE(v);
|
||||
i = JS_snprintf(buf, sizeof buf, "(new %s(", number_class.name);
|
||||
|
||||
JS_cnvtf(buf + i, sizeof buf - i, 20, d);
|
||||
i = strlen(buf);
|
||||
JS_snprintf(buf + i, sizeof buf - i, "))");
|
||||
str = JS_NewStringCopyZ(cx, buf);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
*rval = STRING_TO_JSVAL(str);
|
||||
return JS_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static JSBool
|
||||
num_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
jsval v;
|
||||
jsdouble d;
|
||||
jsint base, ival, dval;
|
||||
char *bp, buf[32];
|
||||
JSString *str;
|
||||
|
||||
if (!JS_InstanceOf(cx, obj, &number_class, argv))
|
||||
return JS_FALSE;
|
||||
v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
|
||||
if (!JSVAL_IS_NUMBER(v))
|
||||
return js_obj_toString(cx, obj, argc, argv, rval);
|
||||
d = JSVAL_IS_INT(v) ? (jsdouble)JSVAL_TO_INT(v) : *JSVAL_TO_DOUBLE(v);
|
||||
if (argc != 0) {
|
||||
if (!js_ValueToECMAInt32(cx, argv[0], &base))
|
||||
return JS_FALSE;
|
||||
if (base < 2 || base > 36) {
|
||||
char numBuf[12];
|
||||
JS_snprintf(numBuf, sizeof numBuf, "%ld", (long) base);
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_RADIX,
|
||||
numBuf);
|
||||
return JS_FALSE;
|
||||
}
|
||||
if (base != 10 && JSDOUBLE_IS_FINITE(d)) {
|
||||
ival = (jsint) js_DoubleToInteger(d);
|
||||
bp = buf + sizeof buf;
|
||||
for (*--bp = '\0'; ival != 0 && --bp >= buf; ival /= base) {
|
||||
dval = ival % base;
|
||||
*bp = (char)((dval >= 10) ? 'a' - 10 + dval : '0' + dval);
|
||||
}
|
||||
if (*bp == '\0')
|
||||
*--bp = '0';
|
||||
str = JS_NewStringCopyZ(cx, bp);
|
||||
} else {
|
||||
str = js_NumberToString(cx, d);
|
||||
}
|
||||
} else {
|
||||
str = js_NumberToString(cx, d);
|
||||
}
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
*rval = STRING_TO_JSVAL(str);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
num_valueOf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
if (!JS_InstanceOf(cx, obj, &number_class, argv))
|
||||
return JS_FALSE;
|
||||
*rval = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSFunctionSpec number_methods[] = {
|
||||
#if JS_HAS_TOSOURCE
|
||||
{js_toSource_str, num_toSource, 0},
|
||||
#endif
|
||||
{js_toString_str, num_toString, 0},
|
||||
{js_valueOf_str, num_valueOf, 0},
|
||||
{0}
|
||||
};
|
||||
|
||||
/* NB: Keep this in synch with number_constants[]. */
|
||||
enum nc_slot {
|
||||
NC_NaN,
|
||||
NC_POSITIVE_INFINITY,
|
||||
NC_NEGATIVE_INFINITY,
|
||||
NC_MAX_VALUE,
|
||||
NC_MIN_VALUE,
|
||||
NC_LIMIT
|
||||
};
|
||||
|
||||
/*
|
||||
* Some to most C compilers forbid spelling these at compile time, or barf
|
||||
* if you try, so all but MAX_VALUE are set at runtime by js_InitNumberClass
|
||||
* using union dpun.
|
||||
*/
|
||||
static JSConstDoubleSpec number_constants[] = {
|
||||
{0, "NaN"},
|
||||
{0, "POSITIVE_INFINITY"},
|
||||
{0, "NEGATIVE_INFINITY"},
|
||||
{1.7976931348623157E+308, "MAX_VALUE"},
|
||||
{0, "MIN_VALUE"},
|
||||
{0}
|
||||
};
|
||||
|
||||
static jsdouble NaN;
|
||||
|
||||
JSObject *
|
||||
js_InitNumberClass(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
union dpun u;
|
||||
JSObject *proto, *ctor;
|
||||
|
||||
rt = cx->runtime;
|
||||
if (!rt->jsNaN) {
|
||||
#ifdef XP_PC
|
||||
#ifdef XP_OS2
|
||||
/*DSR071597 - I have no idea what this really does other than mucking with the floating */
|
||||
/*point unit, but it does fix a "floating point underflow" exception I am getting, and there*/
|
||||
/*is similar code in the Hursley java. Making sure we have the same code in Javascript */
|
||||
/*where Netscape was calling control87 on Windows... */
|
||||
_control87(MCW_EM+PC_53+RC_NEAR,MCW_EM+MCW_PC+MCW_RC);
|
||||
#else
|
||||
_control87(MCW_EM, MCW_EM);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
u.s.hi = JSDOUBLE_HI32_EXPMASK | JSDOUBLE_HI32_MANTMASK;
|
||||
u.s.lo = 0xffffffff;
|
||||
number_constants[NC_NaN].dval = NaN = u.d;
|
||||
rt->jsNaN = js_NewDouble(cx, NaN);
|
||||
if (!rt->jsNaN || !js_LockGCThing(cx, rt->jsNaN))
|
||||
return NULL;
|
||||
|
||||
u.s.hi = JSDOUBLE_HI32_EXPMASK;
|
||||
u.s.lo = 0x00000000;
|
||||
number_constants[NC_POSITIVE_INFINITY].dval = u.d;
|
||||
rt->jsPositiveInfinity = js_NewDouble(cx, u.d);
|
||||
if (!rt->jsPositiveInfinity ||
|
||||
!js_LockGCThing(cx, rt->jsPositiveInfinity)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
u.s.hi = JSDOUBLE_HI32_SIGNBIT | JSDOUBLE_HI32_EXPMASK;
|
||||
u.s.lo = 0x00000000;
|
||||
number_constants[NC_NEGATIVE_INFINITY].dval = u.d;
|
||||
rt->jsNegativeInfinity = js_NewDouble(cx, u.d);
|
||||
if (!rt->jsNegativeInfinity ||
|
||||
!js_LockGCThing(cx, rt->jsNegativeInfinity)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
u.s.hi = 0;
|
||||
u.s.lo = 1;
|
||||
number_constants[NC_MIN_VALUE].dval = u.d;
|
||||
}
|
||||
|
||||
if (!JS_DefineFunctions(cx, obj, number_functions))
|
||||
return NULL;
|
||||
|
||||
proto = JS_InitClass(cx, obj, NULL, &number_class, Number, 1,
|
||||
NULL, number_methods, NULL, NULL);
|
||||
if (!proto || !(ctor = JS_GetConstructor(cx, proto)))
|
||||
return NULL;
|
||||
OBJ_SET_SLOT(cx, proto, JSSLOT_PRIVATE, JSVAL_ZERO);
|
||||
if (!JS_DefineConstDoubles(cx, ctor, number_constants))
|
||||
return NULL;
|
||||
|
||||
/* ECMA 15.1.1.1 */
|
||||
if (!JS_DefineProperty(cx, obj, "NaN", DOUBLE_TO_JSVAL(rt->jsNaN),
|
||||
NULL, NULL, 0)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ECMA 15.1.1.2 */
|
||||
if (!JS_DefineProperty(cx, obj, "Infinity",
|
||||
DOUBLE_TO_JSVAL(rt->jsPositiveInfinity),
|
||||
NULL, NULL, 0)) {
|
||||
return NULL;
|
||||
}
|
||||
return proto;
|
||||
}
|
||||
|
||||
jsdouble *
|
||||
js_NewDouble(JSContext *cx, jsdouble d)
|
||||
{
|
||||
jsdouble *dp;
|
||||
|
||||
dp = js_AllocGCThing(cx, GCX_DOUBLE);
|
||||
if (!dp)
|
||||
return NULL;
|
||||
*dp = d;
|
||||
return dp;
|
||||
}
|
||||
|
||||
void
|
||||
js_FinalizeDouble(JSContext *cx, jsdouble *dp)
|
||||
{
|
||||
*dp = NaN;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_NewDoubleValue(JSContext *cx, jsdouble d, jsval *rval)
|
||||
{
|
||||
jsdouble *dp;
|
||||
|
||||
dp = js_NewDouble(cx, d);
|
||||
if (!dp)
|
||||
return JS_FALSE;
|
||||
*rval = DOUBLE_TO_JSVAL(dp);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_NewNumberValue(JSContext *cx, jsdouble d, jsval *rval)
|
||||
{
|
||||
jsint i;
|
||||
|
||||
if (JSDOUBLE_IS_INT(d, i) && INT_FITS_IN_JSVAL(i)) {
|
||||
*rval = INT_TO_JSVAL(i);
|
||||
} else {
|
||||
if (!js_NewDoubleValue(cx, d, rval))
|
||||
return JS_FALSE;
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSObject *
|
||||
js_NumberToObject(JSContext *cx, jsdouble d)
|
||||
{
|
||||
JSObject *obj;
|
||||
jsval v;
|
||||
|
||||
obj = js_NewObject(cx, &number_class, NULL, NULL);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
if (!js_NewNumberValue(cx, d, &v)) {
|
||||
cx->newborn[GCX_OBJECT] = NULL;
|
||||
return NULL;
|
||||
}
|
||||
OBJ_SET_SLOT(cx, obj, JSSLOT_PRIVATE, v);
|
||||
return obj;
|
||||
}
|
||||
|
||||
/* XXXbe rewrite me to be ECMA-based! */
|
||||
JSString *
|
||||
js_NumberToString(JSContext *cx, jsdouble d)
|
||||
{
|
||||
jsint i;
|
||||
char buf[32];
|
||||
|
||||
if (JSDOUBLE_IS_INT(d, i)) {
|
||||
JS_snprintf(buf, sizeof buf, "%ld", (long)i);
|
||||
} else {
|
||||
JS_cnvtf(buf, sizeof buf, 20, d);
|
||||
}
|
||||
return JS_NewStringCopyZ(cx, buf);
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_ValueToNumber(JSContext *cx, jsval v, jsdouble *dp)
|
||||
{
|
||||
JSObject *obj;
|
||||
JSString *str;
|
||||
const jschar *ep;
|
||||
jsdouble d;
|
||||
|
||||
if (JSVAL_IS_OBJECT(v)) {
|
||||
obj = JSVAL_TO_OBJECT(v);
|
||||
if (!obj) {
|
||||
*dp = 0;
|
||||
return JS_TRUE;
|
||||
}
|
||||
if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_NUMBER, &v))
|
||||
return JS_FALSE;
|
||||
}
|
||||
if (JSVAL_IS_INT(v)) {
|
||||
*dp = (jsdouble)JSVAL_TO_INT(v);
|
||||
} else if (JSVAL_IS_DOUBLE(v)) {
|
||||
*dp = *JSVAL_TO_DOUBLE(v);
|
||||
} else if (JSVAL_IS_STRING(v)) {
|
||||
str = JSVAL_TO_STRING(v);
|
||||
errno = 0;
|
||||
/* Note that ECMAScript doesn't treat numbers beginning with a zero as octal numbers here.
|
||||
* This works because all such numbers will be interpreted as decimal by js_strtod and
|
||||
* will never get passed to js_strtointeger, which would interpret them as octal. */
|
||||
if ((!js_strtod(cx, str->chars, &ep, &d) || js_SkipWhiteSpace(ep) != str->chars + str->length) &&
|
||||
(!js_strtointeger(cx, str->chars, &ep, 0, &d) || js_SkipWhiteSpace(ep) != str->chars + str->length)) {
|
||||
goto badstr;
|
||||
}
|
||||
*dp = d;
|
||||
} else if (JSVAL_IS_BOOLEAN(v)) {
|
||||
*dp = JSVAL_TO_BOOLEAN(v) ? 1 : 0;
|
||||
} else {
|
||||
#if JS_BUG_FALLIBLE_TONUM
|
||||
str = js_DecompileValueGenerator(cx, v, NULL);
|
||||
badstr:
|
||||
if (str) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NAN,
|
||||
JS_GetStringBytes(str));
|
||||
|
||||
}
|
||||
return JS_FALSE;
|
||||
#else
|
||||
badstr:
|
||||
*dp = *cx->runtime->jsNaN;
|
||||
#endif
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_ValueToECMAInt32(JSContext *cx, jsval v, int32 *ip)
|
||||
{
|
||||
jsdouble d;
|
||||
|
||||
if (!js_ValueToNumber(cx, v, &d))
|
||||
return JS_FALSE;
|
||||
return js_DoubleToECMAInt32(cx, d, ip);
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_DoubleToECMAInt32(JSContext *cx, jsdouble d, int32 *ip)
|
||||
{
|
||||
jsdouble two32 = 4294967296.0;
|
||||
jsdouble two31 = 2147483648.0;
|
||||
|
||||
if (!JSDOUBLE_IS_FINITE(d) || d == 0) {
|
||||
*ip = 0;
|
||||
return JS_TRUE;
|
||||
}
|
||||
d = fmod(d, two32);
|
||||
d = d >= 0 ? d : d + two32;
|
||||
if (d >= two31)
|
||||
*ip = (int32)(d - two32);
|
||||
else
|
||||
*ip = (int32)d;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_ValueToECMAUint32(JSContext *cx, jsval v, uint32 *ip)
|
||||
{
|
||||
jsdouble d;
|
||||
|
||||
if (!js_ValueToNumber(cx, v, &d))
|
||||
return JS_FALSE;
|
||||
return js_DoubleToECMAUint32(cx, d, ip);
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_DoubleToECMAUint32(JSContext *cx, jsdouble d, uint32 *ip)
|
||||
{
|
||||
JSBool neg;
|
||||
jsdouble two32 = 4294967296.0;
|
||||
|
||||
if (!JSDOUBLE_IS_FINITE(d) || d == 0) {
|
||||
*ip = 0;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
neg = (d < 0);
|
||||
d = floor(neg ? -d : d);
|
||||
d = neg ? -d : d;
|
||||
|
||||
d = fmod(d, two32);
|
||||
|
||||
d = d >= 0 ? d : d + two32;
|
||||
*ip = (uint32)d;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_ValueToInt32(JSContext *cx, jsval v, int32 *ip)
|
||||
{
|
||||
jsdouble d;
|
||||
JSString *str;
|
||||
|
||||
if (!js_ValueToNumber(cx, v, &d))
|
||||
return JS_FALSE;
|
||||
if (JSDOUBLE_IS_NaN(d) || d <= -2147483649.0 || 2147483648.0 <= d) {
|
||||
str = js_DecompileValueGenerator(cx, v, NULL);
|
||||
if (str) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_CANT_CONVERT, JS_GetStringBytes(str));
|
||||
|
||||
}
|
||||
return JS_FALSE;
|
||||
}
|
||||
*ip = (int32)floor(d + 0.5); /* Round to nearest */
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_ValueToUint16(JSContext *cx, jsval v, uint16 *ip)
|
||||
{
|
||||
jsdouble d;
|
||||
jsuint i, m;
|
||||
JSBool neg;
|
||||
|
||||
if (!js_ValueToNumber(cx, v, &d))
|
||||
return JS_FALSE;
|
||||
if (d == 0 || !JSDOUBLE_IS_FINITE(d)) {
|
||||
*ip = 0;
|
||||
return JS_TRUE;
|
||||
}
|
||||
i = (jsuint)d;
|
||||
if ((jsdouble)i == d) {
|
||||
*ip = (uint16)i;
|
||||
return JS_TRUE;
|
||||
}
|
||||
neg = (d < 0);
|
||||
d = floor(neg ? -d : d);
|
||||
d = neg ? -d : d;
|
||||
m = JS_BIT(16);
|
||||
d = fmod(d, m);
|
||||
if (d < 0)
|
||||
d += m;
|
||||
*ip = (uint16) d;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
jsdouble
|
||||
js_DoubleToInteger(jsdouble d)
|
||||
{
|
||||
JSBool neg;
|
||||
|
||||
if (d == 0)
|
||||
return d;
|
||||
if (!JSDOUBLE_IS_FINITE(d)) {
|
||||
if (JSDOUBLE_IS_NaN(d))
|
||||
return 0;
|
||||
return d;
|
||||
}
|
||||
neg = (d < 0);
|
||||
d = floor(neg ? -d : d);
|
||||
return neg ? -d : d;
|
||||
}
|
||||
|
||||
|
||||
JSBool
|
||||
js_strtod(JSContext *cx, const jschar *s, const jschar **ep, jsdouble *dp)
|
||||
{
|
||||
size_t i;
|
||||
char *cstr, *istr, *estr;
|
||||
JSBool negative;
|
||||
jsdouble d;
|
||||
const jschar *s1 = js_SkipWhiteSpace(s);
|
||||
size_t length = js_strlen(s1);
|
||||
|
||||
cstr = malloc(length + 1);
|
||||
if (!cstr)
|
||||
return JS_FALSE;
|
||||
for (i = 0; i <= length; i++) {
|
||||
if (s1[i] >> 8) {
|
||||
cstr[i] = 0;
|
||||
break;
|
||||
}
|
||||
cstr[i] = (char)s1[i];
|
||||
}
|
||||
|
||||
istr = cstr;
|
||||
if ((negative = (*istr == '-')) != 0 || *istr == '+')
|
||||
istr++;
|
||||
if (!strncmp(istr, "Infinity", 8)) {
|
||||
d = *(negative ? cx->runtime->jsNegativeInfinity : cx->runtime->jsPositiveInfinity);
|
||||
estr = istr + 8;
|
||||
} else {
|
||||
errno = 0;
|
||||
d = JS_strtod(cstr, &estr);
|
||||
if (errno == ERANGE)
|
||||
if (d == HUGE_VAL)
|
||||
d = *cx->runtime->jsPositiveInfinity;
|
||||
else if (d == -HUGE_VAL)
|
||||
d = *cx->runtime->jsNegativeInfinity;
|
||||
#ifdef HPUX
|
||||
if (d == 0.0 && negative) {
|
||||
/*
|
||||
* "-0", "-1e-2000" come out as positive zero
|
||||
* here on HPUX. Force a negative zero instead.
|
||||
*/
|
||||
JSDOUBLE_HI32(d) = JSDOUBLE_HI32_SIGNBIT;
|
||||
JSDOUBLE_LO32(d) = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
free(cstr);
|
||||
i = estr - cstr;
|
||||
*ep = i ? s1 + i : s;
|
||||
*dp = d;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
struct BinaryDigitReader
|
||||
{
|
||||
uintN base; /* Base of number; must be a power of 2 */
|
||||
uintN digit; /* Current digit value in radix given by base */
|
||||
uintN digitMask; /* Mask to extract the next bit from digit */
|
||||
const jschar *digits; /* Pointer to the remaining digits */
|
||||
const jschar *end; /* Pointer to first non-digit */
|
||||
};
|
||||
|
||||
/* Return the next binary digit from the number or -1 if done */
|
||||
static intN GetNextBinaryDigit(struct BinaryDigitReader *bdr)
|
||||
{
|
||||
intN bit;
|
||||
|
||||
if (bdr->digitMask == 0) {
|
||||
uintN c;
|
||||
|
||||
if (bdr->digits == bdr->end)
|
||||
return -1;
|
||||
|
||||
c = *bdr->digits++;
|
||||
if ('0' <= c && c <= '9')
|
||||
bdr->digit = c - '0';
|
||||
else if ('a' <= c && c <= 'z')
|
||||
bdr->digit = c - 'a' + 10;
|
||||
else bdr->digit = c - 'A' + 10;
|
||||
bdr->digitMask = bdr->base >> 1;
|
||||
}
|
||||
bit = (bdr->digit & bdr->digitMask) != 0;
|
||||
bdr->digitMask >>= 1;
|
||||
return bit;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_strtointeger(JSContext *cx, const jschar *s, const jschar **ep, jsint base, jsdouble *dp)
|
||||
{
|
||||
JSBool negative;
|
||||
jsdouble value;
|
||||
const jschar *start;
|
||||
const jschar *s1 = js_SkipWhiteSpace(s);
|
||||
|
||||
if ((negative = (*s1 == '-')) != 0 || *s1 == '+')
|
||||
s1++;
|
||||
|
||||
if (base == 0)
|
||||
/* No base supplied, or some base that evaluated to 0. */
|
||||
if (*s1 == '0')
|
||||
/* It's either hex or octal; only increment char if str isn't '0' */
|
||||
if (s1[1] == 'X' || s1[1] == 'x') { /* Hex */
|
||||
s1 += 2;
|
||||
base = 16;
|
||||
} else /* Octal */
|
||||
base = 8;
|
||||
else
|
||||
base = 10; /* Default to decimal. */
|
||||
else if (base == 16 && *s1 == '0' && (s1[1] == 'X' || s1[1] == 'x'))
|
||||
/* If base is 16, ignore hex prefix. */
|
||||
s1 += 2;
|
||||
|
||||
/* Done with the preliminaries; find some prefix of the string that's
|
||||
* a number in the given base.
|
||||
*/
|
||||
start = s1; /* Mark - if string is empty, we return NaN. */
|
||||
value = 0.0;
|
||||
while (1) {
|
||||
uintN digit;
|
||||
jschar c = *s1;
|
||||
if ('0' <= c && c <= '9')
|
||||
digit = c - '0';
|
||||
else if ('a' <= c && c <= 'z')
|
||||
digit = c - 'a' + 10;
|
||||
else if ('A' <= c && c <= 'Z')
|
||||
digit = c - 'A' + 10;
|
||||
else
|
||||
break;
|
||||
if (digit >= (uintN)base)
|
||||
break;
|
||||
value = value*base + digit;
|
||||
s1++;
|
||||
}
|
||||
|
||||
if (value >= 9007199254740992.0)
|
||||
if (base == 10) {
|
||||
/* If we're accumulating a decimal number and the number is >= 2^53, then
|
||||
* the result from the repeated multiply-add above may be inaccurate. Call
|
||||
* JS_strtod to get the correct answer.
|
||||
*/
|
||||
size_t i;
|
||||
size_t length = s1 - start;
|
||||
char *cstr = malloc(length + 1);
|
||||
char *estr;
|
||||
|
||||
if (!cstr)
|
||||
return JS_FALSE;
|
||||
for (i = 0; i != length; i++)
|
||||
cstr[i] = (char)start[i];
|
||||
cstr[length] = 0;
|
||||
|
||||
errno = 0;
|
||||
value = JS_strtod(cstr, &estr);
|
||||
if (errno == ERANGE && value == HUGE_VAL)
|
||||
value = *cx->runtime->jsPositiveInfinity;
|
||||
free(cstr);
|
||||
|
||||
} else if (base == 2 || base == 4 || base == 8 || base == 16 || base == 32) {
|
||||
/* The number may also be inaccurate for one of these bases. This
|
||||
* happens if the addition in value*base + digit causes a round-down
|
||||
* to an even least significant mantissa bit when the first dropped bit
|
||||
* is a one. If any of the following digits in the number (which haven't
|
||||
* been added in yet) are nonzero then the correct action would have
|
||||
* been to round up instead of down. An example of this occurs when
|
||||
* reading the number 0x1000000000000081, which rounds to 0x1000000000000000
|
||||
* instead of 0x1000000000000100.
|
||||
*/
|
||||
struct BinaryDigitReader bdr;
|
||||
intN bit, bit2;
|
||||
intN j;
|
||||
|
||||
bdr.base = base;
|
||||
bdr.digitMask = 0;
|
||||
bdr.digits = start;
|
||||
bdr.end = s1;
|
||||
value = 0.0;
|
||||
|
||||
/* Skip leading zeros. */
|
||||
do {
|
||||
bit = GetNextBinaryDigit(&bdr);
|
||||
} while (bit == 0);
|
||||
|
||||
if (bit == 1) {
|
||||
/* Gather the 53 significant bits (including the leading 1) */
|
||||
value = 1.0;
|
||||
for (j = 52; j; j--) {
|
||||
bit = GetNextBinaryDigit(&bdr);
|
||||
if (bit < 0)
|
||||
goto done;
|
||||
value = value*2 + bit;
|
||||
}
|
||||
/* bit2 is the 54th bit (the first dropped from the mantissa) */
|
||||
bit2 = GetNextBinaryDigit(&bdr);
|
||||
if (bit2 >= 0) {
|
||||
jsdouble factor = 2.0;
|
||||
intN sticky = 0; /* sticky is 1 if any bit beyond the 54th is 1 */
|
||||
intN bit3;
|
||||
|
||||
while ((bit3 = GetNextBinaryDigit(&bdr)) >= 0) {
|
||||
sticky |= bit3;
|
||||
factor *= 2;
|
||||
}
|
||||
value += bit2 & (bit | sticky);
|
||||
value *= factor;
|
||||
}
|
||||
done:;
|
||||
}
|
||||
}
|
||||
/* We don't worry about inaccurate numbers for any other base. */
|
||||
|
||||
if (s1 == start) {
|
||||
*dp = 0.0;
|
||||
*ep = s;
|
||||
} else {
|
||||
*dp = negative ? -value : value;
|
||||
*ep = s1;
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
167
mozilla/js/src/jsnum.h
Normal file
167
mozilla/js/src/jsnum.h
Normal file
@@ -0,0 +1,167 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef jsnum_h___
|
||||
#define jsnum_h___
|
||||
/*
|
||||
* JS number (IEEE double) interface.
|
||||
*
|
||||
* JS numbers are optimistically stored in the top 31 bits of 32-bit integers,
|
||||
* but floating point literals, results that overflow 31 bits, and division and
|
||||
* modulus operands and results require a 64-bit IEEE double. These are GC'ed
|
||||
* and pointed to by 32-bit jsvals on the stack and in object properties.
|
||||
*
|
||||
* When a JS number is treated as an object (followed by . or []), the runtime
|
||||
* wraps it with a JSObject whose valueOf method returns the unwrapped number.
|
||||
*/
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
#define JSDOUBLE_HI32(x) (((uint32 *)&(x))[1])
|
||||
#define JSDOUBLE_LO32(x) (((uint32 *)&(x))[0])
|
||||
#else
|
||||
#define JSDOUBLE_HI32(x) (((uint32 *)&(x))[0])
|
||||
#define JSDOUBLE_LO32(x) (((uint32 *)&(x))[1])
|
||||
#endif
|
||||
#define JSDOUBLE_HI32_SIGNBIT 0x80000000
|
||||
#define JSDOUBLE_HI32_EXPMASK 0x7ff00000
|
||||
#define JSDOUBLE_HI32_MANTMASK 0x000fffff
|
||||
|
||||
#define JSDOUBLE_IS_NaN(x) \
|
||||
((JSDOUBLE_HI32(x) & JSDOUBLE_HI32_EXPMASK) == JSDOUBLE_HI32_EXPMASK && \
|
||||
(JSDOUBLE_LO32(x) || (JSDOUBLE_HI32(x) & JSDOUBLE_HI32_MANTMASK)))
|
||||
|
||||
#define JSDOUBLE_IS_INFINITE(x) \
|
||||
((JSDOUBLE_HI32(x) & ~JSDOUBLE_HI32_SIGNBIT) == JSDOUBLE_HI32_EXPMASK && \
|
||||
!JSDOUBLE_LO32(x))
|
||||
|
||||
#define JSDOUBLE_IS_FINITE(x) \
|
||||
((JSDOUBLE_HI32(x) & JSDOUBLE_HI32_EXPMASK) != JSDOUBLE_HI32_EXPMASK)
|
||||
|
||||
#define JSDOUBLE_IS_NEGZERO(d) (JSDOUBLE_HI32(d) == JSDOUBLE_HI32_SIGNBIT && \
|
||||
JSDOUBLE_LO32(d) == 0)
|
||||
|
||||
/*
|
||||
* JSDOUBLE_IS_INT first checks that d is neither NaN nor infinite, to avoid
|
||||
* raising SIGFPE on platforms such as Alpha Linux, then (only if the cast is
|
||||
* safe) leaves i as (jsint)d. This also avoid anomalous NaN floating point
|
||||
* comparisons under MSVC.
|
||||
*/
|
||||
#define JSDOUBLE_IS_INT(d, i) (JSDOUBLE_IS_FINITE(d) && !JSDOUBLE_IS_NEGZERO(d) \
|
||||
&& ((d) == (i = (jsint)(d))))
|
||||
|
||||
/* Initialize the Number class, returning its prototype object. */
|
||||
extern JSObject *
|
||||
js_InitNumberClass(JSContext *cx, JSObject *obj);
|
||||
|
||||
/* GC-allocate a new JS number. */
|
||||
extern jsdouble *
|
||||
js_NewDouble(JSContext *cx, jsdouble d);
|
||||
|
||||
extern void
|
||||
js_FinalizeDouble(JSContext *cx, jsdouble *dp);
|
||||
|
||||
extern JSBool
|
||||
js_NewDoubleValue(JSContext *cx, jsdouble d, jsval *rval);
|
||||
|
||||
extern JSBool
|
||||
js_NewNumberValue(JSContext *cx, jsdouble d, jsval *rval);
|
||||
|
||||
/* Construct a Number instance that wraps around d. */
|
||||
extern JSObject *
|
||||
js_NumberToObject(JSContext *cx, jsdouble d);
|
||||
|
||||
/* Convert a number to a GC'ed string. */
|
||||
extern JSString *
|
||||
js_NumberToString(JSContext *cx, jsdouble d);
|
||||
|
||||
/*
|
||||
* Convert a value to a number, returning false after reporting any error,
|
||||
* otherwise returning true with *dp set.
|
||||
*/
|
||||
extern JSBool
|
||||
js_ValueToNumber(JSContext *cx, jsval v, jsdouble *dp);
|
||||
|
||||
/*
|
||||
* Convert a value or a double to an int32, according to the ECMA rules
|
||||
* for ToInt32.
|
||||
*/
|
||||
extern JSBool
|
||||
js_ValueToECMAInt32(JSContext *cx, jsval v, int32 *ip);
|
||||
|
||||
extern JSBool
|
||||
js_DoubleToECMAInt32(JSContext *cx, jsdouble d, int32 *ip);
|
||||
|
||||
/*
|
||||
* Convert a value or a double to a uint32, according to the ECMA rules
|
||||
* for ToUint32.
|
||||
*/
|
||||
extern JSBool
|
||||
js_ValueToECMAUint32(JSContext *cx, jsval v, uint32 *ip);
|
||||
|
||||
extern JSBool
|
||||
js_DoubleToECMAUint32(JSContext *cx, jsdouble d, uint32 *ip);
|
||||
|
||||
/*
|
||||
* Convert a value to a number, then to an int32 if it fits by rounding to
|
||||
* nearest; but failing with an error report if the double is out of range
|
||||
* or unordered.
|
||||
*/
|
||||
extern JSBool
|
||||
js_ValueToInt32(JSContext *cx, jsval v, int32 *ip);
|
||||
|
||||
/*
|
||||
* Convert a value to a number, then to a uint16 according to the ECMA rules
|
||||
* for ToUint16.
|
||||
*/
|
||||
extern JSBool
|
||||
js_ValueToUint16(JSContext *cx, jsval v, uint16 *ip);
|
||||
|
||||
/*
|
||||
* Convert a jsdouble to an integral number, stored in a jsdouble.
|
||||
* If d is NaN, return 0. If d is an infinity, return it without conversion.
|
||||
*/
|
||||
extern jsdouble
|
||||
js_DoubleToInteger(jsdouble d);
|
||||
|
||||
/*
|
||||
* Similar to strtod except that replaces overflows with infinities of the correct
|
||||
* sign and underflows with zeros of the correct sign. Guaranteed to return the
|
||||
* closest double number to the given input in dp.
|
||||
* Also allows inputs of the form [+|-]Infinity, which produce an infinity of the
|
||||
* appropriate sign. The case of the "Infinity" string must match.
|
||||
* If the string does not have a number in it, set *ep to s and return 0.0 in dp.
|
||||
* Return false if out of memory.
|
||||
*/
|
||||
extern JSBool
|
||||
js_strtod(JSContext *cx, const jschar *s, const jschar **ep, jsdouble *dp);
|
||||
|
||||
/*
|
||||
* Similar to strtol except that handles integers of arbitrary size. Guaranteed to
|
||||
* return the closest double number to the given input when radix is 10 or a power of 2.
|
||||
* May experience roundoff errors for very large numbers of a different radix.
|
||||
* If the string does not have a number in it, set *ep to s and return 0.0 in dp.
|
||||
* Return false if out of memory.
|
||||
*/
|
||||
extern JSBool
|
||||
js_strtointeger(JSContext *cx, const jschar *s, const jschar **ep, jsint radix, jsdouble *dp);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsnum_h___ */
|
||||
2692
mozilla/js/src/jsobj.c
Normal file
2692
mozilla/js/src/jsobj.c
Normal file
File diff suppressed because it is too large
Load Diff
327
mozilla/js/src/jsobj.h
Normal file
327
mozilla/js/src/jsobj.h
Normal file
@@ -0,0 +1,327 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef jsobj_h___
|
||||
#define jsobj_h___
|
||||
/*
|
||||
* JS object definitions.
|
||||
*
|
||||
* A JS object consists of a possibly-shared object descriptor containing
|
||||
* ordered property names, called the map; and a dense vector of property
|
||||
* values, called slots. The map/slot pointer pair is GC'ed, while the map
|
||||
* is reference counted and the slot vector is malloc'ed.
|
||||
*/
|
||||
#include "jshash.h" /* Added by JSIFY */
|
||||
#include "jsprvtd.h"
|
||||
#include "jspubtd.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
struct JSObjectMap {
|
||||
jsrefcount nrefs; /* count of all referencing objects */
|
||||
JSObjectOps *ops; /* high level object operation vtable */
|
||||
uint32 nslots; /* length of obj->slots vector */
|
||||
uint32 freeslot; /* index of next free obj->slots element */
|
||||
};
|
||||
|
||||
/* Shorthand macros for frequently-made calls. */
|
||||
#if defined JS_THREADSAFE && defined DEBUG
|
||||
#define OBJ_LOOKUP_PROPERTY(cx,obj,id,objp,propp) \
|
||||
(obj)->map->ops->lookupProperty(cx,obj,id,objp,propp,__FILE__,__LINE__)
|
||||
#else
|
||||
#define OBJ_LOOKUP_PROPERTY(cx,obj,id,objp,propp) \
|
||||
(obj)->map->ops->lookupProperty(cx,obj,id,objp,propp)
|
||||
#endif
|
||||
#define OBJ_DEFINE_PROPERTY(cx,obj,id,value,getter,setter,attrs,propp) \
|
||||
(obj)->map->ops->defineProperty(cx,obj,id,value,getter,setter,attrs,propp)
|
||||
#define OBJ_GET_PROPERTY(cx,obj,id,vp) \
|
||||
(obj)->map->ops->getProperty(cx,obj,id,vp)
|
||||
#define OBJ_SET_PROPERTY(cx,obj,id,vp) \
|
||||
(obj)->map->ops->setProperty(cx,obj,id,vp)
|
||||
#define OBJ_GET_ATTRIBUTES(cx,obj,id,prop,attrsp) \
|
||||
(obj)->map->ops->getAttributes(cx,obj,id,prop,attrsp)
|
||||
#define OBJ_SET_ATTRIBUTES(cx,obj,id,prop,attrsp) \
|
||||
(obj)->map->ops->setAttributes(cx,obj,id,prop,attrsp)
|
||||
#define OBJ_DELETE_PROPERTY(cx,obj,id,rval) \
|
||||
(obj)->map->ops->deleteProperty(cx,obj,id,rval)
|
||||
#define OBJ_DEFAULT_VALUE(cx,obj,hint,vp) \
|
||||
(obj)->map->ops->defaultValue(cx,obj,hint,vp)
|
||||
#define OBJ_ENUMERATE(cx,obj,enum_op,statep,idp) \
|
||||
(obj)->map->ops->enumerate(cx,obj,enum_op,statep,idp)
|
||||
#define OBJ_CHECK_ACCESS(cx,obj,id,mode,vp,attrsp) \
|
||||
(obj)->map->ops->checkAccess(cx,obj,id,mode,vp,attrsp)
|
||||
|
||||
/* These two are time-optimized to avoid stub calls. */
|
||||
#define OBJ_THIS_OBJECT(cx,obj) \
|
||||
((obj)->map->ops->thisObject \
|
||||
? (obj)->map->ops->thisObject(cx,obj) \
|
||||
: (obj))
|
||||
#define OBJ_DROP_PROPERTY(cx,obj,prop) \
|
||||
((obj)->map->ops->dropProperty \
|
||||
? (obj)->map->ops->dropProperty(cx,obj,prop) \
|
||||
: (void)0)
|
||||
|
||||
struct JSObject {
|
||||
JSObjectMap *map;
|
||||
jsval *slots;
|
||||
};
|
||||
|
||||
#define JSSLOT_PROTO 0
|
||||
#define JSSLOT_PARENT 1
|
||||
#define JSSLOT_CLASS 2
|
||||
#define JSSLOT_PRIVATE 3
|
||||
#define JSSLOT_START 3
|
||||
|
||||
#define JSSLOT_FREE(clasp) (((clasp)->flags & JSCLASS_HAS_PRIVATE) \
|
||||
? JSSLOT_PRIVATE + 1 \
|
||||
: JSSLOT_START)
|
||||
|
||||
#define JS_INITIAL_NSLOTS 5
|
||||
|
||||
#ifdef DEBUG
|
||||
#define MAP_CHECK_SLOT(map,slot) \
|
||||
JS_ASSERT((uint32)slot < JS_MAX((map)->nslots, (map)->freeslot))
|
||||
#define OBJ_CHECK_SLOT(obj,slot) \
|
||||
MAP_CHECK_SLOT((obj)->map, slot)
|
||||
#else
|
||||
#define OBJ_CHECK_SLOT(obj,slot) ((void)0)
|
||||
#endif
|
||||
|
||||
/* Fast macros for accessing obj->slots while obj is locked (if thread-safe). */
|
||||
#define LOCKED_OBJ_GET_SLOT(obj,slot) \
|
||||
(OBJ_CHECK_SLOT(obj, slot), (obj)->slots[slot])
|
||||
#define LOCKED_OBJ_SET_SLOT(obj,slot,value) \
|
||||
(OBJ_CHECK_SLOT(obj, slot), (obj)->slots[slot] = (value))
|
||||
#define LOCKED_OBJ_GET_PROTO(obj) \
|
||||
JSVAL_TO_OBJECT(LOCKED_OBJ_GET_SLOT(obj, JSSLOT_PROTO))
|
||||
#define LOCKED_OBJ_GET_CLASS(obj) \
|
||||
((JSClass *)JSVAL_TO_PRIVATE(LOCKED_OBJ_GET_SLOT(obj, JSSLOT_CLASS)))
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
|
||||
/* Thread-safe functions and wrapper macros for accessing obj->slots. */
|
||||
#define OBJ_GET_SLOT(cx,obj,slot) \
|
||||
(OBJ_CHECK_SLOT(obj, slot), js_GetSlotWhileLocked(cx, obj, slot))
|
||||
#define OBJ_SET_SLOT(cx,obj,slot,value) \
|
||||
(OBJ_CHECK_SLOT(obj, slot), js_SetSlotWhileLocked(cx, obj, slot, value))
|
||||
|
||||
#else /* !JS_THREADSAFE */
|
||||
|
||||
#define OBJ_GET_SLOT(cx,obj,slot) LOCKED_OBJ_GET_SLOT(obj,slot)
|
||||
#define OBJ_SET_SLOT(cx,obj,slot,value) LOCKED_OBJ_SET_SLOT(obj,slot,value)
|
||||
|
||||
#endif /* !JS_THREADSAFE */
|
||||
|
||||
/* Thread-safe proto, parent, and class access macros. */
|
||||
#define OBJ_GET_PROTO(cx,obj) \
|
||||
JSVAL_TO_OBJECT(OBJ_GET_SLOT(cx, obj, JSSLOT_PROTO))
|
||||
#define OBJ_SET_PROTO(cx,obj,proto) \
|
||||
OBJ_SET_SLOT(cx, obj, JSSLOT_PROTO, OBJECT_TO_JSVAL(proto))
|
||||
|
||||
#define OBJ_GET_PARENT(cx,obj) \
|
||||
JSVAL_TO_OBJECT(OBJ_GET_SLOT(cx, obj, JSSLOT_PARENT))
|
||||
#define OBJ_SET_PARENT(cx,obj,parent) \
|
||||
OBJ_SET_SLOT(cx, obj, JSSLOT_PARENT, OBJECT_TO_JSVAL(parent))
|
||||
|
||||
#define OBJ_GET_CLASS(cx,obj) \
|
||||
((JSClass *)JSVAL_TO_PRIVATE(OBJ_GET_SLOT(cx, obj, JSSLOT_CLASS)))
|
||||
|
||||
/* Test whether a map or object is native. */
|
||||
#define MAP_IS_NATIVE(map) ((map)->ops == &js_ObjectOps || \
|
||||
(map)->ops == &js_WithObjectOps)
|
||||
#define OBJ_IS_NATIVE(obj) MAP_IS_NATIVE((obj)->map)
|
||||
|
||||
extern JS_FRIEND_DATA(JSObjectOps) js_ObjectOps;
|
||||
extern JS_FRIEND_DATA(JSObjectOps) js_WithObjectOps;
|
||||
extern JSClass js_ObjectClass;
|
||||
extern JSClass js_WithClass;
|
||||
|
||||
struct JSSharpObjectMap {
|
||||
jsrefcount depth;
|
||||
jsatomid sharpgen;
|
||||
JSHashTable *table;
|
||||
};
|
||||
|
||||
#define SHARP_BIT 1
|
||||
#define IS_SHARP(he) ((jsatomid)(he)->value & SHARP_BIT)
|
||||
#define MAKE_SHARP(he) ((he)->value = (void*)((jsatomid)(he)->value|SHARP_BIT))
|
||||
|
||||
extern JSHashEntry *
|
||||
js_EnterSharpObject(JSContext *cx, JSObject *obj, JSIdArray **idap,
|
||||
jschar **sp);
|
||||
|
||||
extern void
|
||||
js_LeaveSharpObject(JSContext *cx, JSIdArray **idap);
|
||||
|
||||
extern JSBool
|
||||
js_obj_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval);
|
||||
|
||||
extern JSBool
|
||||
js_obj_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval);
|
||||
|
||||
extern JSObject *
|
||||
js_InitObjectClass(JSContext *cx, JSObject *obj);
|
||||
|
||||
extern void
|
||||
js_InitObjectMap(JSObjectMap *map, jsrefcount nrefs, JSObjectOps *ops,
|
||||
JSClass *clasp);
|
||||
|
||||
extern JSObjectMap *
|
||||
js_NewObjectMap(JSContext *cx, jsrefcount nrefs, JSObjectOps *ops,
|
||||
JSClass *clasp, JSObject *obj);
|
||||
|
||||
extern void
|
||||
js_DestroyObjectMap(JSContext *cx, JSObjectMap *map);
|
||||
|
||||
extern JSObjectMap *
|
||||
js_HoldObjectMap(JSContext *cx, JSObjectMap *map);
|
||||
|
||||
extern JSObjectMap *
|
||||
js_DropObjectMap(JSContext *cx, JSObjectMap *map, JSObject *obj);
|
||||
|
||||
extern JSObject *
|
||||
js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent);
|
||||
|
||||
extern JSObject *
|
||||
js_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto,
|
||||
JSObject *parent);
|
||||
|
||||
extern void
|
||||
js_FinalizeObject(JSContext *cx, JSObject *obj);
|
||||
|
||||
extern JSBool
|
||||
js_AllocSlot(JSContext *cx, JSObject *obj, uint32 *slotp);
|
||||
|
||||
extern void
|
||||
js_FreeSlot(JSContext *cx, JSObject *obj, uint32 slot);
|
||||
|
||||
/*
|
||||
* On error, return false. On success, if propp is non-null, return true with
|
||||
* obj locked and with a held property in *propp; if propp is null, return true
|
||||
* but release obj's lock first. Therefore all callers who pass non-null propp
|
||||
* result parameters must later call OBJ_DROP_PROPERTY(cx, obj, *propp) both to
|
||||
* drop the held property, and to release the lock on obj.
|
||||
*/
|
||||
extern JSBool
|
||||
js_DefineProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
|
||||
JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
|
||||
JSProperty **propp);
|
||||
|
||||
/*
|
||||
* Unlike js_DefineProperty, propp must be non-null. On success, and if id was
|
||||
* found, return true with *objp non-null and locked, and with a held property
|
||||
* stored in *propp. If successful but id was not found, return true with both
|
||||
* *objp and *propp null. Therefore all callers who receive a non-null *propp
|
||||
* must later call OBJ_DROP_PROPERTY(cx, *objp, *propp).
|
||||
*/
|
||||
#if defined JS_THREADSAFE && defined DEBUG
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
_js_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
|
||||
JSProperty **propp, const char *file, uintN line);
|
||||
|
||||
#define js_LookupProperty(cx,obj,id,objp,propp) \
|
||||
_js_LookupProperty(cx,obj,id,objp,propp,__FILE__,__LINE__)
|
||||
#else
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
js_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
|
||||
JSProperty **propp);
|
||||
#endif
|
||||
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
js_FindProperty(JSContext *cx, jsid id, JSObject **objp, JSObject **pobjp,
|
||||
JSProperty **propp);
|
||||
|
||||
extern JSBool
|
||||
js_FindVariable(JSContext *cx, jsid id, JSObject **objp, JSObject **pobjp,
|
||||
JSProperty **propp);
|
||||
|
||||
extern JSObject *
|
||||
js_FindVariableScope(JSContext *cx, JSFunction **funp);
|
||||
|
||||
extern JSBool
|
||||
js_GetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
|
||||
|
||||
extern JSBool
|
||||
js_SetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
|
||||
|
||||
extern JSBool
|
||||
js_GetAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop,
|
||||
uintN *attrsp);
|
||||
|
||||
extern JSBool
|
||||
js_SetAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop,
|
||||
uintN *attrsp);
|
||||
|
||||
extern JSBool
|
||||
js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *rval);
|
||||
|
||||
extern JSBool
|
||||
js_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp);
|
||||
|
||||
extern JSBool
|
||||
js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
|
||||
jsval *statep, jsid *idp);
|
||||
|
||||
extern JSBool
|
||||
js_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
|
||||
jsval *vp, uintN *attrsp);
|
||||
|
||||
extern JSBool
|
||||
js_Call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
|
||||
|
||||
extern JSBool
|
||||
js_Construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval);
|
||||
|
||||
extern JSBool
|
||||
js_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
|
||||
|
||||
extern JSBool
|
||||
js_IsDelegate(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
|
||||
|
||||
extern JSBool
|
||||
js_GetClassPrototype(JSContext *cx, const char *name, JSObject **protop);
|
||||
|
||||
extern JSBool
|
||||
js_SetClassPrototype(JSContext *cx, JSObject *ctor, JSObject *proto,
|
||||
uintN attrs);
|
||||
|
||||
extern JSBool
|
||||
js_ValueToObject(JSContext *cx, jsval v, JSObject **objp);
|
||||
|
||||
extern JSObject *
|
||||
js_ValueToNonNullObject(JSContext *cx, jsval v);
|
||||
|
||||
extern JSBool
|
||||
js_TryValueOf(JSContext *cx, JSObject *obj, JSType type, jsval *rval);
|
||||
|
||||
extern JSBool
|
||||
js_TryMethod(JSContext *cx, JSObject *obj, JSAtom *atom,
|
||||
uintN argc, jsval *argv, jsval *rval);
|
||||
|
||||
extern JSBool
|
||||
js_XDRObject(JSXDRState *xdr, JSObject **objp);
|
||||
|
||||
extern JSIdArray *
|
||||
js_NewIdArray(JSContext *cx, jsint length);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsobj_h___ */
|
||||
2219
mozilla/js/src/jsopcode.c
Normal file
2219
mozilla/js/src/jsopcode.c
Normal file
File diff suppressed because it is too large
Load Diff
191
mozilla/js/src/jsopcode.h
Normal file
191
mozilla/js/src/jsopcode.h
Normal file
@@ -0,0 +1,191 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef jsopcode_h___
|
||||
#define jsopcode_h___
|
||||
/*
|
||||
* JS bytecode definitions.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include "jsprvtd.h"
|
||||
#include "jspubtd.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
/*
|
||||
* JS operation bytecodes.
|
||||
*/
|
||||
typedef enum JSOp {
|
||||
#define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \
|
||||
op = val,
|
||||
#include "jsopcode.tbl"
|
||||
#undef OPDEF
|
||||
JSOP_LIMIT
|
||||
} JSOp;
|
||||
|
||||
/*
|
||||
* JS bytecode formats.
|
||||
*/
|
||||
#define JOF_BYTE 0 /* single bytecode, no immediates */
|
||||
#define JOF_JUMP 1 /* signed 16-bit jump offset immediate */
|
||||
#define JOF_CONST 2 /* unsigned 16-bit constant pool index */
|
||||
#define JOF_UINT16 3 /* unsigned 16-bit immediate operand */
|
||||
#define JOF_TABLESWITCH 4 /* table switch */
|
||||
#define JOF_LOOKUPSWITCH 5 /* lookup switch */
|
||||
#define JOF_QARG 6 /* quickened get/set function argument ops */
|
||||
#define JOF_QVAR 7 /* quickened get/set local variable ops */
|
||||
#define JOF_TYPEMASK 0x000f /* mask for above immediate types */
|
||||
#define JOF_NAME 0x0010 /* name operation */
|
||||
#define JOF_PROP 0x0020 /* obj.prop operation */
|
||||
#define JOF_ELEM 0x0030 /* obj[index] operation */
|
||||
#define JOF_MODEMASK 0x0030 /* mask for above addressing modes */
|
||||
#define JOF_SET 0x0040 /* set (i.e., assignment) operation */
|
||||
#define JOF_DEL 0x0080 /* delete operation */
|
||||
#define JOF_DEC 0x0100 /* decrement (--, not ++) opcode */
|
||||
#define JOF_INC 0x0200 /* increment (++, not --) opcode */
|
||||
#define JOF_INCDEC 0x0300 /* increment or decrement opcode */
|
||||
#define JOF_POST 0x0400 /* postorder increment or decrement */
|
||||
#define JOF_IMPORT 0x0800 /* import property op */
|
||||
#define JOF_FOR2 0x1000 /* new for/in loop bytecodes */
|
||||
|
||||
/*
|
||||
* Immediate operand getters, setters, and bounds.
|
||||
*/
|
||||
#define JUMP_OFFSET_LEN 2
|
||||
#define JUMP_OFFSET_HI(off) ((jsbytecode)((off) >> 8))
|
||||
#define JUMP_OFFSET_LO(off) ((jsbytecode)(off))
|
||||
#define GET_JUMP_OFFSET(pc) ((int16)(((pc)[1] << 8) | (pc)[2]))
|
||||
#define SET_JUMP_OFFSET(pc,off) ((pc)[1] = JUMP_OFFSET_HI(off), \
|
||||
(pc)[2] = JUMP_OFFSET_LO(off))
|
||||
#define JUMP_OFFSET_MIN ((int16)0x8000)
|
||||
#define JUMP_OFFSET_MAX ((int16)0x7fff)
|
||||
|
||||
#define ATOM_INDEX_LEN 2
|
||||
#define ATOM_INDEX_HI(index) ((jsbytecode)((index) >> 8))
|
||||
#define ATOM_INDEX_LO(index) ((jsbytecode)(index))
|
||||
#define GET_ATOM_INDEX(pc) (((pc)[1] << 8) | (pc)[2])
|
||||
#define SET_ATOM_INDEX(pc,index)((pc)[1] = ATOM_INDEX_HI(index), \
|
||||
(pc)[2] = ATOM_INDEX_LO(index))
|
||||
#define GET_ATOM(cx,script,pc) js_GetAtom((cx), &(script)->atomMap, \
|
||||
GET_ATOM_INDEX(pc))
|
||||
#define ATOM_INDEX_LIMIT_LOG2 16
|
||||
#define ATOM_INDEX_LIMIT ((uint32)1 << ATOM_INDEX_LIMIT_LOG2)
|
||||
|
||||
#define ARGC_HI(argc) ((jsbytecode)((argc) >> 8))
|
||||
#define ARGC_LO(argc) ((jsbytecode)(argc))
|
||||
#define GET_ARGC(pc) (((pc)[1] << 8) | (pc)[2])
|
||||
#define ARGC_LIMIT ((uint32)1 << 16)
|
||||
|
||||
/* Synonyms for quick JOF_QARG and JOF_QVAR bytecodes. */
|
||||
#define GET_ARGNO(pc) GET_ARGC(pc)
|
||||
#define SET_ARGNO(pc,argno) SET_JUMP_OFFSET(pc,argno)
|
||||
#define GET_VARNO(pc) GET_ARGC(pc)
|
||||
#define SET_VARNO(pc,varno) SET_JUMP_OFFSET(pc,varno)
|
||||
|
||||
struct JSCodeSpec {
|
||||
const char *name; /* JS bytecode name */
|
||||
const char *token; /* JS source literal or null */
|
||||
int8 length; /* length including opcode byte */
|
||||
int8 nuses; /* arity, -1 if variadic */
|
||||
int8 ndefs; /* number of stack results */
|
||||
uint8 prec; /* operator precedence */
|
||||
uint32 format; /* immediate operand format */
|
||||
};
|
||||
|
||||
extern char js_in_str[];
|
||||
extern char js_instanceof_str[];
|
||||
extern char js_new_str[];
|
||||
extern char js_delete_str[];
|
||||
extern char js_typeof_str[];
|
||||
extern char js_void_str[];
|
||||
extern char js_null_str[];
|
||||
extern char js_this_str[];
|
||||
extern char js_false_str[];
|
||||
extern char js_true_str[];
|
||||
extern JSCodeSpec js_CodeSpec[];
|
||||
extern uintN js_NumCodeSpecs;
|
||||
extern jschar js_EscapeMap[];
|
||||
|
||||
/*
|
||||
* Return a GC'ed string containing the chars in str, with any non-printing
|
||||
* chars or quotes (' or " as specified by the quote argument) escaped, and
|
||||
* with the quote character at the beginning and end of the result string.
|
||||
*/
|
||||
extern JSString *
|
||||
js_QuoteString(JSContext *cx, JSString *str, jschar quote);
|
||||
|
||||
/*
|
||||
* JSPrinter operations, for printf style message formatting. The return
|
||||
* value from js_GetPrinterOutput() is the printer's cumulative output, in
|
||||
* a GC'ed string.
|
||||
*/
|
||||
extern JSPrinter *
|
||||
js_NewPrinter(JSContext *cx, const char *name, uintN indent);
|
||||
|
||||
extern void
|
||||
js_DestroyPrinter(JSPrinter *jp);
|
||||
|
||||
extern JSString *
|
||||
js_GetPrinterOutput(JSPrinter *jp);
|
||||
|
||||
extern int
|
||||
js_printf(JSPrinter *jp, char *format, ...);
|
||||
|
||||
extern JSBool
|
||||
js_puts(JSPrinter *jp, char *s);
|
||||
|
||||
#ifdef DEBUG
|
||||
/*
|
||||
* Disassemblers, for debugging only.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
js_Disassemble(JSContext *cx, JSScript *script, JSBool lines, FILE *fp);
|
||||
|
||||
extern JS_FRIEND_API(uintN)
|
||||
js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc, uintN loc,
|
||||
JSBool lines, FILE *fp);
|
||||
#endif /* DEBUG */
|
||||
|
||||
/*
|
||||
* Decompilers, for script, function, and expression pretty-printing.
|
||||
*/
|
||||
extern JSBool
|
||||
js_DecompileCode(JSPrinter *jp, JSScript *script, jsbytecode *pc, uintN len);
|
||||
|
||||
extern JSBool
|
||||
js_DecompileScript(JSPrinter *jp, JSScript *script);
|
||||
|
||||
extern JSBool
|
||||
js_DecompileFunctionBody(JSPrinter *jp, JSFunction *fun, JSBool newlines);
|
||||
|
||||
extern JSBool
|
||||
js_DecompileFunction(JSPrinter *jp, JSFunction *fun, JSBool newlines);
|
||||
|
||||
/*
|
||||
* Find the source expression that resulted in v, and return a new string
|
||||
* containing it. Fall back on v's string conversion if we can't find the
|
||||
* bytecode that generated and pushed v on the operand stack.
|
||||
*/
|
||||
extern JSString *
|
||||
js_DecompileValueGenerator(JSContext *cx, jsval v, JSString *fallback);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsopcode_h___ */
|
||||
217
mozilla/js/src/jsopcode.tbl
Normal file
217
mozilla/js/src/jsopcode.tbl
Normal file
@@ -0,0 +1,217 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
/*
|
||||
* JavaScript operation bytecodes.
|
||||
*
|
||||
* Includers must define an OPDEF macro of the following form:
|
||||
*
|
||||
* #define OPDEF(op,val,name,image,length,nuses,ndefs,prec,format) ...
|
||||
*
|
||||
* Selected arguments can be expanded in initializers. The op argument is
|
||||
* expanded followed by comma in the JSOp enum (jsopcode.h), e.g. The value
|
||||
* field must be dense for now, because jsopcode.c uses an OPDEF() expansion
|
||||
* inside the js_CodeSpec[] initializer.
|
||||
*
|
||||
* Field Description
|
||||
* op Bytecode name, which is the JSOp enumerator name
|
||||
* value Bytecode value, which is the JSOp enumerator value
|
||||
* name C string containing name for disassembler
|
||||
* image C string containing "image" for pretty-printer, null if ugly
|
||||
* length Number of bytes including any immediate operands
|
||||
* nuses Number of stack slots consumed by bytecode, -1 if variadic
|
||||
* ndefs Number of stack slots produced by bytecode
|
||||
* prec Operator precedence, zero if not an operator
|
||||
* format Bytecode plus immediate operand encoding format
|
||||
*
|
||||
* This file is best viewed with 116 columns:
|
||||
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345
|
||||
*/
|
||||
|
||||
/* legend: op val name image len use def prec format */
|
||||
|
||||
/* Permanently-assigned bytecodes. */
|
||||
OPDEF(JSOP_NOP, 0, "nop", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_PUSH, 1, "push", NULL, 1, 0, 1, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_POPV, 2, "popv", NULL, 1, 1, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_ENTERWITH, 3, "enterwith", NULL, 1, 1, 1, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_LEAVEWITH, 4, "leavewith", NULL, 1, 1, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_RETURN, 5, "return", NULL, 1, 1, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_GOTO, 6, "goto", NULL, 3, 0, 0, 0, JOF_JUMP)
|
||||
OPDEF(JSOP_IFEQ, 7, "ifeq", NULL, 3, 1, 0, 0, JOF_JUMP)
|
||||
OPDEF(JSOP_IFNE, 8, "ifne", NULL, 3, 1, 0, 0, JOF_JUMP)
|
||||
OPDEF(JSOP_FORNAME, 9, "forname", NULL, 3, 1, 1, 0, JOF_CONST|JOF_NAME|JOF_SET)
|
||||
OPDEF(JSOP_FORPROP, 10, "forprop", NULL, 3, 2, 1, 0, JOF_CONST|JOF_PROP|JOF_SET)
|
||||
OPDEF(JSOP_FORELEM, 11, "forelem", NULL, 1, 3, 1, 0, JOF_BYTE |JOF_ELEM|JOF_SET)
|
||||
OPDEF(JSOP_DUP, 12, "dup", NULL, 1, 1, 2, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_DUP2, 13, "dup2", NULL, 1, 2, 4, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_SETNAME, 14, "setname", NULL, 3, 1, 1, 1, JOF_CONST|JOF_NAME|JOF_SET)
|
||||
OPDEF(JSOP_BITOR, 15, "bitor", "|", 1, 2, 1, 2, JOF_BYTE)
|
||||
OPDEF(JSOP_BITXOR, 16, "bitxor", "^", 1, 2, 1, 3, JOF_BYTE)
|
||||
OPDEF(JSOP_BITAND, 17, "bitand", "&", 1, 2, 1, 4, JOF_BYTE)
|
||||
OPDEF(JSOP_EQ, 18, "eq", "==", 1, 2, 1, 5, JOF_BYTE)
|
||||
OPDEF(JSOP_NE, 19, "ne", "!=", 1, 2, 1, 5, JOF_BYTE)
|
||||
OPDEF(JSOP_LT, 20, "lt", "<", 1, 2, 1, 6, JOF_BYTE)
|
||||
OPDEF(JSOP_LE, 21, "le", "<=", 1, 2, 1, 6, JOF_BYTE)
|
||||
OPDEF(JSOP_GT, 22, "gt", ">", 1, 2, 1, 6, JOF_BYTE)
|
||||
OPDEF(JSOP_GE, 23, "ge", ">=", 1, 2, 1, 6, JOF_BYTE)
|
||||
OPDEF(JSOP_LSH, 24, "lsh", "<<", 1, 2, 1, 7, JOF_BYTE)
|
||||
OPDEF(JSOP_RSH, 25, "rsh", ">>", 1, 2, 1, 7, JOF_BYTE)
|
||||
OPDEF(JSOP_URSH, 26, "ursh", ">>>", 1, 2, 1, 7, JOF_BYTE)
|
||||
OPDEF(JSOP_ADD, 27, "add", "+", 1, 2, 1, 8, JOF_BYTE)
|
||||
OPDEF(JSOP_SUB, 28, "sub", "-", 1, 2, 1, 8, JOF_BYTE)
|
||||
OPDEF(JSOP_MUL, 29, "mul", "*", 1, 2, 1, 9, JOF_BYTE)
|
||||
OPDEF(JSOP_DIV, 30, "div", "/", 1, 2, 1, 9, JOF_BYTE)
|
||||
OPDEF(JSOP_MOD, 31, "mod", "%", 1, 2, 1, 9, JOF_BYTE)
|
||||
OPDEF(JSOP_NOT, 32, "not", "!", 1, 1, 1, 10, JOF_BYTE)
|
||||
OPDEF(JSOP_BITNOT, 33, "bitnot", "~", 1, 1, 1, 10, JOF_BYTE)
|
||||
OPDEF(JSOP_NEG, 34, "neg", "-", 1, 1, 1, 10, JOF_BYTE)
|
||||
OPDEF(JSOP_NEW, 35, js_new_str, NULL, 3, -1, 1, 10, JOF_UINT16)
|
||||
OPDEF(JSOP_DELNAME, 36, "delname", NULL, 3, 0, 1, 10, JOF_CONST|JOF_NAME|JOF_DEL)
|
||||
OPDEF(JSOP_DELPROP, 37, "delprop", NULL, 3, 1, 1, 10, JOF_CONST|JOF_PROP|JOF_DEL)
|
||||
OPDEF(JSOP_DELELEM, 38, "delelem", NULL, 1, 2, 1, 10, JOF_BYTE |JOF_ELEM|JOF_DEL)
|
||||
OPDEF(JSOP_TYPEOF, 39, js_typeof_str,NULL, 1, 1, 1, 10, JOF_BYTE)
|
||||
OPDEF(JSOP_VOID, 40, js_void_str, NULL, 1, 1, 1, 10, JOF_BYTE)
|
||||
OPDEF(JSOP_INCNAME, 41, "incname", NULL, 3, 0, 1, 10, JOF_CONST|JOF_NAME|JOF_INC)
|
||||
OPDEF(JSOP_INCPROP, 42, "incprop", NULL, 3, 1, 1, 10, JOF_CONST|JOF_PROP|JOF_INC)
|
||||
OPDEF(JSOP_INCELEM, 43, "incelem", NULL, 1, 2, 1, 10, JOF_BYTE |JOF_ELEM|JOF_INC)
|
||||
OPDEF(JSOP_DECNAME, 44, "decname", NULL, 3, 0, 1, 10, JOF_CONST|JOF_NAME|JOF_DEC)
|
||||
OPDEF(JSOP_DECPROP, 45, "decprop", NULL, 3, 1, 1, 10, JOF_CONST|JOF_PROP|JOF_DEC)
|
||||
OPDEF(JSOP_DECELEM, 46, "decelem", NULL, 1, 2, 1, 10, JOF_BYTE |JOF_ELEM|JOF_DEC)
|
||||
OPDEF(JSOP_NAMEINC, 47, "nameinc", NULL, 3, 0, 1, 10, JOF_CONST|JOF_NAME|JOF_INC|JOF_POST)
|
||||
OPDEF(JSOP_PROPINC, 48, "propinc", NULL, 3, 1, 1, 10, JOF_CONST|JOF_PROP|JOF_INC|JOF_POST)
|
||||
OPDEF(JSOP_ELEMINC, 49, "eleminc", NULL, 1, 2, 1, 10, JOF_BYTE |JOF_ELEM|JOF_INC|JOF_POST)
|
||||
OPDEF(JSOP_NAMEDEC, 50, "namedec", NULL, 3, 0, 1, 10, JOF_CONST|JOF_NAME|JOF_DEC|JOF_POST)
|
||||
OPDEF(JSOP_PROPDEC, 51, "propdec", NULL, 3, 1, 1, 10, JOF_CONST|JOF_PROP|JOF_DEC|JOF_POST)
|
||||
OPDEF(JSOP_ELEMDEC, 52, "elemdec", NULL, 1, 2, 1, 10, JOF_BYTE |JOF_ELEM|JOF_DEC|JOF_POST)
|
||||
OPDEF(JSOP_GETPROP, 53, "getprop", NULL, 3, 1, 1, 11, JOF_CONST|JOF_PROP)
|
||||
OPDEF(JSOP_SETPROP, 54, "setprop", NULL, 3, 2, 1, 1, JOF_CONST|JOF_PROP|JOF_SET)
|
||||
OPDEF(JSOP_GETELEM, 55, "getelem", NULL, 1, 2, 1, 11, JOF_BYTE |JOF_ELEM)
|
||||
OPDEF(JSOP_SETELEM, 56, "setelem", NULL, 1, 3, 1, 1, JOF_BYTE |JOF_ELEM|JOF_SET)
|
||||
OPDEF(JSOP_PUSHOBJ, 57, "pushobj", NULL, 1, 0, 1, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_CALL, 58, "call", NULL, 3, -1, 1, 11, JOF_UINT16)
|
||||
OPDEF(JSOP_NAME, 59, "name", NULL, 3, 0, 1, 12, JOF_CONST|JOF_NAME)
|
||||
OPDEF(JSOP_NUMBER, 60, "number", NULL, 3, 0, 1, 12, JOF_CONST)
|
||||
OPDEF(JSOP_STRING, 61, "string", NULL, 3, 0, 1, 12, JOF_CONST)
|
||||
OPDEF(JSOP_ZERO, 62, "zero", "0", 1, 0, 1, 12, JOF_BYTE)
|
||||
OPDEF(JSOP_ONE, 63, "one", "1", 1, 0, 1, 12, JOF_BYTE)
|
||||
OPDEF(JSOP_NULL, 64, js_null_str, js_null_str, 1, 0, 1, 12, JOF_BYTE)
|
||||
OPDEF(JSOP_THIS, 65, js_this_str, js_this_str, 1, 0, 1, 12, JOF_BYTE)
|
||||
OPDEF(JSOP_FALSE, 66, js_false_str, js_false_str, 1, 0, 1, 12, JOF_BYTE)
|
||||
OPDEF(JSOP_TRUE, 67, js_true_str, js_true_str, 1, 0, 1, 12, JOF_BYTE)
|
||||
OPDEF(JSOP_OR, 68, "or", NULL, 3, 1, 0, 0, JOF_JUMP)
|
||||
OPDEF(JSOP_AND, 69, "and", NULL, 3, 1, 0, 0, JOF_JUMP)
|
||||
|
||||
/* The switch bytecodes have variable length. */
|
||||
OPDEF(JSOP_TABLESWITCH, 70, "tableswitch", NULL, -1, 1, 0, 0, JOF_TABLESWITCH)
|
||||
OPDEF(JSOP_LOOKUPSWITCH, 71, "lookupswitch", NULL, -1, 1, 0, 0, JOF_LOOKUPSWITCH)
|
||||
|
||||
/* New, infallible/transitive identity ops. */
|
||||
OPDEF(JSOP_NEW_EQ, 72, "eq", NULL, 1, 2, 1, 5, JOF_BYTE)
|
||||
OPDEF(JSOP_NEW_NE, 73, "ne", NULL, 1, 2, 1, 5, JOF_BYTE)
|
||||
|
||||
/* Lexical closure constructor. */
|
||||
OPDEF(JSOP_CLOSURE, 74, "closure", NULL, 3, 0, 1, 0, JOF_CONST)
|
||||
|
||||
/* Export and import ops. */
|
||||
OPDEF(JSOP_EXPORTALL, 75, "exportall", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_EXPORTNAME,76, "exportname", NULL, 3, 0, 0, 0, JOF_CONST|JOF_NAME)
|
||||
OPDEF(JSOP_IMPORTALL, 77, "importall", NULL, 1, 1, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_IMPORTPROP,78, "importprop", NULL, 3, 1, 0, 0, JOF_CONST|JOF_PROP|JOF_IMPORT)
|
||||
OPDEF(JSOP_IMPORTELEM,79, "importelem", NULL, 1, 2, 0, 0, JOF_BYTE |JOF_ELEM|JOF_IMPORT)
|
||||
|
||||
/* Push object literal. */
|
||||
OPDEF(JSOP_OBJECT, 80, "object", NULL, 3, 0, 1, 12, JOF_CONST)
|
||||
|
||||
/* Pop value and discard it. */
|
||||
OPDEF(JSOP_POP, 81, "pop", NULL, 1, 1, 0, 0, JOF_BYTE)
|
||||
|
||||
/* Convert value to number, for unary +. */
|
||||
OPDEF(JSOP_POS, 82, "pos", "+", 1, 1, 1, 10, JOF_BYTE)
|
||||
|
||||
/* Trap into debugger for breakpoint, etc. */
|
||||
OPDEF(JSOP_TRAP, 83, "trap", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
|
||||
/* Fast get/set ops for function arguments and local variables. */
|
||||
OPDEF(JSOP_GETARG, 84, "getarg", NULL, 3, 0, 1, 12, JOF_QARG |JOF_NAME)
|
||||
OPDEF(JSOP_SETARG, 85, "setarg", NULL, 3, 1, 1, 1, JOF_QARG |JOF_NAME|JOF_SET)
|
||||
OPDEF(JSOP_GETVAR, 86, "getvar", NULL, 3, 0, 1, 12, JOF_QVAR |JOF_NAME)
|
||||
OPDEF(JSOP_SETVAR, 87, "setvar", NULL, 3, 1, 1, 1, JOF_QVAR |JOF_NAME|JOF_SET)
|
||||
|
||||
/* Push unsigned 16-bit int constant. */
|
||||
OPDEF(JSOP_UINT16, 88, "uint16", NULL, 3, 0, 1, 12, JOF_UINT16)
|
||||
|
||||
/* Object and array literal support. */
|
||||
OPDEF(JSOP_NEWINIT, 89, "newinit", NULL, 1, 2, 1, 10, JOF_BYTE)
|
||||
OPDEF(JSOP_ENDINIT, 90, "endinit", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_INITPROP, 91, "initprop", NULL, 3, 1, 0, 0, JOF_CONST|JOF_PROP)
|
||||
OPDEF(JSOP_INITELEM, 92, "initelem", NULL, 1, 2, 0, 0, JOF_BYTE |JOF_ELEM)
|
||||
OPDEF(JSOP_DEFSHARP, 93, "defsharp", NULL, 3, 0, 0, 0, JOF_UINT16)
|
||||
OPDEF(JSOP_USESHARP, 94, "usesharp", NULL, 3, 0, 1, 0, JOF_UINT16)
|
||||
|
||||
/* Fast inc/dec ops for args and local vars. */
|
||||
OPDEF(JSOP_INCARG, 95, "incarg", NULL, 3, 0, 1, 10, JOF_QARG |JOF_NAME|JOF_INC)
|
||||
OPDEF(JSOP_INCVAR, 96, "incvar", NULL, 3, 0, 1, 10, JOF_QVAR |JOF_NAME|JOF_INC)
|
||||
OPDEF(JSOP_DECARG, 97, "decarg", NULL, 3, 0, 1, 10, JOF_QARG |JOF_NAME|JOF_DEC)
|
||||
OPDEF(JSOP_DECVAR, 98, "decvar", NULL, 3, 0, 1, 10, JOF_QVAR |JOF_NAME|JOF_DEC)
|
||||
OPDEF(JSOP_ARGINC, 99, "arginc", NULL, 3, 0, 1, 10, JOF_QARG |JOF_NAME|JOF_INC|JOF_POST)
|
||||
OPDEF(JSOP_VARINC, 100,"varinc", NULL, 3, 0, 1, 10, JOF_QVAR |JOF_NAME|JOF_INC|JOF_POST)
|
||||
OPDEF(JSOP_ARGDEC, 101,"argdec", NULL, 3, 0, 1, 10, JOF_QARG |JOF_NAME|JOF_DEC|JOF_POST)
|
||||
OPDEF(JSOP_VARDEC, 102,"vardec", NULL, 3, 0, 1, 10, JOF_QVAR |JOF_NAME|JOF_DEC|JOF_POST)
|
||||
|
||||
/* ECMA-compliant for/in ops. */
|
||||
OPDEF(JSOP_TOOBJECT, 103,"toobject", NULL, 1, 1, 1, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_FORNAME2, 104,"forname2", NULL, 3, 0, 1, 0, JOF_CONST|JOF_NAME|JOF_SET|JOF_FOR2)
|
||||
OPDEF(JSOP_FORPROP2, 105,"forprop2", NULL, 3, 1, 1, 0, JOF_CONST|JOF_PROP|JOF_SET|JOF_FOR2)
|
||||
OPDEF(JSOP_FORELEM2, 106,"forelem2", NULL, 1, 2, 1, 0, JOF_BYTE |JOF_ELEM|JOF_SET|JOF_FOR2)
|
||||
OPDEF(JSOP_POP2, 107,"pop2", NULL, 1, 2, 0, 0, JOF_BYTE)
|
||||
|
||||
/* ECMA-complaint assignment ops. */
|
||||
OPDEF(JSOP_BINDNAME, 108,"bindname", NULL, 3, 0, 1, 0, JOF_CONST|JOF_NAME)
|
||||
OPDEF(JSOP_SETNAME2, 109,"setname2", NULL, 3, 2, 1, 1, JOF_CONST|JOF_NAME|JOF_SET)
|
||||
|
||||
/* Exception handling ops. */
|
||||
OPDEF(JSOP_THROW, 110,"throw", NULL, 1, 1, 0, 0, JOF_BYTE)
|
||||
|
||||
/* 'in' and 'instanceof' ops. */
|
||||
OPDEF(JSOP_IN, 111,js_in_str, js_in_str, 1, 2, 1, 6, JOF_BYTE)
|
||||
OPDEF(JSOP_INSTANCEOF,112,js_instanceof_str,js_instanceof_str,1,2,1,6,JOF_BYTE)
|
||||
|
||||
/* debugger op */
|
||||
OPDEF(JSOP_DEBUGGER, 113,"debugger", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
|
||||
/* gosub/retsub for finally handling */
|
||||
OPDEF(JSOP_GOSUB, 114,"gosub", NULL, 3, 0, 1, 0, JOF_JUMP)
|
||||
OPDEF(JSOP_RETSUB, 115,"retsub", NULL, 1, 1, 0, 0, JOF_BYTE)
|
||||
|
||||
/* more exception handling ops */
|
||||
OPDEF(JSOP_EXCEPTION, 116,"exception", NULL, 1, 0, 1, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_SETSP, 117,"setsp", NULL, 3, 0, 0, 0, JOF_UINT16)
|
||||
|
||||
/*
|
||||
* ECMA-compliant switch statement ops.
|
||||
* CONDSWITCH is a decompilable NOP; CASE is ===, POP, jump if true, re-push
|
||||
* lval if false; and DEFAULT is POP lval and GOTO.
|
||||
*/
|
||||
OPDEF(JSOP_CONDSWITCH,118,"condswitch", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_CASE, 119,"case", NULL, 3, 1, 0, 0, JOF_JUMP)
|
||||
OPDEF(JSOP_DEFAULT, 120,"default", NULL, 3, 1, 0, 0, JOF_JUMP)
|
||||
|
||||
/*
|
||||
* ECMA-compliant call to eval op
|
||||
*/
|
||||
OPDEF(JSOP_CALLSPECIAL,121,"callspecial",NULL, 3, -1, 1, 11, JOF_UINT16)
|
||||
92
mozilla/js/src/jsosdep.h
Normal file
92
mozilla/js/src/jsosdep.h
Normal file
@@ -0,0 +1,92 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef jsosdep_h___
|
||||
#define jsosdep_h___
|
||||
/*
|
||||
* OS (and machine, and compiler XXX) dependent information.
|
||||
*/
|
||||
|
||||
#ifdef XP_PC
|
||||
|
||||
#ifdef _WIN32
|
||||
#define JS_HAVE_LONG_LONG
|
||||
#else
|
||||
#undef JS_HAVE_LONG_LONG
|
||||
#endif
|
||||
#endif /* XP_PC */
|
||||
|
||||
#ifdef XP_MAC
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
extern void* reallocSmaller(void* block, size_t newSize);
|
||||
|
||||
extern char* strdup(const char* str);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* XP_MAC */
|
||||
|
||||
#ifdef XP_UNIX
|
||||
|
||||
/*
|
||||
* Get OS specific header information.
|
||||
*/
|
||||
#if defined(AIXV3)
|
||||
#define JS_HAVE_LONG_LONG
|
||||
|
||||
#elif defined(BSDI)
|
||||
#define JS_HAVE_LONG_LONG
|
||||
|
||||
#elif defined(HPUX)
|
||||
#undef JS_HAVE_LONG_LONG
|
||||
|
||||
#elif defined(IRIX)
|
||||
#define JS_HAVE_LONG_LONG
|
||||
|
||||
#elif defined(linux)
|
||||
#define JS_HAVE_LONG_LONG
|
||||
|
||||
#elif defined(OSF1)
|
||||
#define JS_HAVE_LONG_LONG
|
||||
|
||||
#elif defined(SCO)
|
||||
#undef JS_HAVE_LONG_LONG
|
||||
|
||||
#elif defined(SOLARIS)
|
||||
#define JS_HAVE_LONG_LONG
|
||||
|
||||
#elif defined(SUNOS4)
|
||||
#undef JS_HAVE_LONG_LONG
|
||||
|
||||
/*
|
||||
** Missing function prototypes
|
||||
*/
|
||||
|
||||
extern void *sbrk(int);
|
||||
|
||||
#elif defined(UNIXWARE)
|
||||
#undef JS_HAVE_LONG_LONG
|
||||
#endif
|
||||
|
||||
#endif /* XP_UNIX */
|
||||
|
||||
#endif /* jsosdep_h___ */
|
||||
176
mozilla/js/src/jsotypes.h
Normal file
176
mozilla/js/src/jsotypes.h
Normal file
@@ -0,0 +1,176 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This section typedefs the old 'native' types to the new PR<type>s.
|
||||
* These definitions are scheduled to be eliminated at the earliest
|
||||
* possible time. The NSPR API is implemented and documented using
|
||||
* the new definitions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Note that we test for PROTYPES_H, not JSOTYPES_H. This is to avoid
|
||||
* double-definitions of scalar types such as uint32, if NSPR's
|
||||
* protypes.h is also included.
|
||||
*/
|
||||
#ifndef PROTYPES_H
|
||||
#define PROTYPES_H
|
||||
|
||||
/* SVR4 typedef of uint is commonly found on UNIX machines. */
|
||||
#ifdef XP_UNIX
|
||||
#include <sys/types.h>
|
||||
#else
|
||||
typedef JSUintn uint;
|
||||
#endif
|
||||
|
||||
typedef JSUintn uintn;
|
||||
typedef JSUint64 uint64;
|
||||
#if !defined(XP_MAC) && !defined(_WIN32) && !defined(XP_OS2)
|
||||
typedef JSUint32 uint32;
|
||||
#else
|
||||
typedef unsigned long uint32;
|
||||
#endif
|
||||
typedef JSUint16 uint16;
|
||||
typedef JSUint8 uint8;
|
||||
|
||||
#ifndef _XP_Core_
|
||||
typedef JSIntn intn;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* On AIX 4.3, sys/inttypes.h (which is included by sys/types.h, a very
|
||||
* common header file) defines the types int8, int16, int32, and int64.
|
||||
* So we don't define these four types here to avoid conflicts in case
|
||||
* the code also includes sys/types.h.
|
||||
*/
|
||||
#ifdef AIX4_3
|
||||
#include <sys/inttypes.h>
|
||||
#else
|
||||
typedef JSInt64 int64;
|
||||
|
||||
/* /usr/include/model.h on HP-UX defines int8, int16, and int32 */
|
||||
#ifdef HPUX
|
||||
#include <model.h>
|
||||
#else
|
||||
#if !defined(WIN32) || !defined(_WINSOCK2API_) /* defines its own "int32" */
|
||||
#if !defined(XP_MAC) && !defined(_WIN32) && !defined(XP_OS2)
|
||||
typedef JSInt32 int32;
|
||||
#else
|
||||
typedef long int32;
|
||||
#endif
|
||||
#endif
|
||||
typedef JSInt16 int16;
|
||||
typedef JSInt8 int8;
|
||||
#endif /* HPUX */
|
||||
#endif /* AIX4_3 */
|
||||
|
||||
typedef JSFloat64 float64;
|
||||
|
||||
/* Re: jsbit.h */
|
||||
#define TEST_BIT JS_TEST_BIT
|
||||
#define SET_BIT JS_SET_BIT
|
||||
#define CLEAR_BIT JS_CLEAR_BIT
|
||||
|
||||
/* Re: prarena.h->plarena.h */
|
||||
#define PRArena PLArena
|
||||
#define PRArenaPool PLArenaPool
|
||||
#define PRArenaStats PLArenaStats
|
||||
#define PR_ARENA_ALIGN PL_ARENA_ALIGN
|
||||
#define PR_INIT_ARENA_POOL PL_INIT_ARENA_POOL
|
||||
#define PR_ARENA_ALLOCATE PL_ARENA_ALLOCATE
|
||||
#define PR_ARENA_GROW PL_ARENA_GROW
|
||||
#define PR_ARENA_MARK PL_ARENA_MARK
|
||||
#define PR_CLEAR_UNUSED PL_CLEAR_UNUSED
|
||||
#define PR_CLEAR_ARENA PL_CLEAR_ARENA
|
||||
#define PR_ARENA_RELEASE PL_ARENA_RELEASE
|
||||
#define PR_COUNT_ARENA PL_COUNT_ARENA
|
||||
#define PR_ARENA_DESTROY PL_ARENA_DESTROY
|
||||
#define PR_InitArenaPool PL_InitArenaPool
|
||||
#define PR_FreeArenaPool PL_FreeArenaPool
|
||||
#define PR_FinishArenaPool PL_FinishArenaPool
|
||||
#define PR_CompactArenaPool PL_CompactArenaPool
|
||||
#define PR_ArenaFinish PL_ArenaFinish
|
||||
#define PR_ArenaAllocate PL_ArenaAllocate
|
||||
#define PR_ArenaGrow PL_ArenaGrow
|
||||
#define PR_ArenaRelease PL_ArenaRelease
|
||||
#define PR_ArenaCountAllocation PL_ArenaCountAllocation
|
||||
#define PR_ArenaCountInplaceGrowth PL_ArenaCountInplaceGrowth
|
||||
#define PR_ArenaCountGrowth PL_ArenaCountGrowth
|
||||
#define PR_ArenaCountRelease PL_ArenaCountRelease
|
||||
#define PR_ArenaCountRetract PL_ArenaCountRetract
|
||||
|
||||
/* Re: prevent.h->plevent.h */
|
||||
#define PREvent PLEvent
|
||||
#define PREventQueue PLEventQueue
|
||||
#define PR_CreateEventQueue PL_CreateEventQueue
|
||||
#define PR_DestroyEventQueue PL_DestroyEventQueue
|
||||
#define PR_GetEventQueueMonitor PL_GetEventQueueMonitor
|
||||
#define PR_ENTER_EVENT_QUEUE_MONITOR PL_ENTER_EVENT_QUEUE_MONITOR
|
||||
#define PR_EXIT_EVENT_QUEUE_MONITOR PL_EXIT_EVENT_QUEUE_MONITOR
|
||||
#define PR_PostEvent PL_PostEvent
|
||||
#define PR_PostSynchronousEvent PL_PostSynchronousEvent
|
||||
#define PR_GetEvent PL_GetEvent
|
||||
#define PR_EventAvailable PL_EventAvailable
|
||||
#define PREventFunProc PLEventFunProc
|
||||
#define PR_MapEvents PL_MapEvents
|
||||
#define PR_RevokeEvents PL_RevokeEvents
|
||||
#define PR_ProcessPendingEvents PL_ProcessPendingEvents
|
||||
#define PR_WaitForEvent PL_WaitForEvent
|
||||
#define PR_EventLoop PL_EventLoop
|
||||
#define PR_GetEventQueueSelectFD PL_GetEventQueueSelectFD
|
||||
#define PRHandleEventProc PLHandleEventProc
|
||||
#define PRDestroyEventProc PLDestroyEventProc
|
||||
#define PR_InitEvent PL_InitEvent
|
||||
#define PR_GetEventOwner PL_GetEventOwner
|
||||
#define PR_HandleEvent PL_HandleEvent
|
||||
#define PR_DestroyEvent PL_DestroyEvent
|
||||
#define PR_DequeueEvent PL_DequeueEvent
|
||||
#define PR_GetMainEventQueue PL_GetMainEventQueue
|
||||
|
||||
/* Re: prhash.h->plhash.h */
|
||||
#define PRHashEntry PLHashEntry
|
||||
#define PRHashTable PLHashTable
|
||||
#define PRHashNumber PLHashNumber
|
||||
#define PRHashFunction PLHashFunction
|
||||
#define PRHashComparator PLHashComparator
|
||||
#define PRHashEnumerator PLHashEnumerator
|
||||
#define PRHashAllocOps PLHashAllocOps
|
||||
#define PR_NewHashTable PL_NewHashTable
|
||||
#define PR_HashTableDestroy PL_HashTableDestroy
|
||||
#define PR_HashTableRawLookup PL_HashTableRawLookup
|
||||
#define PR_HashTableRawAdd PL_HashTableRawAdd
|
||||
#define PR_HashTableRawRemove PL_HashTableRawRemove
|
||||
#define PR_HashTableAdd PL_HashTableAdd
|
||||
#define PR_HashTableRemove PL_HashTableRemove
|
||||
#define PR_HashTableEnumerateEntries PL_HashTableEnumerateEntries
|
||||
#define PR_HashTableLookup PL_HashTableLookup
|
||||
#define PR_HashTableDump PL_HashTableDump
|
||||
#define PR_HashString PL_HashString
|
||||
#define PR_CompareStrings PL_CompareStrings
|
||||
#define PR_CompareValues PL_CompareValues
|
||||
|
||||
#ifdef XP_MAC
|
||||
#ifndef TRUE /* Mac standard is lower case true */
|
||||
#define TRUE 1
|
||||
#endif
|
||||
#ifndef FALSE /* Mac standard is lower case false */
|
||||
#define FALSE 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* !defined(PROTYPES_H) */
|
||||
2727
mozilla/js/src/jsparse.c
Normal file
2727
mozilla/js/src/jsparse.c
Normal file
File diff suppressed because it is too large
Load Diff
256
mozilla/js/src/jsparse.h
Normal file
256
mozilla/js/src/jsparse.h
Normal file
@@ -0,0 +1,256 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef jsparse_h___
|
||||
#define jsparse_h___
|
||||
/*
|
||||
* JS parser definitions.
|
||||
*/
|
||||
#include "jsprvtd.h"
|
||||
#include "jspubtd.h"
|
||||
#include "jsscan.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
/*
|
||||
* Parsing builds a tree of nodes that directs code generation. This tree is
|
||||
* not a concrete syntax tree in all respects (for example, || and && are left
|
||||
* associative, but (A && B && C) translates into the right-associated tree
|
||||
* <A && <B && C>> so that code generation can emit a left-associative branch
|
||||
* around <B && C> when A is false). Nodes are labeled by token type, with a
|
||||
* JSOp secondary label when needed:
|
||||
*
|
||||
* Label Variant Members
|
||||
* ----- ------- -------
|
||||
* <Definitions>
|
||||
* TOK_FUNCTION func pn_fun: function, contains arg and var properties
|
||||
* pn_body: TOK_LC node for function body
|
||||
* NB: We define or create the function object at
|
||||
* parse (not emit) time, in order to specialize arg
|
||||
* and var bytecodes early.
|
||||
* pn_tryCount: of try statements in function
|
||||
*
|
||||
* <Statements>
|
||||
* TOK_LC list pn_head: list of pn_count statements
|
||||
* TOK_EXPORT list pn_head: list of pn_count TOK_NAMEs or one TOK_STAR
|
||||
* (which is not a multiply node)
|
||||
* TOK_IMPORT list pn_head: list of pn_count sub-trees of the form
|
||||
* a.b.*, a[b].*, a.*, a.b, or a[b] -- but never a.
|
||||
* Each member is expressed with TOK_DOT or TOK_LB.
|
||||
* Each sub-tree's root node has a pn_op in the set
|
||||
* JSOP_IMPORT{ALL,PROP,ELEM}
|
||||
* TOK_IF ternary pn_kid1: cond, pn_kid2: then, pn_kid3: else or null
|
||||
* TOK_SWITCH binary pn_left: discriminant
|
||||
* pn_right: list of TOK_CASE nodes, with at most one
|
||||
* TOK_DEFAULT node
|
||||
* TOK_CASE, binary pn_left: case expr or null if TOK_DEFAULT
|
||||
* TOK_DEFAULT pn_right: TOK_LC node for this case's statements
|
||||
* TOK_WHILE binary pn_left: cond, pn_right: body
|
||||
* TOK_DO binary pn_left: body, pn_right: cond
|
||||
* TOK_FOR binary pn_left: either
|
||||
* for/in loop: a binary TOK_IN node with
|
||||
* pn_left: TOK_VAR or TOK_NAME to left of 'in'
|
||||
* pn_right: object expr to right of 'in'
|
||||
* for(;;) loop: a ternary TOK_RESERVED node with
|
||||
* pn_kid1: init expr before first ';'
|
||||
* pn_kid2: cond expr before second ';'
|
||||
* pn_kid3: update expr after second ';'
|
||||
* any kid may be null
|
||||
* pn_right: body
|
||||
* TOK_THROW unary pn_op: JSOP_THROW, pn_kid: exception
|
||||
* TOK_BREAK name pn_atom: label or null
|
||||
* TOK_CONTINUE name pn_atom: label or null
|
||||
* TOK_WITH binary pn_left: head expr, pn_right: body
|
||||
* TOK_VAR list pn_head: list of pn_count TOK_NAME nodes
|
||||
* each name node has pn_atom: variable name and
|
||||
* pn_expr: initializer or null
|
||||
* TOK_RETURN unary pn_kid: return expr or null
|
||||
* TOK_SEMI unary pn_kid: expr or null statement
|
||||
* TOK_COLON name pn_atom: label, pn_expr: labeled statement
|
||||
*
|
||||
* <Expressions>
|
||||
* TOK_COMMA list pn_head: list of pn_count comma-separated exprs
|
||||
* TOK_ASSIGN binary pn_left: lvalue, pn_right: rvalue
|
||||
* TOK_HOOK ternary pn_kid1: cond, pn_kid2: then, pn_kid3: else
|
||||
* TOK_OR binary pn_left: first in || chain, pn_right: rest of chain
|
||||
* TOK_AND binary pn_left: first in && chain, pn_right: rest of chain
|
||||
* TOK_BITOR binary pn_left: left-assoc | expr, pn_right: ^ expr
|
||||
* TOK_BITXOR binary pn_left: left-assoc ^ expr, pn_right: & expr
|
||||
* TOK_BITAND binary pn_left: left-assoc & expr, pn_right: EQ expr
|
||||
* TOK_EQOP binary pn_left: left-assoc EQ expr, pn_right: REL expr
|
||||
* pn_op: JSOP_EQ, JSOP_NE, JSOP_NEW_EQ, JSOP_NEW_NE
|
||||
* TOK_RELOP binary pn_left: left-assoc REL expr, pn_right: SH expr
|
||||
* pn_op: JSOP_LT, JSOP_LE, JSOP_GT, JSOP_GE
|
||||
* TOK_SHOP binary pn_left: left-assoc SH expr, pn_right: ADD expr
|
||||
* pn_op: JSOP_LSH, JSOP_RSH, JSOP_URSH
|
||||
* TOK_PLUS, binary pn_left: left-assoc ADD expr, pn_right: MUL expr
|
||||
* TOK_MINUS pn_op: JSOP_ADD, JSOP_SUB
|
||||
* TOK_STAR, binary pn_left: left-assoc MUL expr, pn_right: UNARY expr
|
||||
* TOK_DIVOP pn_op: JSOP_MUL, JSOP_DIV, JSOP_MOD
|
||||
* TOK_UNARYOP unary pn_kid: UNARY expr, pn_op: JSOP_NEG, JSOP_POS,
|
||||
* JSOP_NOT, JSOP_BITNOT, JSOP_TYPEOF, JSOP_VOID
|
||||
* TOK_INC, unary pn_kid: MEMBER expr
|
||||
* TOK_DEC pn_num: arg or local var slot if non-negative
|
||||
* TOK_NEW list pn_head: list of ctor, arg1, arg2, ... argN
|
||||
* pn_count: 1 + N (where N is number of args)
|
||||
* ctor is a MEMBER expr
|
||||
* TOK_DELETE unary pn_kid: MEMBER expr
|
||||
* TOK_DOT name pn_expr: MEMBER expr to left of .
|
||||
* pn_atom: name to right of .
|
||||
* TOK_LB binary pn_left: MEMBER expr to left of [
|
||||
* pn_right: expr between [ and ]
|
||||
* TOK_LP list pn_head: list of call, arg1, arg2, ... argN
|
||||
* pn_count: 1 + N (where N is number of args)
|
||||
* call is a MEMBER expr naming a callable object
|
||||
* TOK_RB list pn_head: list of pn_count array element exprs
|
||||
* [,,] holes are represented by TOK_COMMA nodes
|
||||
* #n=[...] produces TOK_DEFSHARP at head of list
|
||||
* pn_extra: true if extra comma at end
|
||||
* TOK_RC list pn_head: list of pn_count TOK_COLON nodes where
|
||||
* each has pn_left: property id, pn_right: value
|
||||
* #n={...} produces TOK_DEFSHARP at head of list
|
||||
* TOK_DEFSHARP unary pn_num: jsint value of n in #n=
|
||||
* pn_kid: null for #n=[...] and #n={...}, primary
|
||||
* if #n=primary for function, paren, name, object
|
||||
* literal expressions
|
||||
* TOK_USESHARP nullary pn_num: jsint value of n in #n#
|
||||
* TOK_RP unary pn_kid: parenthesized expression
|
||||
* TOK_NAME, name pn_atom: name, string, or object atom
|
||||
* TOK_STRING, pn_op: JSOP_NAME, JSOP_STRING, or JSOP_OBJECT
|
||||
* TOK_OBJECT pn_op may be *ARG or *VAR with pn_slot >= 0
|
||||
* TOK_NUMBER dval pn_dval: double value of numeric literal
|
||||
* TOK_PRIMARY nullary pn_op: JSOp bytecode
|
||||
*/
|
||||
typedef enum JSParseNodeArity {
|
||||
PN_FUNC = -3,
|
||||
PN_LIST = -2,
|
||||
PN_TERNARY = 3,
|
||||
PN_BINARY = 2,
|
||||
PN_UNARY = 1,
|
||||
PN_NAME = -1,
|
||||
PN_NULLARY = 0
|
||||
} JSParseNodeArity;
|
||||
|
||||
struct JSParseNode {
|
||||
JSTokenType pn_type;
|
||||
JSTokenPos pn_pos;
|
||||
JSOp pn_op;
|
||||
ptrdiff_t pn_offset; /* first generated bytecode offset */
|
||||
JSParseNodeArity pn_arity;
|
||||
union {
|
||||
struct { /* TOK_FUNCTION node */
|
||||
JSFunction *fun; /* function object private data */
|
||||
JSParseNode *body; /* TOK_LC list of statements */
|
||||
uint32 tryCount; /* try statement count */
|
||||
} func;
|
||||
struct { /* list of next-linked nodes */
|
||||
JSParseNode *head; /* first node in list */
|
||||
JSParseNode **tail; /* ptr to ptr to last node in list */
|
||||
uint32 count; /* number of nodes in list */
|
||||
JSBool extra; /* extra comma flag for [1,2,,] */
|
||||
} list;
|
||||
struct { /* ternary: if, for(;;), ?: */
|
||||
JSParseNode *kid1; /* condition, discriminant, etc. */
|
||||
JSParseNode *kid2; /* then-part, case list, etc. */
|
||||
JSParseNode *kid3; /* else-part, default case, etc. */
|
||||
} ternary;
|
||||
struct { /* two kids if binary */
|
||||
JSParseNode *left;
|
||||
JSParseNode *right;
|
||||
jsval val; /* switch case value */
|
||||
} binary;
|
||||
struct { /* one kid if unary */
|
||||
JSParseNode *kid;
|
||||
jsint num; /* -1 or arg or local/sharp var num */
|
||||
} unary;
|
||||
struct { /* name, labeled statement, etc. */
|
||||
JSAtom *atom; /* name or label atom, null if slot */
|
||||
JSParseNode *expr; /* object or initializer */
|
||||
jsint slot; /* -1 or arg or local var slot */
|
||||
} name;
|
||||
jsdouble dval; /* aligned numeric literal value */
|
||||
} pn_u;
|
||||
JSParseNode *pn_next; /* here to align dval and pn_u on RISCs */
|
||||
};
|
||||
|
||||
#define pn_fun pn_u.func.fun
|
||||
#define pn_body pn_u.func.body
|
||||
#define pn_tryCount pn_u.func.tryCount
|
||||
#define pn_head pn_u.list.head
|
||||
#define pn_tail pn_u.list.tail
|
||||
#define pn_count pn_u.list.count
|
||||
#define pn_extra pn_u.list.extra
|
||||
#define pn_kid1 pn_u.ternary.kid1
|
||||
#define pn_kid2 pn_u.ternary.kid2
|
||||
#define pn_kid3 pn_u.ternary.kid3
|
||||
#define pn_left pn_u.binary.left
|
||||
#define pn_right pn_u.binary.right
|
||||
#define pn_val pn_u.binary.val
|
||||
#define pn_kid pn_u.unary.kid
|
||||
#define pn_num pn_u.unary.num
|
||||
#define pn_atom pn_u.name.atom
|
||||
#define pn_expr pn_u.name.expr
|
||||
#define pn_slot pn_u.name.slot
|
||||
#define pn_dval pn_u.dval
|
||||
|
||||
/*
|
||||
* Compute a pointer to the last JSParseNode element in a singly-linked list.
|
||||
* NB: list must be non-empty for correct PN_LAST usage!
|
||||
*/
|
||||
#define PN_LAST(list) \
|
||||
((JSParseNode *)((char *)(list)->pn_tail - offsetof(JSParseNode, pn_next)))
|
||||
|
||||
#define PN_INIT_LIST(list) \
|
||||
JS_BEGIN_MACRO \
|
||||
(list)->pn_head = NULL; \
|
||||
(list)->pn_tail = &(list)->pn_head; \
|
||||
(list)->pn_count = 0; \
|
||||
JS_END_MACRO
|
||||
|
||||
#define PN_INIT_LIST_1(list, pn) \
|
||||
JS_BEGIN_MACRO \
|
||||
(list)->pn_head = (pn); \
|
||||
(list)->pn_tail = &(pn)->pn_next; \
|
||||
(list)->pn_count = 1; \
|
||||
JS_END_MACRO
|
||||
|
||||
#define PN_APPEND(list, pn) \
|
||||
JS_BEGIN_MACRO \
|
||||
*(list)->pn_tail = (pn); \
|
||||
(list)->pn_tail = &(pn)->pn_next; \
|
||||
(list)->pn_count++; \
|
||||
JS_END_MACRO
|
||||
|
||||
/* New names to connote code generation in addition to parse tree gen. */
|
||||
#define js_CompileTokenStream js_Parse
|
||||
#define js_CompileFunctionBody js_ParseFunctionBody
|
||||
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
js_CompileTokenStream(JSContext *cx, JSObject *chain, JSTokenStream *ts,
|
||||
JSCodeGenerator *cg);
|
||||
|
||||
extern JSBool
|
||||
js_CompileFunctionBody(JSContext *cx, JSTokenStream *ts, JSFunction *fun);
|
||||
|
||||
/* XXXbe expose js_Parse{TokenStream,FunctionBody} that return trees? */
|
||||
extern JSBool
|
||||
js_FoldConstants(JSContext *cx, JSParseNode *pn);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsparse_h___ */
|
||||
1225
mozilla/js/src/jsprf.c
Normal file
1225
mozilla/js/src/jsprf.c
Normal file
File diff suppressed because it is too large
Load Diff
128
mozilla/js/src/jsprf.h
Normal file
128
mozilla/js/src/jsprf.h
Normal file
@@ -0,0 +1,128 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef jsprf_h___
|
||||
#define jsprf_h___
|
||||
|
||||
/*
|
||||
** API for PR printf like routines. Supports the following formats
|
||||
** %d - decimal
|
||||
** %u - unsigned decimal
|
||||
** %x - unsigned hex
|
||||
** %X - unsigned uppercase hex
|
||||
** %o - unsigned octal
|
||||
** %hd, %hu, %hx, %hX, %ho - 16-bit versions of above
|
||||
** %ld, %lu, %lx, %lX, %lo - 32-bit versions of above
|
||||
** %lld, %llu, %llx, %llX, %llo - 64 bit versions of above
|
||||
** %s - string
|
||||
** %c - character
|
||||
** %p - pointer (deals with machine dependent pointer size)
|
||||
** %f - float
|
||||
** %g - float
|
||||
*/
|
||||
#include "jstypes.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
/*
|
||||
** sprintf into a fixed size buffer. Guarantees that a NUL is at the end
|
||||
** of the buffer. Returns the length of the written output, NOT including
|
||||
** the NUL, or (JSUint32)-1 if an error occurs.
|
||||
*/
|
||||
JS_EXTERN_API(JSUint32) JS_snprintf(char *out, JSUint32 outlen, const char *fmt, ...);
|
||||
|
||||
/*
|
||||
** sprintf into a malloc'd buffer. Return a pointer to the malloc'd
|
||||
** buffer on success, NULL on failure. Call "JS_smprintf_free" to release
|
||||
** the memory returned.
|
||||
*/
|
||||
JS_EXTERN_API(char*) JS_smprintf(const char *fmt, ...);
|
||||
|
||||
/*
|
||||
** Free the memory allocated, for the caller, by JS_smprintf
|
||||
*/
|
||||
JS_EXTERN_API(void) JS_smprintf_free(char *mem);
|
||||
|
||||
/*
|
||||
** "append" sprintf into a malloc'd buffer. "last" is the last value of
|
||||
** the malloc'd buffer. sprintf will append data to the end of last,
|
||||
** growing it as necessary using realloc. If last is NULL, JS_sprintf_append
|
||||
** will allocate the initial string. The return value is the new value of
|
||||
** last for subsequent calls, or NULL if there is a malloc failure.
|
||||
*/
|
||||
JS_EXTERN_API(char*) JS_sprintf_append(char *last, const char *fmt, ...);
|
||||
|
||||
/*
|
||||
** sprintf into a function. The function "f" is called with a string to
|
||||
** place into the output. "arg" is an opaque pointer used by the stuff
|
||||
** function to hold any state needed to do the storage of the output
|
||||
** data. The return value is a count of the number of characters fed to
|
||||
** the stuff function, or (JSUint32)-1 if an error occurs.
|
||||
*/
|
||||
typedef JSIntn (*JSStuffFunc)(void *arg, const char *s, JSUint32 slen);
|
||||
|
||||
JS_EXTERN_API(JSUint32) JS_sxprintf(JSStuffFunc f, void *arg, const char *fmt, ...);
|
||||
|
||||
/*
|
||||
** va_list forms of the above.
|
||||
*/
|
||||
JS_EXTERN_API(JSUint32) JS_vsnprintf(char *out, JSUint32 outlen, const char *fmt, va_list ap);
|
||||
JS_EXTERN_API(char*) JS_vsmprintf(const char *fmt, va_list ap);
|
||||
JS_EXTERN_API(char*) JS_vsprintf_append(char *last, const char *fmt, va_list ap);
|
||||
JS_EXTERN_API(JSUint32) JS_vsxprintf(JSStuffFunc f, void *arg, const char *fmt, va_list ap);
|
||||
|
||||
/*
|
||||
***************************************************************************
|
||||
** FUNCTION: JS_sscanf
|
||||
** DESCRIPTION:
|
||||
** JS_sscanf() scans the input character string, performs data
|
||||
** conversions, and stores the converted values in the data objects
|
||||
** pointed to by its arguments according to the format control
|
||||
** string.
|
||||
**
|
||||
** JS_sscanf() behaves the same way as the sscanf() function in the
|
||||
** Standard C Library (stdio.h), with the following exceptions:
|
||||
** - JS_sscanf() handles the NSPR integer and floating point types,
|
||||
** such as JSInt16, JSInt32, JSInt64, and JSFloat64, whereas
|
||||
** sscanf() handles the standard C types like short, int, long,
|
||||
** and double.
|
||||
** - JS_sscanf() has no multibyte character support, while sscanf()
|
||||
** does.
|
||||
** INPUTS:
|
||||
** const char *buf
|
||||
** a character string holding the input to scan
|
||||
** const char *fmt
|
||||
** the format control string for the conversions
|
||||
** ...
|
||||
** variable number of arguments, each of them is a pointer to
|
||||
** a data object in which the converted value will be stored
|
||||
** OUTPUTS: none
|
||||
** RETURNS: JSInt32
|
||||
** The number of values converted and stored.
|
||||
** RESTRICTIONS:
|
||||
** Multibyte characters in 'buf' or 'fmt' are not allowed.
|
||||
***************************************************************************
|
||||
*/
|
||||
|
||||
JS_EXTERN_API(JSInt32) JS_sscanf(const char *buf, const char *fmt, ...);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsprf_h___ */
|
||||
131
mozilla/js/src/jsprhash.h
Normal file
131
mozilla/js/src/jsprhash.h
Normal file
@@ -0,0 +1,131 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef JSplhash_h___
|
||||
#define JSplhash_h___
|
||||
/*
|
||||
* API to portable hash table code.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include "jsprtypes.h"
|
||||
|
||||
JSPR_BEGIN_EXTERN_C
|
||||
|
||||
typedef struct JSPRHashEntry JSPRHashEntry;
|
||||
typedef struct JSPRHashTable JSPRHashTable;
|
||||
typedef JSPRUint32 JSPRHashNumber;
|
||||
#define JSPR_HASH_BITS 32
|
||||
typedef JSPRHashNumber (JSJS_DLL_CALLBACK *JSPRHashFunction)(const void *key);
|
||||
typedef JSPRIntn (JSJS_DLL_CALLBACK *JSPRHashComparator)(const void *v1, const void *v2);
|
||||
typedef JSPRIntn (JSJS_DLL_CALLBACK *JSPRHashEnumerator)(JSPRHashEntry *he, JSPRIntn i, void *arg);
|
||||
|
||||
/* Flag bits in JSPRHashEnumerator's return value */
|
||||
#define HT_ENUMERATE_NEXT 0 /* continue enumerating entries */
|
||||
#define HT_ENUMERATE_STOP 1 /* stop enumerating entries */
|
||||
#define HT_ENUMERATE_REMOVE 2 /* remove and free the current entry */
|
||||
#define HT_ENUMERATE_UNHASH 4 /* just unhash the current entry */
|
||||
|
||||
typedef struct JSPRHashAllocOps {
|
||||
void * (JSJS_DLL_CALLBACK *allocTable)(void *pool, JSPRSize size);
|
||||
void (JSJS_DLL_CALLBACK *freeTable)(void *pool, void *item);
|
||||
JSPRHashEntry * (JSJS_DLL_CALLBACK *allocEntry)(void *pool, const void *key);
|
||||
void (JSJS_DLL_CALLBACK *freeEntry)(void *pool, JSPRHashEntry *he, JSPRUintn flag);
|
||||
} JSPRHashAllocOps;
|
||||
|
||||
#define HT_FREE_VALUE 0 /* just free the entry's value */
|
||||
#define HT_FREE_ENTRY 1 /* free value and entire entry */
|
||||
|
||||
struct JSPRHashEntry {
|
||||
JSPRHashEntry *next; /* hash chain linkage */
|
||||
JSPRHashNumber keyHash; /* key hash function result */
|
||||
const void *key; /* ptr to opaque key */
|
||||
void *value; /* ptr to opaque value */
|
||||
};
|
||||
|
||||
struct JSPRHashTable {
|
||||
JSPRHashEntry **buckets; /* vector of hash buckets */
|
||||
JSPRUint32 nentries; /* number of entries in table */
|
||||
JSPRUint32 shift; /* multiplicative hash shift */
|
||||
JSPRHashFunction keyHash; /* key hash function */
|
||||
JSPRHashComparator keyCompare; /* key comparison function */
|
||||
JSPRHashComparator valueCompare; /* value comparison function */
|
||||
JSPRHashAllocOps *allocOps; /* allocation operations */
|
||||
void *allocPriv; /* allocation private data */
|
||||
#ifdef HASHMETER
|
||||
JSPRUint32 nlookups; /* total number of lookups */
|
||||
JSPRUint32 nsteps; /* number of hash chains traversed */
|
||||
JSPRUint32 ngrows; /* number of table expansions */
|
||||
JSPRUint32 nshrinks; /* number of table contractions */
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* Create a new hash table.
|
||||
* If allocOps is null, use default allocator ops built on top of malloc().
|
||||
*/
|
||||
JSJS_EXTERN_API(JSPRHashTable *)
|
||||
JSPR_NewHashTable(JSPRUint32 n, JSPRHashFunction keyHash,
|
||||
JSPRHashComparator keyCompare, JSPRHashComparator valueCompare,
|
||||
JSPRHashAllocOps *allocOps, void *allocPriv);
|
||||
|
||||
JSJS_EXTERN_API(void)
|
||||
JSPR_HashTableDestroy(JSPRHashTable *ht);
|
||||
|
||||
/* Low level access methods */
|
||||
JSJS_EXTERN_API(JSPRHashEntry **)
|
||||
JSPR_HashTableRawLookup(JSPRHashTable *ht, JSPRHashNumber keyHash, const void *key);
|
||||
|
||||
JSJS_EXTERN_API(JSPRHashEntry *)
|
||||
JSPR_HashTableRawAdd(JSPRHashTable *ht, JSPRHashEntry **hep, JSPRHashNumber keyHash,
|
||||
const void *key, void *value);
|
||||
|
||||
JSJS_EXTERN_API(void)
|
||||
JSPR_HashTableRawRemove(JSPRHashTable *ht, JSPRHashEntry **hep, JSPRHashEntry *he);
|
||||
|
||||
/* Higher level access methods */
|
||||
JSJS_EXTERN_API(JSPRHashEntry *)
|
||||
JSPR_HashTableAdd(JSPRHashTable *ht, const void *key, void *value);
|
||||
|
||||
JSJS_EXTERN_API(JSPRBool)
|
||||
JSPR_HashTableRemove(JSPRHashTable *ht, const void *key);
|
||||
|
||||
JSJS_EXTERN_API(JSPRIntn)
|
||||
JSPR_HashTableEnumerateEntries(JSPRHashTable *ht, JSPRHashEnumerator f, void *arg);
|
||||
|
||||
JSJS_EXTERN_API(void *)
|
||||
JSPR_HashTableLookup(JSPRHashTable *ht, const void *key);
|
||||
|
||||
JSJS_EXTERN_API(JSPRIntn)
|
||||
JSPR_HashTableDump(JSPRHashTable *ht, JSPRHashEnumerator dump, FILE *fp);
|
||||
|
||||
/* General-purpose C string hash function. */
|
||||
JSJS_EXTERN_API(JSPRHashNumber)
|
||||
JSPR_HashString(const void *key);
|
||||
|
||||
/* Compare strings using strcmp(), return true if equal. */
|
||||
JSJS_EXTERN_API(int)
|
||||
JSPR_CompareStrings(const void *v1, const void *v2);
|
||||
|
||||
/* Stub function just returns v1 == v2 */
|
||||
JSJS_EXTERN_API(JSPRIntn)
|
||||
JSPR_CompareValues(const void *v1, const void *v2);
|
||||
|
||||
JSPR_END_EXTERN_C
|
||||
|
||||
#endif /* JSplhash_h___ */
|
||||
157
mozilla/js/src/jsprvtd.h
Normal file
157
mozilla/js/src/jsprvtd.h
Normal file
@@ -0,0 +1,157 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef jsprvtd_h___
|
||||
#define jsprvtd_h___
|
||||
/*
|
||||
* JS private typename definitions.
|
||||
*
|
||||
* This header is included only in other .h files, for convenience and for
|
||||
* simplicity of type naming. The alternative for structures is to use tags,
|
||||
* which are named the same as their typedef names (legal in C/C++, and less
|
||||
* noisy than suffixing the typedef name with "Struct" or "Str"). Instead,
|
||||
* all .h files that include this file may use the same typedef name, whether
|
||||
* declaring a pointer to struct type, or defining a member of struct type.
|
||||
*
|
||||
* A few fundamental scalar types are defined here too. Neither the scalar
|
||||
* nor the struct typedefs should change much, therefore the nearly-global
|
||||
* make dependency induced by this file should not prove painful.
|
||||
*/
|
||||
|
||||
#include "jspubtd.h"
|
||||
|
||||
/* Scalar typedefs. */
|
||||
typedef uint8 jsbytecode;
|
||||
typedef uint8 jssrcnote;
|
||||
typedef uint32 jsatomid;
|
||||
|
||||
/* Struct typedefs. */
|
||||
typedef struct JSCodeGenerator JSCodeGenerator;
|
||||
typedef struct JSGCThing JSGCThing;
|
||||
typedef struct JSParseNode JSParseNode;
|
||||
typedef struct JSSharpObjectMap JSSharpObjectMap;
|
||||
typedef struct JSToken JSToken;
|
||||
typedef struct JSTokenPos JSTokenPos;
|
||||
typedef struct JSTokenPtr JSTokenPtr;
|
||||
typedef struct JSTokenStream JSTokenStream;
|
||||
typedef struct JSTreeContext JSTreeContext;
|
||||
typedef struct JSTryNote JSTryNote;
|
||||
|
||||
/* Friend "Advanced API" typedefs. */
|
||||
typedef struct JSAtom JSAtom;
|
||||
typedef struct JSAtomList JSAtomList;
|
||||
typedef struct JSAtomListElement JSAtomListElement;
|
||||
typedef struct JSAtomMap JSAtomMap;
|
||||
typedef struct JSAtomState JSAtomState;
|
||||
typedef struct JSCodeSpec JSCodeSpec;
|
||||
typedef struct JSPrinter JSPrinter;
|
||||
typedef struct JSRegExp JSRegExp;
|
||||
typedef struct JSRegExpStatics JSRegExpStatics;
|
||||
typedef struct JSScope JSScope;
|
||||
typedef struct JSScopeOps JSScopeOps;
|
||||
typedef struct JSScopeProperty JSScopeProperty;
|
||||
typedef struct JSStackFrame JSStackFrame;
|
||||
typedef struct JSSubString JSSubString;
|
||||
typedef struct JSSymbol JSSymbol;
|
||||
|
||||
/* "Friend" types used by jscntxt.h and jsdbgapi.h. */
|
||||
typedef enum JSTrapStatus {
|
||||
JSTRAP_ERROR,
|
||||
JSTRAP_CONTINUE,
|
||||
JSTRAP_RETURN,
|
||||
JSTRAP_THROW,
|
||||
JSTRAP_LIMIT
|
||||
} JSTrapStatus;
|
||||
|
||||
#ifndef CRT_CALL
|
||||
#ifdef XP_OS2
|
||||
#define CRT_CALL _Optlink
|
||||
#else
|
||||
#define CRT_CALL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef JSTrapStatus
|
||||
(* CRT_CALL JSTrapHandler)(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
jsval *rval, void *closure);
|
||||
|
||||
typedef JSBool
|
||||
(* CRT_CALL JSWatchPointHandler)(JSContext *cx, JSObject *obj, jsval id,
|
||||
jsval old, jsval *newp, void *closure);
|
||||
|
||||
/* called just after script creation */
|
||||
typedef void
|
||||
(* CRT_CALL JSNewScriptHook)(JSContext *cx,
|
||||
const char *filename, /* URL of script */
|
||||
uintN lineno, /* line script starts */
|
||||
JSScript *script,
|
||||
JSFunction *fun,
|
||||
void *callerdata);
|
||||
|
||||
/* called just before script destruction */
|
||||
typedef void
|
||||
(* CRT_CALL JSDestroyScriptHook)(JSContext *cx,
|
||||
JSScript *script,
|
||||
void *callerdata);
|
||||
|
||||
typedef void
|
||||
(* CRT_CALL JSSourceHandler)(const char *filename, uintN lineno,
|
||||
jschar *str, size_t length,
|
||||
void **listenerTSData, void *closure);
|
||||
|
||||
/*
|
||||
* This hook captures high level script execution and function calls
|
||||
* (JS or native).
|
||||
* It is used by JS_SetExecuteHook to hook top level scripts and by
|
||||
* JS_SetCallHook to hook function calls.
|
||||
* It will get called twice per script or function call:
|
||||
* just before execution begins and just after it finishes. In both cases
|
||||
* the 'current' frame is that of the executing code.
|
||||
*
|
||||
* The 'before' param is JS_TRUE for the hook invocation before the execution
|
||||
* and JS_FALSE for the invocation after the code has run.
|
||||
*
|
||||
* The 'ok' param is significant only on the post execution invocation to
|
||||
* signify whether or not the code completed 'normally'.
|
||||
*
|
||||
* The 'closure' param is as passed to JS_SetExecuteHook or JS_SetCallHook
|
||||
* for the 'before'invocation, but is whatever value is returned from that
|
||||
* invocation for the 'after' invocation. Thus, the hook implementor *could*
|
||||
* allocate a stucture in the 'before' invocation and return a pointer
|
||||
* to that structure. The pointer would then be handed to the hook for
|
||||
* the 'after' invocation. Alternately, the 'before' could just return the
|
||||
* same value as in 'closure' to cause the 'after' invocation to be called
|
||||
* with the same 'closure' value as the 'before'.
|
||||
*
|
||||
* Returning NULL in the 'before' hook will cause the 'after' hook to
|
||||
* NOT be called.
|
||||
*/
|
||||
|
||||
typedef void *
|
||||
(* CRT_CALL JSInterpreterHook)(JSContext *cx, JSStackFrame *fp, JSBool before,
|
||||
JSBool *ok, void *closure);
|
||||
|
||||
typedef void
|
||||
(* CRT_CALL JSObjectHook)(JSContext *cx, JSObject *obj, JSBool isNew,
|
||||
void *closure);
|
||||
|
||||
typedef JSBool
|
||||
(* CRT_CALL JSDebugErrorHook)(JSContext *cx, const char *message,
|
||||
JSErrorReport *report, void *closure);
|
||||
|
||||
#endif /* jsprvtd_h___ */
|
||||
243
mozilla/js/src/jspubtd.h
Normal file
243
mozilla/js/src/jspubtd.h
Normal file
@@ -0,0 +1,243 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef jspubtd_h___
|
||||
#define jspubtd_h___
|
||||
/*
|
||||
* JS public API typedefs.
|
||||
*/
|
||||
#include "jstypes.h"
|
||||
#include "jscompat.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
/* Scalar typedefs. */
|
||||
typedef uint16 jschar;
|
||||
typedef int32 jsint;
|
||||
typedef uint32 jsuint;
|
||||
typedef float64 jsdouble;
|
||||
typedef jsword jsval;
|
||||
typedef jsword jsid;
|
||||
typedef jsword jsrefcount;
|
||||
|
||||
typedef enum JSVersion {
|
||||
JSVERSION_1_0 = 100,
|
||||
JSVERSION_1_1 = 110,
|
||||
JSVERSION_1_2 = 120,
|
||||
JSVERSION_1_3 = 130,
|
||||
JSVERSION_1_4 = 140,
|
||||
JSVERSION_DEFAULT = 0,
|
||||
JSVERSION_UNKNOWN = -1
|
||||
} JSVersion;
|
||||
|
||||
#define JSVERSION_IS_ECMA(version) \
|
||||
((version) == JSVERSION_DEFAULT || (version) >= JSVERSION_1_3)
|
||||
|
||||
/* Result of typeof operator enumeration. */
|
||||
typedef enum JSType {
|
||||
JSTYPE_VOID, /* undefined */
|
||||
JSTYPE_OBJECT, /* object */
|
||||
JSTYPE_FUNCTION, /* function */
|
||||
JSTYPE_STRING, /* string */
|
||||
JSTYPE_NUMBER, /* number */
|
||||
JSTYPE_BOOLEAN, /* boolean */
|
||||
JSTYPE_LIMIT
|
||||
} JSType;
|
||||
|
||||
/* JSObjectOps.checkAccess mode enumeration. */
|
||||
typedef enum JSAccessMode {
|
||||
JSACC_PROTO,
|
||||
JSACC_PARENT,
|
||||
JSACC_IMPORT,
|
||||
JSACC_WATCH,
|
||||
JSACC_LIMIT
|
||||
} JSAccessMode;
|
||||
|
||||
/*
|
||||
* This enum type is used to control the behavior of a JSObject property
|
||||
* iterator function that has type JSNewEnumerate.
|
||||
*/
|
||||
typedef enum JSIterateOp {
|
||||
JSENUMERATE_INIT, /* Create new iterator state */
|
||||
JSENUMERATE_NEXT, /* Iterate once */
|
||||
JSENUMERATE_DESTROY /* Destroy iterator state */
|
||||
} JSIterateOp;
|
||||
|
||||
/* Struct typedefs. */
|
||||
typedef struct JSClass JSClass;
|
||||
typedef struct JSConstDoubleSpec JSConstDoubleSpec;
|
||||
typedef struct JSContext JSContext;
|
||||
typedef struct JSErrorReport JSErrorReport;
|
||||
typedef struct JSFunction JSFunction;
|
||||
typedef struct JSFunctionSpec JSFunctionSpec;
|
||||
typedef struct JSIdArray JSIdArray;
|
||||
typedef struct JSProperty JSProperty;
|
||||
typedef struct JSPropertySpec JSPropertySpec;
|
||||
typedef struct JSObject JSObject;
|
||||
typedef struct JSObjectMap JSObjectMap;
|
||||
typedef struct JSObjectOps JSObjectOps;
|
||||
typedef struct JSRuntime JSRuntime;
|
||||
typedef struct JSRuntime JSTaskState; /* XXX deprecated name */
|
||||
typedef struct JSScript JSScript;
|
||||
typedef struct JSString JSString;
|
||||
typedef struct JSXDRState JSXDRState;
|
||||
typedef struct JSExceptionState JSExceptionState;
|
||||
|
||||
#ifndef CRT_CALL
|
||||
#ifdef XP_OS2
|
||||
#define CRT_CALL _Optlink
|
||||
#else
|
||||
#define CRT_CALL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* JSClass (and JSObjectOps where appropriate) function pointer typedefs. */
|
||||
|
||||
typedef JSBool
|
||||
(* CRT_CALL JSPropertyOp)(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
||||
|
||||
/*
|
||||
* This function type is used for callbacks that enumerate the properties of a
|
||||
* JSObject. The behavior depends on the value of enum_op:
|
||||
*
|
||||
* JSENUMERATE_INIT - A new, opaque iterator state should be allocated and
|
||||
* stored in *statep. (You can use PRIVATE_TO_JSVAL() to store
|
||||
* a pointer in *statep). The number of properties that will be
|
||||
* enumerated should be returned as an integer jsval in *idp, if idp
|
||||
* is non-NULL.
|
||||
* JSENUMERATE_NEXT - A previously allocated opaque iterator state is passed
|
||||
* in via statep. Return the next jsid in the iteration using *idp.
|
||||
* The opaque iterator state pointed at by statep is destroyed and
|
||||
* *statep is set to JSVAL_NULL if there are no properties left to
|
||||
* enumerate.
|
||||
* JSENUMERATE_DESTROY - Destroy the opaque iterator previous allocated by
|
||||
* a call to this function with enum_op set to JSENUMERATE_INIT.
|
||||
*
|
||||
* The return value is always used to indicate success, with a value of JS_FALSE
|
||||
* for failure.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* CRT_CALL JSNewEnumerateOp)(JSContext *cx, JSObject *obj,
|
||||
JSIterateOp enum_op,
|
||||
jsval *statep, jsid *idp);
|
||||
|
||||
typedef JSBool
|
||||
(* CRT_CALL JSEnumerateOp)(JSContext *cx, JSObject *obj);
|
||||
|
||||
typedef JSBool
|
||||
(* CRT_CALL JSResolveOp)(JSContext *cx, JSObject *obj, jsval id);
|
||||
|
||||
typedef JSBool
|
||||
(* CRT_CALL JSNewResolveOp)(JSContext *cx, JSObject *obj, jsval id, uintN flags,
|
||||
JSObject **objp);
|
||||
|
||||
typedef JSBool
|
||||
(* CRT_CALL JSConvertOp)(JSContext *cx, JSObject *obj, JSType type, jsval *vp);
|
||||
|
||||
typedef void
|
||||
(* CRT_CALL JSFinalizeOp)(JSContext *cx, JSObject *obj);
|
||||
|
||||
typedef JSObjectOps *
|
||||
(* CRT_CALL JSGetObjectOps)(JSContext *cx, JSClass *clasp);
|
||||
|
||||
typedef JSBool
|
||||
(* CRT_CALL JSCheckAccessOp)(JSContext *cx, JSObject *obj, jsval id,
|
||||
JSAccessMode mode, jsval *vp);
|
||||
|
||||
typedef JSBool
|
||||
(* CRT_CALL JSXDRObjectOp)(JSXDRState *xdr, JSObject **objp);
|
||||
|
||||
typedef JSBool
|
||||
(* CRT_CALL JSHasInstanceOp)(JSContext *cx, JSObject *obj, jsval v,
|
||||
JSBool *bp);
|
||||
|
||||
/* JSObjectOps function pointer typedefs. */
|
||||
|
||||
typedef JSObjectMap *
|
||||
(* CRT_CALL JSNewObjectMapOp)(JSContext *cx, jsrefcount nrefs,
|
||||
JSObjectOps *ops, JSClass *clasp,
|
||||
JSObject *obj);
|
||||
|
||||
typedef void
|
||||
(* CRT_CALL JSObjectMapOp)(JSContext *cx, JSObjectMap *map);
|
||||
|
||||
typedef JSBool
|
||||
(* CRT_CALL JSLookupPropOp)(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSObject **objp, JSProperty **propp
|
||||
#if defined JS_THREADSAFE && defined DEBUG
|
||||
, const char *file, uintN line
|
||||
#endif
|
||||
);
|
||||
|
||||
typedef JSBool
|
||||
(* CRT_CALL JSDefinePropOp)(JSContext *cx, JSObject *obj, jsid id, jsval value,
|
||||
JSPropertyOp getter, JSPropertyOp setter,
|
||||
uintN attrs, JSProperty **propp);
|
||||
|
||||
typedef JSBool
|
||||
(* CRT_CALL JSPropertyIdOp)(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
|
||||
|
||||
typedef JSBool
|
||||
(* CRT_CALL JSAttributesOp)(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSProperty *prop, uintN *attrsp);
|
||||
|
||||
typedef JSBool
|
||||
(* CRT_CALL JSCheckAccessIdOp)(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSAccessMode mode, jsval *vp, uintN *attrsp);
|
||||
|
||||
typedef JSObject *
|
||||
(* CRT_CALL JSObjectOp)(JSContext *cx, JSObject *obj);
|
||||
|
||||
typedef void
|
||||
(* CRT_CALL JSPropertyRefOp)(JSContext *cx, JSObject *obj, JSProperty *prop);
|
||||
|
||||
/* Typedef for native functions called by the JS VM. */
|
||||
|
||||
typedef JSBool
|
||||
(* CRT_CALL JSNative)(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval);
|
||||
|
||||
/* Callbacks and their arguments. */
|
||||
|
||||
typedef enum JSGCStatus {
|
||||
JSGC_BEGIN,
|
||||
JSGC_END
|
||||
} JSGCStatus;
|
||||
|
||||
typedef JSBool
|
||||
(* CRT_CALL JSGCCallback)(JSContext *cx, JSGCStatus status);
|
||||
|
||||
typedef JSBool
|
||||
(* CRT_CALL JSBranchCallback)(JSContext *cx, JSScript *script);
|
||||
|
||||
typedef void
|
||||
(* CRT_CALL JSErrorReporter)(JSContext *cx, const char *message,
|
||||
JSErrorReport *report);
|
||||
|
||||
typedef struct JSErrorFormatString {
|
||||
const char *format;
|
||||
const uintN argCount;
|
||||
} JSErrorFormatString;
|
||||
|
||||
typedef const JSErrorFormatString *
|
||||
(* CRT_CALL JSErrorCallback)(void *userRef, const char *locale,
|
||||
const uintN errorNumber);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jspubtd_h___ */
|
||||
3318
mozilla/js/src/jsregexp.c
Normal file
3318
mozilla/js/src/jsregexp.c
Normal file
File diff suppressed because it is too large
Load Diff
107
mozilla/js/src/jsregexp.h
Normal file
107
mozilla/js/src/jsregexp.h
Normal file
@@ -0,0 +1,107 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef jsregexp_h___
|
||||
#define jsregexp_h___
|
||||
/*
|
||||
* JS regular expression interface.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include "jspubtd.h"
|
||||
#include "jsstr.h"
|
||||
|
||||
struct JSRegExpStatics {
|
||||
JSString *input; /* input string to match (perl $_, GC root) */
|
||||
JSBool multiline; /* whether input contains newlines (perl $*) */
|
||||
uintN parenCount; /* number of valid elements in parens[] */
|
||||
uintN moreLength; /* number of allocated elements in moreParens */
|
||||
JSSubString parens[9]; /* last set of parens matched (perl $1, $2) */
|
||||
JSSubString *moreParens; /* null or realloc'd vector for $10, etc. */
|
||||
JSSubString lastMatch; /* last string matched (perl $&) */
|
||||
JSSubString lastParen; /* last paren matched (perl $+) */
|
||||
JSSubString leftContext; /* input to left of last match (perl $`) */
|
||||
JSSubString rightContext; /* input to right of last match (perl $') */
|
||||
};
|
||||
|
||||
/*
|
||||
* This macro is safe because moreParens is guaranteed to be allocated and big
|
||||
* enough to hold parenCount, or else be null when parenCount is 0.
|
||||
*/
|
||||
#define REGEXP_PAREN_SUBSTRING(res, num) \
|
||||
(((jsuint)(num) < (jsuint)(res)->parenCount) \
|
||||
? ((jsuint)(num) < 9) \
|
||||
? &(res)->parens[num] \
|
||||
: &(res)->moreParens[(num) - 9] \
|
||||
: &js_EmptySubString)
|
||||
|
||||
struct JSRegExp {
|
||||
JSString *source; /* locked source string, sans // */
|
||||
size_t length; /* program length in bytes */
|
||||
size_t lastIndex; /* index after last match, for //g iterator */
|
||||
uintN parenCount; /* number of parenthesized submatches */
|
||||
uint8 flags; /* flags, see jsapi.h */
|
||||
jsbytecode program[1]; /* regular expression bytecode */
|
||||
};
|
||||
|
||||
extern JSRegExp *
|
||||
js_NewRegExp(JSContext *cx, JSString *str, uintN flags);
|
||||
|
||||
extern JSRegExp *
|
||||
js_NewRegExpOpt(JSContext *cx, JSString *str, JSString *opt);
|
||||
|
||||
extern void
|
||||
js_DestroyRegExp(JSContext *cx, JSRegExp *re);
|
||||
|
||||
/*
|
||||
* Execute re on input str at *indexp, returning null in *rval on mismatch.
|
||||
* On match, return true if test is true, otherwise return an array object.
|
||||
* Update *indexp and cx->regExpStatics always on match.
|
||||
*/
|
||||
extern JSBool
|
||||
js_ExecuteRegExp(JSContext *cx, JSRegExp *re, JSString *str, size_t *indexp,
|
||||
JSBool test, jsval *rval);
|
||||
|
||||
/*
|
||||
* These two add and remove GC roots, respectively, so their calls must be
|
||||
* well-ordered.
|
||||
*/
|
||||
extern JSBool
|
||||
js_InitRegExpStatics(JSContext *cx, JSRegExpStatics *res);
|
||||
|
||||
extern void
|
||||
js_FreeRegExpStatics(JSContext *cx, JSRegExpStatics *res);
|
||||
|
||||
#define JSVAL_IS_REGEXP(cx, v) \
|
||||
(JSVAL_IS_OBJECT(v) && JSVAL_TO_OBJECT(v) && \
|
||||
OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == &js_RegExpClass)
|
||||
|
||||
extern JSClass js_RegExpClass;
|
||||
|
||||
extern JSObject *
|
||||
js_InitRegExpClass(JSContext *cx, JSObject *obj);
|
||||
|
||||
/*
|
||||
* Create a new RegExp object.
|
||||
*/
|
||||
extern JSObject *
|
||||
js_NewRegExpObject(JSContext *cx, jschar *chars, size_t length, uintN flags);
|
||||
|
||||
extern JSBool
|
||||
js_XDRRegExp(JSXDRState *xdr, JSObject **objp);
|
||||
|
||||
#endif /* jsregexp_h___ */
|
||||
1194
mozilla/js/src/jsscan.c
Normal file
1194
mozilla/js/src/jsscan.c
Normal file
File diff suppressed because it is too large
Load Diff
264
mozilla/js/src/jsscan.h
Normal file
264
mozilla/js/src/jsscan.h
Normal file
@@ -0,0 +1,264 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef jsscan_h___
|
||||
#define jsscan_h___
|
||||
/*
|
||||
* JS lexical scanner interface.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#ifdef JSFILE
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#include "jsopcode.h"
|
||||
#include "jsprvtd.h"
|
||||
#include "jspubtd.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
typedef enum JSTokenType {
|
||||
TOK_ERROR = -1, /* well-known as the only code < EOF */
|
||||
TOK_EOF = 0, /* end of file */
|
||||
TOK_EOL = 1, /* end of line */
|
||||
TOK_SEMI = 2, /* semicolon */
|
||||
TOK_LB = 3, TOK_RB = 4, /* left and right brackets */
|
||||
TOK_LC = 5, TOK_RC = 6, /* left and right curlies (braces) */
|
||||
TOK_LP = 7, TOK_RP = 8, /* left and right parentheses */
|
||||
TOK_COMMA = 9, /* comma operator */
|
||||
TOK_ASSIGN = 10, /* assignment ops (= += -= etc.) */
|
||||
TOK_HOOK = 11, TOK_COLON = 12, /* conditional (?:) */
|
||||
TOK_OR = 13, /* logical or (||) */
|
||||
TOK_AND = 14, /* logical and (&&) */
|
||||
TOK_BITOR = 15, /* bitwise-or (|) */
|
||||
TOK_BITXOR = 16, /* bitwise-xor (^) */
|
||||
TOK_BITAND = 17, /* bitwise-and (&) */
|
||||
TOK_EQOP = 18, /* equality ops (== !=) */
|
||||
TOK_RELOP = 19, /* relational ops (< <= > >=) */
|
||||
TOK_SHOP = 20, /* shift ops (<< >> >>>) */
|
||||
TOK_PLUS = 21, /* plus */
|
||||
TOK_MINUS = 22, /* minus */
|
||||
TOK_STAR = 23, TOK_DIVOP = 24, /* multiply/divide ops (* / %) */
|
||||
TOK_UNARYOP = 25, /* unary prefix operator */
|
||||
TOK_INC = 26, TOK_DEC = 27, /* increment/decrement (++ --) */
|
||||
TOK_DOT = 28, /* member operator (.) */
|
||||
TOK_NAME = 29, /* identifier */
|
||||
TOK_NUMBER = 30, /* numeric constant */
|
||||
TOK_STRING = 31, /* string constant */
|
||||
TOK_OBJECT = 32, /* RegExp or other object constant */
|
||||
TOK_PRIMARY = 33, /* true, false, null, this, super */
|
||||
TOK_FUNCTION = 34, /* function keyword */
|
||||
TOK_EXPORT = 35, /* export keyword */
|
||||
TOK_IMPORT = 36, /* import keyword */
|
||||
TOK_IF = 37, /* if keyword */
|
||||
TOK_ELSE = 38, /* else keyword */
|
||||
TOK_SWITCH = 39, /* switch keyword */
|
||||
TOK_CASE = 40, /* case keyword */
|
||||
TOK_DEFAULT = 41, /* default keyword */
|
||||
TOK_WHILE = 42, /* while keyword */
|
||||
TOK_DO = 43, /* do keyword */
|
||||
TOK_FOR = 44, /* for keyword */
|
||||
TOK_BREAK = 45, /* break keyword */
|
||||
TOK_CONTINUE = 46, /* continue keyword */
|
||||
TOK_IN = 47, /* in keyword */
|
||||
TOK_VAR = 48, /* var keyword */
|
||||
TOK_WITH = 49, /* with keyword */
|
||||
TOK_RETURN = 50, /* return keyword */
|
||||
TOK_NEW = 51, /* new keyword */
|
||||
TOK_DELETE = 52, /* delete keyword */
|
||||
TOK_DEFSHARP = 53, /* #n= for object/array initializers */
|
||||
TOK_USESHARP = 54, /* #n# for object/array initializers */
|
||||
TOK_TRY = 55, /* try keyword */
|
||||
TOK_CATCH = 56, /* catch keyword */
|
||||
TOK_FINALLY = 57, /* finally keyword */
|
||||
TOK_THROW = 58, /* throw keyword */
|
||||
TOK_INSTANCEOF = 59, /* instanceof keyword */
|
||||
TOK_DEBUGGER = 60, /* debugger keyword */
|
||||
TOK_RESERVED, /* reserved keywords */
|
||||
TOK_LIMIT /* domain size */
|
||||
} JSTokenType;
|
||||
|
||||
#define IS_PRIMARY_TOKEN(tt) \
|
||||
((uintN)((tt) - TOK_NAME) <= (uintN)(TOK_PRIMARY - TOK_NAME))
|
||||
|
||||
struct JSTokenPtr {
|
||||
uint16 index; /* index of char in physical line */
|
||||
uint16 lineno; /* physical line number */
|
||||
};
|
||||
|
||||
struct JSTokenPos {
|
||||
JSTokenPtr begin; /* first character and line of token */
|
||||
JSTokenPtr end; /* index 1 past last char, last line */
|
||||
};
|
||||
|
||||
struct JSToken {
|
||||
JSTokenType type; /* char value or above enumerator */
|
||||
JSTokenPos pos; /* token position in file */
|
||||
jschar *ptr; /* beginning of token in line buffer */
|
||||
union {
|
||||
struct {
|
||||
JSOp op; /* operator, for minimal parser */
|
||||
JSAtom *atom; /* atom table entry */
|
||||
} s;
|
||||
jsdouble dval; /* floating point number */
|
||||
} u;
|
||||
};
|
||||
|
||||
#define t_op u.s.op
|
||||
#define t_atom u.s.atom
|
||||
#define t_dval u.dval
|
||||
|
||||
typedef struct JSTokenBuf {
|
||||
jschar *base; /* base of line or stream buffer */
|
||||
jschar *limit; /* limit for quick bounds check */
|
||||
jschar *ptr; /* next char to get, or slot to use */
|
||||
} JSTokenBuf;
|
||||
|
||||
#define JS_LINE_LIMIT 256 /* logical line buffer size limit --
|
||||
physical line length is unlimited */
|
||||
|
||||
struct JSTokenStream {
|
||||
JSToken token; /* last token scanned */
|
||||
JSToken pushback; /* pushed-back already-scanned token */
|
||||
uintN lineno; /* current line number */
|
||||
uintN ungetpos; /* next free char slot in ungetbuf */
|
||||
jschar ungetbuf[4]; /* at most 4, for \uXXXX lookahead */
|
||||
uintN flags; /* flags -- see below */
|
||||
ptrdiff_t linelen; /* physical linebuf segment length */
|
||||
ptrdiff_t linepos; /* linebuf offset in physical line */
|
||||
JSTokenBuf linebuf; /* line buffer for diagnostics */
|
||||
JSTokenBuf userbuf; /* user input buffer if !file */
|
||||
JSTokenBuf tokenbuf; /* current token string buffer */
|
||||
const char *filename; /* input filename or null */
|
||||
#ifdef JSFILE
|
||||
FILE *file; /* stdio stream if reading from file */
|
||||
#endif
|
||||
JSPrincipals *principals; /* principals associated with given input */
|
||||
JSSourceHandler listener; /* callback for source; eg debugger */
|
||||
void *listenerData; /* listener 'this' data */
|
||||
void *listenerTSData;/* listener data for this TokenStream */
|
||||
};
|
||||
|
||||
/* JSTokenStream flags */
|
||||
#define TSF_ERROR 0x01 /* fatal error while scanning */
|
||||
#define TSF_EOF 0x02 /* hit end of file */
|
||||
#define TSF_NEWLINES 0x04 /* tokenize newlines */
|
||||
#define TSF_REGEXP 0x08 /* looking for a regular expression */
|
||||
#define TSF_INTERACTIVE 0x10 /* interactive parsing mode */
|
||||
#define TSF_NLFLAG 0x20 /* last linebuf ended with \n */
|
||||
#define TSF_CRFLAG 0x40 /* linebuf would have ended with \r */
|
||||
#define TSF_BADCOMPILE 0x80 /* compile failed, stop throwing exns */
|
||||
|
||||
/*
|
||||
* At most one non-EOF token can be pushed back onto a TokenStream between
|
||||
* Get or successful Match operations. These macros manipulate the pushback
|
||||
* token to clear it when changing scanning modes (upon initialzation, after
|
||||
* errors, or between newline-sensitive and insensitive states).
|
||||
*/
|
||||
#define CLEAR_PUSHBACK(ts) ((ts)->pushback.type = TOK_EOF)
|
||||
#define SCAN_NEWLINES(ts) ((ts)->flags |= TSF_NEWLINES)
|
||||
#define HIDE_NEWLINES(ts) \
|
||||
JS_BEGIN_MACRO \
|
||||
(ts)->flags &= ~TSF_NEWLINES; \
|
||||
if ((ts)->pushback.type == TOK_EOL) \
|
||||
(ts)->pushback.type = TOK_EOF; \
|
||||
JS_END_MACRO
|
||||
|
||||
/* Clear ts member that might point above a released cx->tempPool mark. */
|
||||
#define RESET_TOKENBUF(ts) ((ts)->tokenbuf.base = (ts)->tokenbuf.limit = NULL)
|
||||
|
||||
/*
|
||||
* Create a new token stream, either from an input buffer or from a file.
|
||||
* Return null on file-open or memory-allocation failure.
|
||||
*
|
||||
* NB: All of js_New{,Buffer,File}TokenStream() return a pointer to transient
|
||||
* memory in the current context's temp pool. This memory is deallocated via
|
||||
* JS_ARENA_RELEASE() after parsing is finished.
|
||||
*/
|
||||
extern JSTokenStream *
|
||||
js_NewTokenStream(JSContext *cx, const jschar *base, size_t length,
|
||||
const char *filename, uintN lineno, JSPrincipals *principals);
|
||||
|
||||
extern JS_FRIEND_API(JSTokenStream *)
|
||||
js_NewBufferTokenStream(JSContext *cx, const jschar *base, size_t length);
|
||||
|
||||
#ifdef JSFILE
|
||||
extern JS_FRIEND_API(JSTokenStream *)
|
||||
js_NewFileTokenStream(JSContext *cx, const char *filename, FILE *defaultfp);
|
||||
#endif
|
||||
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
js_CloseTokenStream(JSContext *cx, JSTokenStream *ts);
|
||||
|
||||
/*
|
||||
* Initialize the scanner, installing JS keywords into cx's global scope.
|
||||
*/
|
||||
extern JSBool
|
||||
js_InitScanner(JSContext *cx);
|
||||
|
||||
/*
|
||||
* Friend-exported API entry point to call a mapping function on each reserved
|
||||
* identifier in the scanner's keyword table.
|
||||
*/
|
||||
extern JS_FRIEND_API(void)
|
||||
js_MapKeywords(void (*mapfun)(const char *));
|
||||
|
||||
/*
|
||||
* Report an error found while scanning ts to a window or other output device
|
||||
* associated with cx.
|
||||
*/
|
||||
#if 0
|
||||
/* XXX js_ReportCompileError is unused */
|
||||
extern void
|
||||
js_ReportCompileError(JSContext *cx, JSTokenStream *ts, uintN flags,
|
||||
const char *format, ...);
|
||||
#endif
|
||||
|
||||
void
|
||||
js_ReportCompileErrorNumber(JSContext *cx, JSTokenStream *ts, uintN flags,
|
||||
const uintN errorNumber, ...);
|
||||
|
||||
/*
|
||||
* Look ahead one token and return its type.
|
||||
*/
|
||||
extern JSTokenType
|
||||
js_PeekToken(JSContext *cx, JSTokenStream *ts);
|
||||
|
||||
extern JSTokenType
|
||||
js_PeekTokenSameLine(JSContext *cx, JSTokenStream *ts);
|
||||
|
||||
/*
|
||||
* Get the next token from ts.
|
||||
*/
|
||||
extern JSTokenType
|
||||
js_GetToken(JSContext *cx, JSTokenStream *ts);
|
||||
|
||||
/*
|
||||
* Push back the last scanned token onto ts.
|
||||
*/
|
||||
extern void
|
||||
js_UngetToken(JSTokenStream *ts);
|
||||
|
||||
/*
|
||||
* Get the next token from ts if its type is tt.
|
||||
*/
|
||||
extern JSBool
|
||||
js_MatchToken(JSContext *cx, JSTokenStream *ts, JSTokenType tt);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsscan_h___ */
|
||||
524
mozilla/js/src/jsscope.c
Normal file
524
mozilla/js/src/jsscope.c
Normal file
@@ -0,0 +1,524 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* JS symbol tables.
|
||||
*/
|
||||
#include "jsstddef.h"
|
||||
#include <string.h>
|
||||
#include "jstypes.h"
|
||||
#include "jsutil.h" /* Added by JSIFY */
|
||||
#include "jsapi.h"
|
||||
#include "jsatom.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsinterp.h"
|
||||
#include "jslock.h"
|
||||
#include "jsnum.h"
|
||||
#include "jsscope.h"
|
||||
#include "jsstr.h"
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(JSHashNumber)
|
||||
js_hash_id(const void *key)
|
||||
{
|
||||
jsval v;
|
||||
const JSAtom *atom;
|
||||
|
||||
v = (jsval)key;
|
||||
if (JSVAL_IS_INT(v))
|
||||
return JSVAL_TO_INT(v);
|
||||
atom = key;
|
||||
return atom->number;
|
||||
}
|
||||
|
||||
typedef struct JSScopePrivate {
|
||||
JSContext *context;
|
||||
JSScope *scope;
|
||||
} JSScopePrivate;
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(void *)
|
||||
js_alloc_scope_space(void *priv, size_t size)
|
||||
{
|
||||
return JS_malloc(((JSScopePrivate *)priv)->context, size);
|
||||
}
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(void)
|
||||
js_free_scope_space(void *priv, void *item)
|
||||
{
|
||||
JS_free(((JSScopePrivate *)priv)->context, item);
|
||||
}
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(JSHashEntry *)
|
||||
js_alloc_symbol(void *priv, const void *key)
|
||||
{
|
||||
JSScopePrivate *spriv;
|
||||
JSContext *cx;
|
||||
JSSymbol *sym;
|
||||
|
||||
spriv = priv;
|
||||
JS_ASSERT(JS_IS_SCOPE_LOCKED(spriv->scope));
|
||||
cx = spriv->context;
|
||||
sym = JS_malloc(cx, sizeof(JSSymbol));
|
||||
if (!sym)
|
||||
return NULL;
|
||||
sym->entry.key = key;
|
||||
return &sym->entry;
|
||||
}
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(void)
|
||||
js_free_symbol(void *priv, JSHashEntry *he, uintN flag)
|
||||
{
|
||||
JSScopePrivate *spriv;
|
||||
JSContext *cx;
|
||||
JSSymbol *sym, **sp;
|
||||
JSScopeProperty *sprop;
|
||||
|
||||
spriv = priv;
|
||||
JS_ASSERT(JS_IS_SCOPE_LOCKED(spriv->scope));
|
||||
cx = spriv->context;
|
||||
sym = (JSSymbol *)he;
|
||||
sprop = sym->entry.value;
|
||||
if (sprop) {
|
||||
sym->entry.value = NULL;
|
||||
sprop = js_DropScopeProperty(cx, spriv->scope, sprop);
|
||||
if (sprop) {
|
||||
for (sp = &sprop->symbols; *sp; sp = &(*sp)->next) {
|
||||
if (*sp == sym) {
|
||||
*sp = sym->next;
|
||||
if (!*sp)
|
||||
break;
|
||||
}
|
||||
}
|
||||
sym->next = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag == HT_FREE_ENTRY)
|
||||
JS_free(cx, he);
|
||||
}
|
||||
|
||||
static JSHashAllocOps hash_scope_alloc_ops = {
|
||||
js_alloc_scope_space, js_free_scope_space,
|
||||
js_alloc_symbol, js_free_symbol
|
||||
};
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(JSSymbol *)
|
||||
js_hash_scope_lookup(JSContext *cx, JSScope *scope, jsid id, JSHashNumber hash)
|
||||
{
|
||||
JSHashTable *table = scope->data;
|
||||
JSHashEntry **hep;
|
||||
JSSymbol *sym;
|
||||
|
||||
hep = JS_HashTableRawLookup(table, hash, (const void *)id);
|
||||
sym = (JSSymbol *) *hep;
|
||||
return sym;
|
||||
}
|
||||
|
||||
#define SCOPE_ADD(PRIV, CLASS_SPECIFIC_CODE) \
|
||||
JS_BEGIN_MACRO \
|
||||
if (sym) { \
|
||||
if (sym->entry.value == sprop) \
|
||||
return sym; \
|
||||
if (sym->entry.value) \
|
||||
js_free_symbol(PRIV, &sym->entry, HT_FREE_VALUE); \
|
||||
} else { \
|
||||
CLASS_SPECIFIC_CODE \
|
||||
sym->scope = scope; \
|
||||
sym->next = NULL; \
|
||||
} \
|
||||
if (sprop) { \
|
||||
sym->entry.value = js_HoldScopeProperty(cx, scope, sprop); \
|
||||
for (sp = &sprop->symbols; *sp; sp = &(*sp)->next) \
|
||||
; \
|
||||
*sp = sym; \
|
||||
} else { \
|
||||
sym->entry.value = NULL; \
|
||||
} \
|
||||
JS_END_MACRO
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(JSSymbol *)
|
||||
js_hash_scope_add(JSContext *cx, JSScope *scope, jsid id, JSScopeProperty *sprop)
|
||||
{
|
||||
JSHashTable *table = scope->data;
|
||||
const void *key;
|
||||
JSHashNumber keyHash;
|
||||
JSHashEntry **hep;
|
||||
JSSymbol *sym, **sp;
|
||||
JSScopePrivate *priv;
|
||||
|
||||
JS_ASSERT(JS_IS_SCOPE_LOCKED(scope));
|
||||
priv = table->allocPriv;
|
||||
priv->context = cx;
|
||||
key = (const void *)id;
|
||||
keyHash = js_hash_id(key);
|
||||
hep = JS_HashTableRawLookup(table, keyHash, key);
|
||||
sym = (JSSymbol *) *hep;
|
||||
SCOPE_ADD(priv,
|
||||
sym = (JSSymbol *) JS_HashTableRawAdd(table, hep, keyHash, key, NULL);
|
||||
if (!sym)
|
||||
return NULL;
|
||||
);
|
||||
return sym;
|
||||
}
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(JSBool)
|
||||
js_hash_scope_remove(JSContext *cx, JSScope *scope, jsid id)
|
||||
{
|
||||
JSHashTable *table = scope->data;
|
||||
JSScopePrivate *priv;
|
||||
|
||||
JS_ASSERT(JS_IS_SCOPE_LOCKED(scope));
|
||||
priv = table->allocPriv;
|
||||
priv->context = cx;
|
||||
return JS_HashTableRemove(table, (const void *)id);
|
||||
}
|
||||
|
||||
/* Forward declaration for use by js_hash_scope_clear(). */
|
||||
extern JS_FRIEND_DATA(JSScopeOps) js_list_scope_ops;
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(void)
|
||||
js_hash_scope_clear(JSContext *cx, JSScope *scope)
|
||||
{
|
||||
JSHashTable *table = scope->data;
|
||||
JSScopePrivate *priv;
|
||||
|
||||
JS_ASSERT(JS_IS_SCOPE_LOCKED(scope));
|
||||
priv = table->allocPriv;
|
||||
priv->context = cx;
|
||||
JS_HashTableDestroy(table);
|
||||
JS_free(cx, priv);
|
||||
scope->ops = &js_list_scope_ops;
|
||||
scope->data = NULL;
|
||||
}
|
||||
|
||||
JSScopeOps js_hash_scope_ops = {
|
||||
js_hash_scope_lookup,
|
||||
js_hash_scope_add,
|
||||
js_hash_scope_remove,
|
||||
js_hash_scope_clear
|
||||
};
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
static void
|
||||
move_sym_to_front(JSSymbol *sym, JSSymbol **nextp, JSSymbol **front)
|
||||
{
|
||||
*nextp = (JSSymbol*)sym->entry.next;
|
||||
sym->entry.next = &(*front)->entry;
|
||||
*front = sym;
|
||||
}
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(JSSymbol *)
|
||||
js_list_scope_lookup(JSContext *cx, JSScope *scope, jsid id, JSHashNumber hash)
|
||||
{
|
||||
JSSymbol *sym, **sp;
|
||||
JS_ASSERT(JS_IS_SCOPE_LOCKED(scope));
|
||||
|
||||
for (sp = (JSSymbol **)&scope->data; (sym = *sp) != 0;
|
||||
sp = (JSSymbol **)&sym->entry.next) {
|
||||
if (sym_id(sym) == id) {
|
||||
/* Move sym to the front for shorter searches. */
|
||||
move_sym_to_front(sym,sp,(JSSymbol**)&scope->data);
|
||||
return sym;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define HASH_THRESHOLD 5
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(JSSymbol *)
|
||||
js_list_scope_add(JSContext *cx, JSScope *scope, jsid id, JSScopeProperty *sprop)
|
||||
{
|
||||
JSSymbol *list = scope->data;
|
||||
uint32 nsyms;
|
||||
JSSymbol *sym, *next, **sp;
|
||||
JSHashTable *table;
|
||||
JSHashEntry **hep;
|
||||
JSScopePrivate priv;
|
||||
|
||||
JS_ASSERT(JS_IS_SCOPE_LOCKED(scope));
|
||||
nsyms = 0;
|
||||
for (sym = list; sym; sym = (JSSymbol *)sym->entry.next) {
|
||||
if (sym_id(sym) == id)
|
||||
break;
|
||||
nsyms++;
|
||||
}
|
||||
|
||||
if (nsyms >= HASH_THRESHOLD) {
|
||||
JSScopePrivate *priv = JS_malloc(cx, sizeof(JSScopePrivate));
|
||||
if (!priv) return NULL;
|
||||
priv->context = cx;
|
||||
priv->scope = scope;
|
||||
table = JS_NewHashTable(nsyms, js_hash_id,
|
||||
JS_CompareValues, JS_CompareValues,
|
||||
&hash_scope_alloc_ops, priv);
|
||||
if (table) {
|
||||
for (sym = list; sym; sym = next) {
|
||||
/* Save next for loop update, before it changes in lookup. */
|
||||
next = (JSSymbol *)sym->entry.next;
|
||||
|
||||
/* Now compute missing keyHash fields. */
|
||||
sym->entry.keyHash = js_hash_id(sym->entry.key);
|
||||
sym->entry.next = NULL;
|
||||
hep = JS_HashTableRawLookup(table,
|
||||
sym->entry.keyHash,
|
||||
sym->entry.key);
|
||||
*hep = &sym->entry;
|
||||
}
|
||||
table->nentries = nsyms;
|
||||
scope->ops = &js_hash_scope_ops;
|
||||
scope->data = table;
|
||||
return scope->ops->add(cx, scope, id, sprop);
|
||||
}
|
||||
}
|
||||
|
||||
priv.context = cx;
|
||||
priv.scope = scope;
|
||||
SCOPE_ADD(&priv,
|
||||
sym = (JSSymbol *)js_alloc_symbol(&priv, (const void *)id);
|
||||
if (!sym)
|
||||
return NULL;
|
||||
/* Don't set keyHash until we know we need it, above. */
|
||||
sym->entry.next = scope->data;
|
||||
scope->data = sym;
|
||||
);
|
||||
return sym;
|
||||
}
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(JSBool)
|
||||
js_list_scope_remove(JSContext *cx, JSScope *scope, jsid id)
|
||||
{
|
||||
JSSymbol *sym, **sp;
|
||||
JSScopePrivate priv;
|
||||
|
||||
JS_ASSERT(JS_IS_SCOPE_LOCKED(scope));
|
||||
for (sp = (JSSymbol **)&scope->data; (sym = *sp) != 0;
|
||||
sp = (JSSymbol **)&sym->entry.next) {
|
||||
if (sym_id(sym) == id) {
|
||||
*sp = (JSSymbol *)sym->entry.next;
|
||||
priv.context = cx;
|
||||
priv.scope = scope;
|
||||
js_free_symbol(&priv, &sym->entry, HT_FREE_ENTRY);
|
||||
return JS_TRUE;
|
||||
}
|
||||
}
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(void)
|
||||
js_list_scope_clear(JSContext *cx, JSScope *scope)
|
||||
{
|
||||
JSSymbol *sym;
|
||||
JSScopePrivate priv;
|
||||
|
||||
JS_ASSERT(JS_IS_SCOPE_LOCKED(scope));
|
||||
while ((sym = scope->data) != NULL) {
|
||||
scope->data = sym->entry.next;
|
||||
priv.context = cx;
|
||||
priv.scope = scope;
|
||||
js_free_symbol(&priv, &sym->entry, HT_FREE_ENTRY);
|
||||
}
|
||||
}
|
||||
|
||||
JSScopeOps JS_FRIEND_DATA(js_list_scope_ops) = {
|
||||
js_list_scope_lookup,
|
||||
js_list_scope_add,
|
||||
js_list_scope_remove,
|
||||
js_list_scope_clear
|
||||
};
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
JSScope *
|
||||
js_GetMutableScope(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JSScope *scope, *newscope;
|
||||
|
||||
scope = (JSScope *) obj->map;
|
||||
JS_ASSERT(JS_IS_SCOPE_LOCKED(scope));
|
||||
if (scope->object == obj)
|
||||
return scope;
|
||||
newscope = js_NewScope(cx, 0, scope->map.ops, LOCKED_OBJ_GET_CLASS(obj),
|
||||
obj);
|
||||
if (!newscope)
|
||||
return NULL;
|
||||
JS_LOCK_SCOPE(cx, newscope);
|
||||
obj->map = js_HoldObjectMap(cx, &newscope->map);
|
||||
scope = (JSScope *) js_DropObjectMap(cx, &scope->map, obj);
|
||||
JS_TRANSFER_SCOPE_LOCK(cx, scope, newscope);
|
||||
return newscope;
|
||||
}
|
||||
|
||||
JSScope *
|
||||
js_MutateScope(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
|
||||
JSScopeProperty **propp)
|
||||
{
|
||||
/* XXX pessimal */
|
||||
*propp = NULL;
|
||||
return js_GetMutableScope(cx, obj);
|
||||
}
|
||||
|
||||
JSScope *
|
||||
js_NewScope(JSContext *cx, jsrefcount nrefs, JSObjectOps *ops, JSClass *clasp,
|
||||
JSObject *obj)
|
||||
{
|
||||
JSScope *scope;
|
||||
|
||||
scope = JS_malloc(cx, sizeof(JSScope));
|
||||
if (!scope)
|
||||
return NULL;
|
||||
js_InitObjectMap(&scope->map, nrefs, ops, clasp);
|
||||
scope->object = obj;
|
||||
scope->props = NULL;
|
||||
scope->proptail = &scope->props;
|
||||
scope->ops = &js_list_scope_ops;
|
||||
scope->data = NULL;
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
js_NewLock(&scope->lock);
|
||||
scope->count = 0;
|
||||
#ifdef DEBUG
|
||||
scope->file[0] = scope->file[1] = scope->file[2] = scope->file[3] = NULL;
|
||||
scope->line[0] = scope->line[1] = scope->line[2] = scope->line[3] = 0;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return scope;
|
||||
}
|
||||
|
||||
void
|
||||
js_DestroyScope(JSContext *cx, JSScope *scope)
|
||||
{
|
||||
JS_LOCK_SCOPE(cx, scope);
|
||||
scope->ops->clear(cx, scope);
|
||||
JS_UNLOCK_SCOPE(cx, scope);
|
||||
#ifdef JS_THREADSAFE
|
||||
JS_ASSERT(scope->count == 0);
|
||||
js_DestroyLock(&scope->lock);
|
||||
#endif
|
||||
JS_free(cx, scope);
|
||||
}
|
||||
|
||||
JSHashNumber
|
||||
js_HashValue(jsval v)
|
||||
{
|
||||
return js_hash_id((const void *)v);
|
||||
}
|
||||
|
||||
jsval
|
||||
js_IdToValue(jsid id)
|
||||
{
|
||||
JSAtom *atom;
|
||||
|
||||
if (JSVAL_IS_INT(id))
|
||||
return id;
|
||||
atom = (JSAtom *)id;
|
||||
return ATOM_KEY(atom);
|
||||
}
|
||||
|
||||
JSScopeProperty *
|
||||
js_NewScopeProperty(JSContext *cx, JSScope *scope, jsid id,
|
||||
JSPropertyOp getter, JSPropertyOp setter, uintN attrs)
|
||||
{
|
||||
uint32 slot;
|
||||
JSScopeProperty *sprop;
|
||||
|
||||
JS_ASSERT(JS_IS_SCOPE_LOCKED(scope));
|
||||
if (!js_AllocSlot(cx, scope->object, &slot))
|
||||
return NULL;
|
||||
sprop = JS_malloc(cx, sizeof(JSScopeProperty));
|
||||
if (!sprop) {
|
||||
js_FreeSlot(cx, scope->object, slot);
|
||||
return NULL;
|
||||
}
|
||||
sprop->nrefs = 0;
|
||||
sprop->id = js_IdToValue(id);
|
||||
sprop->getter = getter;
|
||||
sprop->setter = setter;
|
||||
sprop->slot = slot;
|
||||
sprop->attrs = attrs;
|
||||
sprop->spare = 0;
|
||||
sprop->symbols = NULL;
|
||||
sprop->next = NULL;
|
||||
sprop->prevp = scope->proptail;
|
||||
*scope->proptail = sprop;
|
||||
scope->proptail = &sprop->next;
|
||||
return sprop;
|
||||
}
|
||||
|
||||
void
|
||||
js_DestroyScopeProperty(JSContext *cx, JSScope *scope, JSScopeProperty *sprop)
|
||||
{
|
||||
/*
|
||||
* Test whether obj was finalized before prop's last dereference.
|
||||
*
|
||||
* This can happen when a deleted property is held by a property iterator
|
||||
* object (which points to obj, keeping obj alive so long as the property
|
||||
* iterator is reachable). As soon as the GC finds the iterator to be
|
||||
* unreachable, it will finalize the iterator, and may also finalize obj,
|
||||
* in an unpredictable order. If obj is finalized first, its map will be
|
||||
* null below, and we need only free prop.
|
||||
*
|
||||
* In the more typical case of a property whose last reference (from a
|
||||
* symbol in obj's scope) goes away before obj is finalized, we must be
|
||||
* sure to free prop's slot and unlink it from obj's property list.
|
||||
*/
|
||||
if (scope) {
|
||||
JS_ASSERT(JS_IS_SCOPE_LOCKED(scope));
|
||||
if (scope->object) {
|
||||
js_FreeSlot(cx, scope->object, sprop->slot);
|
||||
*sprop->prevp = sprop->next;
|
||||
if (sprop->next)
|
||||
sprop->next->prevp = sprop->prevp;
|
||||
else
|
||||
scope->proptail = sprop->prevp;
|
||||
}
|
||||
}
|
||||
|
||||
/* Purge any cached weak links to prop, then free it. */
|
||||
js_FlushPropertyCacheByProp(cx, (JSProperty *)sprop);
|
||||
JS_free(cx, sprop);
|
||||
}
|
||||
|
||||
JSScopeProperty *
|
||||
js_HoldScopeProperty(JSContext *cx, JSScope *scope, JSScopeProperty *sprop)
|
||||
{
|
||||
JS_ASSERT(JS_IS_SCOPE_LOCKED(scope));
|
||||
if (sprop) {
|
||||
JS_ASSERT(sprop->nrefs >= 0);
|
||||
sprop->nrefs++;
|
||||
}
|
||||
return sprop;
|
||||
}
|
||||
|
||||
JSScopeProperty *
|
||||
js_DropScopeProperty(JSContext *cx, JSScope *scope, JSScopeProperty *sprop)
|
||||
{
|
||||
JS_ASSERT(JS_IS_SCOPE_LOCKED(scope));
|
||||
if (sprop) {
|
||||
JS_ASSERT(sprop->nrefs > 0);
|
||||
if (--sprop->nrefs == 0) {
|
||||
js_DestroyScopeProperty(cx, scope, sprop);
|
||||
sprop = NULL;
|
||||
}
|
||||
}
|
||||
return sprop;
|
||||
}
|
||||
122
mozilla/js/src/jsscope.h
Normal file
122
mozilla/js/src/jsscope.h
Normal file
@@ -0,0 +1,122 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef jsscope_h___
|
||||
#define jsscope_h___
|
||||
/*
|
||||
* JS symbol tables.
|
||||
*/
|
||||
#include "jstypes.h"
|
||||
#include "jshash.h" /* Added by JSIFY */
|
||||
#include "jsobj.h"
|
||||
#include "jsprvtd.h"
|
||||
#include "jspubtd.h"
|
||||
|
||||
struct JSScopeOps {
|
||||
JSSymbol * (*lookup)(JSContext *cx, JSScope *scope, jsid id,
|
||||
JSHashNumber hash);
|
||||
JSSymbol * (*add)(JSContext *cx, JSScope *scope, jsid id,
|
||||
JSScopeProperty *sprop);
|
||||
JSBool (*remove)(JSContext *cx, JSScope *scope, jsid id);
|
||||
void (*clear)(JSContext *cx, JSScope *scope);
|
||||
};
|
||||
|
||||
struct JSScope {
|
||||
JSObjectMap map; /* base class state */
|
||||
JSObject *object; /* object that owns this scope */
|
||||
JSScopeProperty *props; /* property list in definition order */
|
||||
JSScopeProperty **proptail; /* pointer to pointer to last prop */
|
||||
JSScopeOps *ops; /* virtual operations */
|
||||
void *data; /* private data specific to ops */
|
||||
#ifdef JS_THREADSAFE
|
||||
JSThinLock lock; /* binary semaphore protecting scope */
|
||||
int32 count; /* entry count for reentrancy */
|
||||
#ifdef DEBUG
|
||||
const char *file[4]; /* file where lock was (re-)taken */
|
||||
unsigned int line[4]; /* line where lock was (re-)taken */
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
struct JSSymbol {
|
||||
JSHashEntry entry; /* base class state */
|
||||
JSScope *scope; /* pointer to owning scope */
|
||||
JSSymbol *next; /* next in type-specific list */
|
||||
};
|
||||
|
||||
#define sym_id(sym) ((jsid)(sym)->entry.key)
|
||||
#define sym_atom(sym) ((JSAtom *)(sym)->entry.key)
|
||||
#define sym_property(sym) ((JSScopeProperty *)(sym)->entry.value)
|
||||
|
||||
struct JSScopeProperty {
|
||||
jsrefcount nrefs; /* number of referencing symbols */
|
||||
jsval id; /* id passed to getter and setter */
|
||||
JSPropertyOp getter; /* getter and setter methods */
|
||||
JSPropertyOp setter;
|
||||
uint32 slot; /* index in obj->slots vector */
|
||||
uint8 attrs; /* attributes, see jsapi.h JSPROP_ */
|
||||
uint8 spare; /* reserved for future use */
|
||||
JSSymbol *symbols; /* list of aliasing symbols */
|
||||
JSScopeProperty *next; /* doubly-linked list linkage */
|
||||
JSScopeProperty **prevp;
|
||||
};
|
||||
|
||||
/*
|
||||
* These macros are designed to decouple getter and setter from sprop, by
|
||||
* passing obj2 (in whose scope sprop lives, and in whose scope getter and
|
||||
* setter might be stored apart from sprop -- say in scope->opTable[i] for
|
||||
* a compressed getter or setter index i that is stored in sprop).
|
||||
*/
|
||||
#define SPROP_GET(cx,sprop,obj,obj2,vp) ((sprop)->getter(cx,obj,sprop->id,vp))
|
||||
#define SPROP_SET(cx,sprop,obj,obj2,vp) ((sprop)->setter(cx,obj,sprop->id,vp))
|
||||
|
||||
extern JSScope *
|
||||
js_GetMutableScope(JSContext *cx, JSObject *obj);
|
||||
|
||||
extern JSScope *
|
||||
js_MutateScope(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
|
||||
JSScopeProperty **propp);
|
||||
|
||||
extern JSScope *
|
||||
js_NewScope(JSContext *cx, jsrefcount nrefs, JSObjectOps *ops, JSClass *clasp,
|
||||
JSObject *obj);
|
||||
|
||||
extern void
|
||||
js_DestroyScope(JSContext *cx, JSScope *scope);
|
||||
|
||||
extern JSHashNumber
|
||||
js_HashValue(jsval v);
|
||||
|
||||
extern jsval
|
||||
js_IdToValue(jsid id);
|
||||
|
||||
extern JSScopeProperty *
|
||||
js_NewScopeProperty(JSContext *cx, JSScope *scope, jsid id,
|
||||
JSPropertyOp getter, JSPropertyOp setter, uintN attrs);
|
||||
|
||||
extern void
|
||||
js_DestroyScopeProperty(JSContext *cx, JSScope *scope, JSScopeProperty *sprop);
|
||||
|
||||
extern JSScopeProperty *
|
||||
js_HoldScopeProperty(JSContext *cx, JSScope *scope, JSScopeProperty *sprop);
|
||||
|
||||
extern JSScopeProperty *
|
||||
js_DropScopeProperty(JSContext *cx, JSScope *scope, JSScopeProperty *sprop);
|
||||
|
||||
#endif /* jsscope_h___ */
|
||||
783
mozilla/js/src/jsscript.c
Normal file
783
mozilla/js/src/jsscript.c
Normal file
@@ -0,0 +1,783 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* JS script operations.
|
||||
*/
|
||||
#include "jsstddef.h"
|
||||
#include <string.h>
|
||||
#include "jstypes.h"
|
||||
#include "jsutil.h" /* Added by JSIFY */
|
||||
#include "jsprf.h"
|
||||
#include "jsapi.h"
|
||||
#include "jsatom.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsconfig.h"
|
||||
#include "jsdbgapi.h"
|
||||
#include "jsemit.h"
|
||||
#include "jsfun.h"
|
||||
#include "jsinterp.h"
|
||||
#include "jsnum.h"
|
||||
#include "jsopcode.h"
|
||||
#include "jsscript.h"
|
||||
#if JS_HAS_XDR
|
||||
#include "jsxdrapi.h"
|
||||
#endif
|
||||
|
||||
#if JS_HAS_SCRIPT_OBJECT
|
||||
|
||||
#if JS_HAS_TOSOURCE
|
||||
static JSBool
|
||||
script_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
{
|
||||
JSScript *script;
|
||||
size_t i, j, k, n;
|
||||
char buf[16];
|
||||
jschar *s, *t;
|
||||
uint32 indent;
|
||||
JSString *str;
|
||||
|
||||
if (!JS_InstanceOf(cx, obj, &js_ScriptClass, argv))
|
||||
return JS_FALSE;
|
||||
script = JS_GetPrivate(cx, obj);
|
||||
|
||||
/* Let n count the source string length, j the "front porch" length. */
|
||||
j = JS_snprintf(buf, sizeof buf, "(new %s(", js_ScriptClass.name);
|
||||
n = j + 2;
|
||||
if (!script) {
|
||||
/* Let k count the constructor argument string length. */
|
||||
k = 0;
|
||||
s = NULL; /* quell GCC overwarning */
|
||||
} else {
|
||||
indent = 0;
|
||||
if (argc && !js_ValueToECMAUint32(cx, argv[0], &indent))
|
||||
return JS_FALSE;
|
||||
str = JS_DecompileScript(cx, script, "Script.prototype.toSource",
|
||||
(uintN)indent);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
str = js_QuoteString(cx, str, '\'');
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
s = str->chars;
|
||||
k = str->length;
|
||||
n += k;
|
||||
}
|
||||
|
||||
/* Allocate the source string and copy into it. */
|
||||
t = JS_malloc(cx, (n + 1) * sizeof(jschar));
|
||||
if (!t)
|
||||
return JS_FALSE;
|
||||
for (i = 0; i < j; i++)
|
||||
t[i] = buf[i];
|
||||
for (j = 0; j < k; i++, j++)
|
||||
t[i] = s[j];
|
||||
t[i++] = ')';
|
||||
t[i++] = ')';
|
||||
t[i] = 0;
|
||||
|
||||
/* Create and return a JS string for t. */
|
||||
str = JS_NewUCString(cx, t, n);
|
||||
if (!str) {
|
||||
JS_free(cx, t);
|
||||
return JS_FALSE;
|
||||
}
|
||||
*rval = STRING_TO_JSVAL(str);
|
||||
return JS_TRUE;
|
||||
}
|
||||
#endif /* JS_HAS_TOSOURCE */
|
||||
|
||||
static JSBool
|
||||
script_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
{
|
||||
JSScript *script;
|
||||
uint32 indent;
|
||||
JSString *str;
|
||||
|
||||
if (!JS_InstanceOf(cx, obj, &js_ScriptClass, argv))
|
||||
return JS_FALSE;
|
||||
script = JS_GetPrivate(cx, obj);
|
||||
if (!script) {
|
||||
*rval = STRING_TO_JSVAL(cx->runtime->emptyString);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
indent = 0;
|
||||
if (argc && !js_ValueToECMAUint32(cx, argv[0], &indent))
|
||||
return JS_FALSE;
|
||||
str = JS_DecompileScript(cx, script, "Script.prototype.toString",
|
||||
(uintN)indent);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
*rval = STRING_TO_JSVAL(str);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
script_compile(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
{
|
||||
JSScript *oldscript, *script;
|
||||
JSString *str;
|
||||
JSStackFrame *fp, *caller;
|
||||
JSObject *scopeobj;
|
||||
const char *file;
|
||||
uintN line;
|
||||
JSPrincipals *principals;
|
||||
|
||||
/* If no args, leave private undefined and return early. */
|
||||
if (argc == 0)
|
||||
goto out;
|
||||
|
||||
/* Otherwise, the first arg is the script source to compile. */
|
||||
str = js_ValueToString(cx, argv[0]);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
|
||||
/* Compile using the caller's scope chain, which js_Invoke passes to fp. */
|
||||
fp = cx->fp;
|
||||
caller = fp->down;
|
||||
JS_ASSERT(fp->scopeChain == caller->scopeChain);
|
||||
|
||||
scopeobj = NULL;
|
||||
if (argc >= 2) {
|
||||
if (!js_ValueToObject(cx, argv[1], &scopeobj))
|
||||
return JS_FALSE;
|
||||
argv[1] = OBJECT_TO_JSVAL(scopeobj);
|
||||
}
|
||||
if (!scopeobj)
|
||||
scopeobj = caller->scopeChain;
|
||||
|
||||
if (caller->script) {
|
||||
file = caller->script->filename;
|
||||
line = js_PCToLineNumber(caller->script, caller->pc);
|
||||
principals = caller->script->principals;
|
||||
} else {
|
||||
file = NULL;
|
||||
line = 0;
|
||||
principals = NULL;
|
||||
}
|
||||
|
||||
/* Compile the new script using the caller's scope chain, a la eval(). */
|
||||
script = JS_CompileUCScriptForPrincipals(cx, scopeobj, principals,
|
||||
str->chars, str->length,
|
||||
file, line);
|
||||
if (!script)
|
||||
return JS_FALSE;
|
||||
|
||||
/* Swap script for obj's old script, if any. */
|
||||
oldscript = JS_GetPrivate(cx, obj);
|
||||
if (!JS_SetPrivate(cx, obj, script)) {
|
||||
js_DestroyScript(cx, script);
|
||||
return JS_FALSE;
|
||||
}
|
||||
if (oldscript)
|
||||
js_DestroyScript(cx, oldscript);
|
||||
|
||||
script->object = obj;
|
||||
out:
|
||||
/* Return the object. */
|
||||
*rval = OBJECT_TO_JSVAL(obj);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
script_exec(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
JSScript *script;
|
||||
JSStackFrame *fp, *caller;
|
||||
JSObject *scopeobj;
|
||||
|
||||
if (!JS_InstanceOf(cx, obj, &js_ScriptClass, argv))
|
||||
return JS_FALSE;
|
||||
script = JS_GetPrivate(cx, obj);
|
||||
if (!script)
|
||||
return JS_TRUE;
|
||||
|
||||
scopeobj = NULL;
|
||||
if (argc) {
|
||||
if (!js_ValueToObject(cx, argv[0], &scopeobj))
|
||||
return JS_FALSE;
|
||||
argv[0] = OBJECT_TO_JSVAL(scopeobj);
|
||||
}
|
||||
|
||||
/* Emulate eval() by using caller's this, scope chain, and sharp array. */
|
||||
fp = cx->fp;
|
||||
caller = fp->down;
|
||||
if (!scopeobj)
|
||||
scopeobj = caller->scopeChain;
|
||||
fp->thisp = caller->thisp;
|
||||
JS_ASSERT(fp->scopeChain == caller->scopeChain);
|
||||
fp->sharpArray = caller->sharpArray;
|
||||
return js_Execute(cx, scopeobj, script, NULL, fp, JS_FALSE, rval);
|
||||
}
|
||||
|
||||
#if JS_HAS_XDR
|
||||
static JSBool
|
||||
XDRAtom1(JSXDRState *xdr, JSAtomListElement *ale)
|
||||
{
|
||||
uint32 type;
|
||||
jsval value;
|
||||
|
||||
if (xdr->mode == JSXDR_ENCODE) {
|
||||
type = JSVAL_TAG(ATOM_KEY(ale->atom));
|
||||
value = ATOM_KEY(ale->atom);
|
||||
}
|
||||
|
||||
if (!JS_XDRUint32(xdr, &ale->index) ||
|
||||
!JS_XDRValue(xdr, &value))
|
||||
return JS_FALSE;
|
||||
|
||||
if (xdr->mode == JSXDR_DECODE) {
|
||||
ale->atom = js_AtomizeValue(xdr->cx, value, 0);
|
||||
if (!ale->atom)
|
||||
return JS_FALSE;
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
XDRAtomMap(JSXDRState *xdr, JSAtomMap *map)
|
||||
{
|
||||
uint32 length;
|
||||
uintN i;
|
||||
|
||||
if (xdr->mode == JSXDR_ENCODE)
|
||||
length = map->length;
|
||||
|
||||
if (!JS_XDRUint32(xdr, &length))
|
||||
return JS_FALSE;
|
||||
|
||||
if (xdr->mode == JSXDR_DECODE) {
|
||||
JSContext *cx;
|
||||
void *mark;
|
||||
JSAtomList al;
|
||||
JSAtomListElement *ale;
|
||||
|
||||
cx = xdr->cx;
|
||||
mark = JS_ARENA_MARK(&cx->tempPool);
|
||||
ATOM_LIST_INIT(&al);
|
||||
for (i = 0; i < length; i++) {
|
||||
JS_ARENA_ALLOCATE(ale, &cx->tempPool, sizeof(*ale));
|
||||
if (!ale ||
|
||||
!XDRAtom1(xdr, ale)) {
|
||||
if (!ale)
|
||||
JS_ReportOutOfMemory(cx);
|
||||
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
||||
return JS_FALSE;
|
||||
}
|
||||
ale->next = al.list;
|
||||
al.count++;
|
||||
al.list = ale;
|
||||
}
|
||||
if (!js_InitAtomMap(cx, map, &al)) {
|
||||
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
||||
return JS_FALSE;
|
||||
}
|
||||
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
||||
} else if (xdr->mode == JSXDR_ENCODE) {
|
||||
JSAtomListElement ale;
|
||||
|
||||
for (i = 0; i < map->length; i++) {
|
||||
ale.atom = map->vector[i];
|
||||
ale.index = i;
|
||||
if (!XDRAtom1(xdr, &ale))
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_XDRScript(JSXDRState *xdr, JSScript **scriptp, JSBool *magic)
|
||||
{
|
||||
JSScript *script = *scriptp;
|
||||
uint32 length, lineno, depth, magicval;
|
||||
|
||||
if (xdr->mode == JSXDR_ENCODE)
|
||||
magicval = SCRIPT_XDRMAGIC;
|
||||
if (!JS_XDRUint32(xdr, &magicval))
|
||||
return JS_FALSE;
|
||||
if (magicval != SCRIPT_XDRMAGIC) {
|
||||
*magic = JS_FALSE;
|
||||
return JS_TRUE;
|
||||
}
|
||||
*magic = JS_TRUE;
|
||||
if (xdr->mode == JSXDR_ENCODE) {
|
||||
length = script->length;
|
||||
lineno = (uint32)script->lineno;
|
||||
depth = (uint32)script->depth;
|
||||
}
|
||||
if (!JS_XDRUint32(xdr, &length))
|
||||
return JS_FALSE;
|
||||
if (xdr->mode == JSXDR_DECODE) {
|
||||
script = js_NewScript(xdr->cx, length);
|
||||
if (!script)
|
||||
return JS_FALSE;
|
||||
*scriptp = script;
|
||||
}
|
||||
if (!JS_XDRBytes(xdr, (char **)&script->code, length) ||
|
||||
!XDRAtomMap(xdr, &script->atomMap) ||
|
||||
!JS_XDRCStringOrNull(xdr, (char **)&script->notes) ||
|
||||
!JS_XDRCStringOrNull(xdr, (char **)&script->filename) ||
|
||||
!JS_XDRUint32(xdr, &lineno) ||
|
||||
!JS_XDRUint32(xdr, &depth)) {
|
||||
if (xdr->mode == JSXDR_DECODE) {
|
||||
js_DestroyScript(xdr->cx, script);
|
||||
*scriptp = NULL;
|
||||
}
|
||||
return JS_FALSE;
|
||||
}
|
||||
if (xdr->mode == JSXDR_DECODE) {
|
||||
script->lineno = (uintN)lineno;
|
||||
script->depth = (uintN)depth;
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
script_freeze(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
{
|
||||
JSXDRState *xdr;
|
||||
JSScript *script;
|
||||
JSBool ok, magic;
|
||||
uint32 len;
|
||||
void *buf;
|
||||
JSString *str;
|
||||
|
||||
if (!JS_InstanceOf(cx, obj, &js_ScriptClass, argv))
|
||||
return JS_FALSE;
|
||||
script = JS_GetPrivate(cx, obj);
|
||||
if (!script)
|
||||
return JS_TRUE;
|
||||
|
||||
/* create new XDR */
|
||||
xdr = JS_XDRNewMem(cx, JSXDR_ENCODE);
|
||||
if (!xdr)
|
||||
return JS_FALSE;
|
||||
|
||||
/* write */
|
||||
ok = js_XDRScript(xdr, &script, &magic);
|
||||
if (!ok)
|
||||
goto out;
|
||||
if (!magic) {
|
||||
*rval = JSVAL_VOID;
|
||||
goto out;
|
||||
}
|
||||
|
||||
buf = JS_XDRMemGetData(xdr, &len);
|
||||
if (!buf) {
|
||||
ok = JS_FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
JS_ASSERT((jsword)buf % sizeof(jschar) == 0);
|
||||
len /= sizeof(jschar);
|
||||
str = JS_NewUCStringCopyN(cx, (jschar *)buf, len);
|
||||
if (!str) {
|
||||
ok = JS_FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
#if IS_BIG_ENDIAN
|
||||
{
|
||||
jschar *chars;
|
||||
uint32 i;
|
||||
|
||||
/* Swap bytes in Unichars to keep frozen strings machine-independent. */
|
||||
chars = JS_GetStringChars(str);
|
||||
for (i = 0; i < len; i++)
|
||||
chars[i] = JSXDR_SWAB16(chars[i]);
|
||||
}
|
||||
#endif
|
||||
*rval = STRING_TO_JSVAL(str);
|
||||
|
||||
out:
|
||||
JS_XDRDestroy(xdr);
|
||||
return ok;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
script_thaw(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
{
|
||||
JSXDRState *xdr;
|
||||
JSString *str;
|
||||
void *buf;
|
||||
uint32 len;
|
||||
JSScript *script, *oldscript;
|
||||
JSBool ok, magic;
|
||||
|
||||
if (!JS_InstanceOf(cx, obj, &js_ScriptClass, argv))
|
||||
return JS_FALSE;
|
||||
|
||||
if (argc == 0)
|
||||
return JS_TRUE;
|
||||
str = js_ValueToString(cx, argv[0]);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
|
||||
/* create new XDR */
|
||||
xdr = JS_XDRNewMem(cx, JSXDR_DECODE);
|
||||
if (!xdr)
|
||||
return JS_FALSE;
|
||||
|
||||
buf = JS_GetStringChars(str);
|
||||
len = JS_GetStringLength(str);
|
||||
#if IS_BIG_ENDIAN
|
||||
{
|
||||
jschar *from, *to;
|
||||
uint32 i;
|
||||
|
||||
/* Swap bytes in Unichars to keep frozen strings machine-independent. */
|
||||
from = (jschar *)buf;
|
||||
to = JS_malloc(cx, len * sizeof(jschar));
|
||||
if (!to)
|
||||
return JS_FALSE;
|
||||
for (i = 0; i < len; i++)
|
||||
to[i] = JSXDR_SWAB16(from[i]);
|
||||
buf = (char *)to;
|
||||
}
|
||||
#endif
|
||||
len *= sizeof(jschar);
|
||||
JS_XDRMemSetData(xdr, buf, len);
|
||||
|
||||
/* XXXbe should magic mismatch be error, or false return value? */
|
||||
ok = js_XDRScript(xdr, &script, &magic);
|
||||
if (!ok)
|
||||
goto out;
|
||||
if (!magic) {
|
||||
*rval = JSVAL_FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Swap script for obj's old script, if any. */
|
||||
oldscript = JS_GetPrivate(cx, obj);
|
||||
ok = JS_SetPrivate(cx, obj, script);
|
||||
if (!ok) {
|
||||
JS_free(cx, script);
|
||||
goto out;
|
||||
}
|
||||
if (oldscript)
|
||||
js_DestroyScript(cx, oldscript);
|
||||
|
||||
script->object = obj;
|
||||
|
||||
out:
|
||||
/*
|
||||
* We reset the buffer to be NULL so that it doesn't free the chars
|
||||
* memory owned by str (argv[0]).
|
||||
*/
|
||||
JS_XDRMemSetData(xdr, NULL, 0);
|
||||
JS_XDRDestroy(xdr);
|
||||
#if IS_BIG_ENDIAN
|
||||
JS_free(cx, buf);
|
||||
#endif
|
||||
*rval = JSVAL_TRUE;
|
||||
return ok;
|
||||
}
|
||||
|
||||
#endif /* JS_HAS_XDR */
|
||||
|
||||
static char js_thaw_str[] = "thaw";
|
||||
|
||||
static JSFunctionSpec script_methods[] = {
|
||||
#if JS_HAS_TOSOURCE
|
||||
{js_toSource_str, script_toSource, 0},
|
||||
#endif
|
||||
{js_toString_str, script_toString, 0},
|
||||
{"compile", script_compile, 2},
|
||||
{"exec", script_exec, 1},
|
||||
#if JS_HAS_XDR
|
||||
{"freeze", script_freeze, 0},
|
||||
{js_thaw_str, script_thaw, 1},
|
||||
#endif /* JS_HAS_XDR */
|
||||
{0}
|
||||
};
|
||||
|
||||
#endif /* JS_HAS_SCRIPT_OBJECT */
|
||||
|
||||
static void
|
||||
script_finalize(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JSScript *script;
|
||||
|
||||
script = JS_GetPrivate(cx, obj);
|
||||
if (script)
|
||||
js_DestroyScript(cx, script);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
script_call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
return script_exec(cx, JSVAL_TO_OBJECT(argv[-2]), argc, argv, rval);
|
||||
}
|
||||
|
||||
JSClass js_ScriptClass = {
|
||||
"Script",
|
||||
JSCLASS_HAS_PRIVATE,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, script_finalize,
|
||||
NULL, NULL, script_call, NULL,/*XXXbe xdr*/
|
||||
};
|
||||
|
||||
#if JS_HAS_SCRIPT_OBJECT
|
||||
|
||||
static JSBool
|
||||
Script(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
/* If not constructing, replace obj with a new Script object. */
|
||||
if (!cx->fp->constructing) {
|
||||
obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
}
|
||||
return script_compile(cx, obj, argc, argv, rval);
|
||||
}
|
||||
|
||||
#if JS_HAS_XDR
|
||||
|
||||
static JSBool
|
||||
script_static_thaw(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
{
|
||||
obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
if (!script_thaw(cx, obj, argc, argv, rval))
|
||||
return JS_FALSE;
|
||||
*rval = OBJECT_TO_JSVAL(obj);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSFunctionSpec script_static_methods[] = {
|
||||
{js_thaw_str, script_static_thaw, 1},
|
||||
{0}
|
||||
};
|
||||
|
||||
#else /* !JS_HAS_XDR */
|
||||
|
||||
#define script_static_methods NULL
|
||||
|
||||
#endif /* !JS_HAS_XDR */
|
||||
|
||||
JSObject *
|
||||
js_InitScriptClass(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
return JS_InitClass(cx, obj, NULL, &js_ScriptClass, Script, 1,
|
||||
NULL, script_methods, NULL, script_static_methods);
|
||||
}
|
||||
|
||||
#endif /* JS_HAS_SCRIPT_OBJECT */
|
||||
|
||||
JSScript *
|
||||
js_NewScript(JSContext *cx, uint32 length)
|
||||
{
|
||||
JSScript *script;
|
||||
|
||||
script = JS_malloc(cx, sizeof(JSScript) + length * sizeof(jsbytecode));
|
||||
if (!script)
|
||||
return NULL;
|
||||
memset(script, 0, sizeof(JSScript));
|
||||
script->code = (jsbytecode *)(script + 1);
|
||||
script->length = length;
|
||||
return script;
|
||||
}
|
||||
|
||||
JSScript *
|
||||
js_NewScriptFromParams(JSContext *cx, jsbytecode *code, uint32 length,
|
||||
const char *filename, uintN lineno, uintN depth,
|
||||
jssrcnote *notes, JSTryNote *trynotes,
|
||||
JSPrincipals *principals)
|
||||
{
|
||||
JSScript *script;
|
||||
|
||||
script = js_NewScript(cx, length);
|
||||
if (!script)
|
||||
return NULL;
|
||||
memcpy(script->code, code, length * sizeof(jsbytecode));
|
||||
if (filename) {
|
||||
script->filename = JS_strdup(cx, filename);
|
||||
if (!script->filename) {
|
||||
js_DestroyScript(cx, script);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
script->lineno = lineno;
|
||||
script->depth = depth;
|
||||
script->notes = notes;
|
||||
script->trynotes = trynotes;
|
||||
if (principals)
|
||||
JSPRINCIPALS_HOLD(cx, principals);
|
||||
script->principals = principals;
|
||||
return script;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSScript *)
|
||||
js_NewScriptFromCG(JSContext *cx, JSCodeGenerator *cg, JSFunction *fun)
|
||||
{
|
||||
JSTryNote *trynotes;
|
||||
jssrcnote *notes;
|
||||
JSScript *script;
|
||||
JSRuntime *rt;
|
||||
JSNewScriptHook hook;
|
||||
|
||||
if (!js_FinishTakingTryNotes(cx, cg, &trynotes))
|
||||
return NULL;
|
||||
notes = js_FinishTakingSrcNotes(cx, cg);
|
||||
script = js_NewScriptFromParams(cx, cg->base, CG_OFFSET(cg),
|
||||
cg->filename, cg->firstLine,
|
||||
cg->maxStackDepth, notes, trynotes,
|
||||
cg->principals);
|
||||
if (!script)
|
||||
return NULL;
|
||||
if (!notes || !js_InitAtomMap(cx, &script->atomMap, &cg->atomList)) {
|
||||
js_DestroyScript(cx, script);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Tell the debugger about this compiled script. */
|
||||
rt = cx->runtime;
|
||||
hook = rt->newScriptHook;
|
||||
if (hook) {
|
||||
(*hook)(cx, cg->filename, cg->firstLine, script, fun,
|
||||
rt->newScriptHookData);
|
||||
}
|
||||
return script;
|
||||
}
|
||||
|
||||
void
|
||||
js_DestroyScript(JSContext *cx, JSScript *script)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
JSDestroyScriptHook hook;
|
||||
|
||||
rt = cx->runtime;
|
||||
hook = rt->destroyScriptHook;
|
||||
if (hook)
|
||||
(*hook)(cx, script, rt->destroyScriptHookData);
|
||||
|
||||
JS_ClearScriptTraps(cx, script);
|
||||
js_FreeAtomMap(cx, &script->atomMap);
|
||||
JS_free(cx, (void *)script->filename);
|
||||
JS_free(cx, script->notes);
|
||||
JS_free(cx, script->trynotes);
|
||||
if (script->principals)
|
||||
JSPRINCIPALS_DROP(cx, script->principals);
|
||||
JS_free(cx, script);
|
||||
}
|
||||
|
||||
jssrcnote *
|
||||
js_GetSrcNote(JSScript *script, jsbytecode *pc)
|
||||
{
|
||||
jssrcnote *sn;
|
||||
ptrdiff_t offset, target;
|
||||
|
||||
sn = script->notes;
|
||||
if (!sn)
|
||||
return NULL;
|
||||
target = PTRDIFF(pc, script->code, jsbytecode);
|
||||
if ((uintN)target >= script->length)
|
||||
return NULL;
|
||||
for (offset = 0; !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) {
|
||||
offset += SN_DELTA(sn);
|
||||
if (offset == target && SN_IS_GETTABLE(sn))
|
||||
return sn;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uintN
|
||||
js_PCToLineNumber(JSScript *script, jsbytecode *pc)
|
||||
{
|
||||
jssrcnote *sn;
|
||||
ptrdiff_t offset, target;
|
||||
uintN lineno;
|
||||
JSSrcNoteType type;
|
||||
|
||||
sn = script->notes;
|
||||
if (!sn)
|
||||
return 0;
|
||||
target = PTRDIFF(pc, script->code, jsbytecode);
|
||||
lineno = script->lineno;
|
||||
for (offset = 0; !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) {
|
||||
offset += SN_DELTA(sn);
|
||||
type = SN_TYPE(sn);
|
||||
if (type == SRC_SETLINE) {
|
||||
if (offset <= target)
|
||||
lineno = (uintN) js_GetSrcNoteOffset(sn, 0);
|
||||
} else if (type == SRC_NEWLINE) {
|
||||
if (offset <= target)
|
||||
lineno++;
|
||||
}
|
||||
if (offset > target)
|
||||
break;
|
||||
}
|
||||
return lineno;
|
||||
}
|
||||
|
||||
jsbytecode *
|
||||
js_LineNumberToPC(JSScript *script, uintN target)
|
||||
{
|
||||
jssrcnote *sn;
|
||||
uintN lineno;
|
||||
ptrdiff_t offset;
|
||||
JSSrcNoteType type;
|
||||
|
||||
sn = script->notes;
|
||||
if (!sn)
|
||||
return NULL;
|
||||
lineno = script->lineno;
|
||||
for (offset = 0; !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) {
|
||||
if (lineno >= target)
|
||||
break;
|
||||
offset += SN_DELTA(sn);
|
||||
type = SN_TYPE(sn);
|
||||
if (type == SRC_SETLINE) {
|
||||
lineno = (uintN) js_GetSrcNoteOffset(sn, 0);
|
||||
} else if (type == SRC_NEWLINE) {
|
||||
lineno++;
|
||||
}
|
||||
}
|
||||
return script->code + offset;
|
||||
}
|
||||
|
||||
uintN
|
||||
js_GetScriptLineExtent(JSScript *script)
|
||||
{
|
||||
jssrcnote *sn;
|
||||
uintN lineno;
|
||||
JSSrcNoteType type;
|
||||
|
||||
sn = script->notes;
|
||||
if (!sn)
|
||||
return 0;
|
||||
lineno = script->lineno;
|
||||
for (; !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) {
|
||||
type = SN_TYPE(sn);
|
||||
if (type == SRC_SETLINE) {
|
||||
lineno = (uintN) js_GetSrcNoteOffset(sn, 0);
|
||||
} else if (type == SRC_NEWLINE) {
|
||||
lineno++;
|
||||
}
|
||||
}
|
||||
return 1 + lineno - script->lineno;
|
||||
}
|
||||
93
mozilla/js/src/jsscript.h
Normal file
93
mozilla/js/src/jsscript.h
Normal file
@@ -0,0 +1,93 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef jsscript_h___
|
||||
#define jsscript_h___
|
||||
/*
|
||||
* JS script descriptor.
|
||||
*/
|
||||
#include "jsatom.h"
|
||||
#include "jsprvtd.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
/*
|
||||
* Exception handling runtime information.
|
||||
*
|
||||
* All fields except length are code offsets, relative to the beginning of
|
||||
* the script. If script->trynotes is not null, it points to a vector of
|
||||
* these structs terminated by one with start, catchStart, and finallyStart
|
||||
* all equal to 0, and length == script->length.
|
||||
*/
|
||||
struct JSTryNote {
|
||||
ptrdiff_t start; /* start of try statement */
|
||||
ptrdiff_t length; /* count of try statement bytecodes */
|
||||
ptrdiff_t catchStart; /* start of catch block (0 if none) */
|
||||
};
|
||||
|
||||
struct JSScript {
|
||||
jsbytecode *code; /* bytecodes and their immediate operands */
|
||||
uint32 length; /* length of code vector */
|
||||
JSAtomMap atomMap; /* maps immediate index to literal struct */
|
||||
const char *filename; /* source filename or null */
|
||||
uintN lineno; /* base line number of script */
|
||||
uintN depth; /* maximum stack depth in slots */
|
||||
jssrcnote *notes; /* line number and other decompiling data */
|
||||
JSTryNote *trynotes; /* exception table for this script */
|
||||
JSPrincipals *principals; /* principals for this script */
|
||||
JSObject *object; /* optional Script-class object wrapper */
|
||||
};
|
||||
|
||||
extern JSClass js_ScriptClass;
|
||||
|
||||
extern JSObject *
|
||||
js_InitScriptClass(JSContext *cx, JSObject *obj);
|
||||
|
||||
extern JSScript *
|
||||
js_NewScript(JSContext *cx, uint32 length);
|
||||
|
||||
extern JSScript *
|
||||
js_NewScriptFromParams(JSContext *cx, jsbytecode *code, uint32 length,
|
||||
const char *filename, uintN lineno, uintN depth,
|
||||
jssrcnote *notes, JSTryNote *trynotes,
|
||||
JSPrincipals *principals);
|
||||
|
||||
extern JS_FRIEND_API(JSScript *)
|
||||
js_NewScriptFromCG(JSContext *cx, JSCodeGenerator *cg, JSFunction *fun);
|
||||
|
||||
extern void
|
||||
js_DestroyScript(JSContext *cx, JSScript *script);
|
||||
|
||||
extern jssrcnote *
|
||||
js_GetSrcNote(JSScript *script, jsbytecode *pc);
|
||||
|
||||
extern uintN
|
||||
js_PCToLineNumber(JSScript *script, jsbytecode *pc);
|
||||
|
||||
extern jsbytecode *
|
||||
js_LineNumberToPC(JSScript *script, uintN lineno);
|
||||
|
||||
extern uintN
|
||||
js_GetScriptLineExtent(JSScript *script);
|
||||
|
||||
extern JSBool
|
||||
js_XDRScript(JSXDRState *xdr, JSScript **scriptp, JSBool *magic);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsscript_h___ */
|
||||
29
mozilla/js/src/jsshell.msg
Normal file
29
mozilla/js/src/jsshell.msg
Normal file
@@ -0,0 +1,29 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
Error messages for JSShell. See js.msg for format.
|
||||
*/
|
||||
|
||||
MSG_DEF(JSSMSG_NOT_AN_ERROR, 0, 0, JSEXN_NONE, "<Error #0 is reserved>")
|
||||
MSG_DEF(JSSMSG_CANT_OPEN, 1, 2, JSEXN_NONE, "can't open {0}: {1}")
|
||||
MSG_DEF(JSSMSG_TRAP_USAGE, 2, 0, JSEXN_NONE, "usage: trap [fun] [pc] expr")
|
||||
MSG_DEF(JSSMSG_LINE2PC_USAGE, 3, 0, JSEXN_NONE, "usage: line2pc [fun] line")
|
||||
MSG_DEF(JSSMSG_FILE_SCRIPTS_ONLY, 4, 0, JSEXN_NONE, "only works on JS scripts read from files")
|
||||
MSG_DEF(JSSMSG_UNEXPECTED_EOF, 5, 1, JSEXN_NONE, "unexpected EOF in {0}")
|
||||
MSG_DEF(JSSMSG_DOEXP_USAGE, 6, 0, JSEXN_NONE, "usage: doexp obj id")
|
||||
63
mozilla/js/src/jsstddef.h
Normal file
63
mozilla/js/src/jsstddef.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (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 Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
* Netscape Communications Corporation. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* stddef inclusion here to first declare ptrdif as a signed long instead of a
|
||||
* signed int.
|
||||
*/
|
||||
|
||||
#ifdef _WINDOWS
|
||||
# ifndef XP_WIN
|
||||
# define XP_WIN
|
||||
# endif
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
# ifndef XP_WIN32
|
||||
# define XP_WIN32
|
||||
# endif
|
||||
#else
|
||||
# ifndef XP_WIN16
|
||||
# define XP_WIN16
|
||||
# endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef XP_WIN16
|
||||
#ifndef _PTRDIFF_T_DEFINED
|
||||
typedef long ptrdiff_t;
|
||||
|
||||
/*
|
||||
* The Win16 compiler treats pointer differences as 16-bit signed values.
|
||||
* This macro allows us to treat them as 17-bit signed values, stored in
|
||||
* a 32-bit type.
|
||||
*/
|
||||
#define PTRDIFF(p1, p2, type) \
|
||||
((((unsigned long)(p1)) - ((unsigned long)(p2))) / sizeof(type))
|
||||
|
||||
#define _PTRDIFF_T_DEFINED
|
||||
#endif /*_PTRDIFF_T_DEFINED*/
|
||||
#else /*WIN16*/
|
||||
|
||||
#define PTRDIFF(p1, p2, type) \
|
||||
((p1) - (p2))
|
||||
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
3687
mozilla/js/src/jsstr.c
Normal file
3687
mozilla/js/src/jsstr.c
Normal file
File diff suppressed because it is too large
Load Diff
269
mozilla/js/src/jsstr.h
Normal file
269
mozilla/js/src/jsstr.h
Normal file
@@ -0,0 +1,269 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef jsstr_h___
|
||||
#define jsstr_h___
|
||||
/*
|
||||
* JS string type implementation.
|
||||
*
|
||||
* A JS string is a counted array of unicode characters. To support handoff
|
||||
* of API client memory, the chars are allocated separately from the length,
|
||||
* necessitating a pointer after the count, to form a string header. String
|
||||
* headers are GC'ed while string bytes are allocated from the malloc heap.
|
||||
*
|
||||
* When a string is treated as an object (by following it with . or []), the
|
||||
* runtime wraps it with a JSObject whose valueOf method returns the unwrapped
|
||||
* string header.
|
||||
*/
|
||||
#include <ctype.h>
|
||||
#include "jspubtd.h"
|
||||
#include "jsprvtd.h"
|
||||
#include "jshash.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
struct JSString {
|
||||
size_t length;
|
||||
jschar *chars;
|
||||
};
|
||||
|
||||
struct JSSubString {
|
||||
size_t length;
|
||||
const jschar *chars;
|
||||
};
|
||||
|
||||
extern jschar js_empty_ucstr[];
|
||||
extern JSSubString js_EmptySubString;
|
||||
|
||||
/* Unicode character attribute lookup tables. */
|
||||
extern const uint8 js_X[];
|
||||
extern const uint8 js_Y[];
|
||||
extern const uint32 js_A[];
|
||||
|
||||
/* Enumerated Unicode general category types. */
|
||||
typedef enum JSCharType {
|
||||
JSCT_UNASSIGNED = 0,
|
||||
JSCT_UPPERCASE_LETTER = 1,
|
||||
JSCT_LOWERCASE_LETTER = 2,
|
||||
JSCT_TITLECASE_LETTER = 3,
|
||||
JSCT_MODIFIER_LETTER = 4,
|
||||
JSCT_OTHER_LETTER = 5,
|
||||
JSCT_NON_SPACING_MARK = 6,
|
||||
JSCT_ENCLOSING_MARK = 7,
|
||||
JSCT_COMBINING_SPACING_MARK = 8,
|
||||
JSCT_DECIMAL_DIGIT_NUMBER = 9,
|
||||
JSCT_LETTER_NUMBER = 10,
|
||||
JSCT_OTHER_NUMBER = 11,
|
||||
JSCT_SPACE_SEPARATOR = 12,
|
||||
JSCT_LINE_SEPARATOR = 13,
|
||||
JSCT_PARAGRAPH_SEPARATOR = 14,
|
||||
JSCT_CONTROL = 15,
|
||||
JSCT_FORMAT = 16,
|
||||
JSCT_PRIVATE_USE = 18,
|
||||
JSCT_SURROGATE = 19,
|
||||
JSCT_DASH_PUNCTUATION = 20,
|
||||
JSCT_START_PUNCTUATION = 21,
|
||||
JSCT_END_PUNCTUATION = 22,
|
||||
JSCT_CONNECTOR_PUNCTUATION = 23,
|
||||
JSCT_OTHER_PUNCTUATION = 24,
|
||||
JSCT_MATH_SYMBOL = 25,
|
||||
JSCT_CURRENCY_SYMBOL = 26,
|
||||
JSCT_MODIFIER_SYMBOL = 27,
|
||||
JSCT_OTHER_SYMBOL = 28
|
||||
} JSCharType;
|
||||
|
||||
/* Character classifying and mapping macros, based on java.lang.Character. */
|
||||
#define JS_CCODE(c) (js_A[js_Y[(js_X[(uint16)(c)>>6]<<6)|((c)&0x3F)]])
|
||||
#define JS_CTYPE(c) (JS_CCODE(c) & 0x1F)
|
||||
|
||||
#define JS_ISALPHA(c) ((((1 << JSCT_UPPERCASE_LETTER) | \
|
||||
(1 << JSCT_LOWERCASE_LETTER) | \
|
||||
(1 << JSCT_TITLECASE_LETTER) | \
|
||||
(1 << JSCT_MODIFIER_LETTER) | \
|
||||
(1 << JSCT_OTHER_LETTER)) \
|
||||
>> JS_CTYPE(c)) & 1)
|
||||
|
||||
#define JS_ISALNUM(c) ((((1 << JSCT_UPPERCASE_LETTER) | \
|
||||
(1 << JSCT_LOWERCASE_LETTER) | \
|
||||
(1 << JSCT_TITLECASE_LETTER) | \
|
||||
(1 << JSCT_MODIFIER_LETTER) | \
|
||||
(1 << JSCT_OTHER_LETTER) | \
|
||||
(1 << JSCT_DECIMAL_DIGIT_NUMBER)) \
|
||||
>> JS_CTYPE(c)) & 1)
|
||||
|
||||
#define JS_ISWORD(c) (JS_ISALNUM(c) || (c) == '_')
|
||||
|
||||
/* XXXbe unify on A/X/Y tbls, avoid ctype.h? */
|
||||
#define JS_ISIDENT(c) ((c) < 128 && (isalpha(c) || (c) == '_' || (c) == '$'))
|
||||
#define JS_ISIDENT2(c) ((c) < 128 && (isalnum(c) || (c) == '_' || (c) == '$'))
|
||||
|
||||
#define JS_ISDIGIT(c) (JS_CTYPE(c) == JSCT_DECIMAL_DIGIT_NUMBER)
|
||||
|
||||
/* XXXbe fs, etc. ? */
|
||||
#define JS_ISSPACE(c) ((JS_CCODE(c) & 0x00070000) == 0x00040000)
|
||||
#define JS_ISPRINT(c) ((c) < 128 && isprint(c))
|
||||
|
||||
#define JS_ISUPPER(c) (JS_CTYPE(c) == JSCT_UPPERCASE_LETTER)
|
||||
#define JS_ISLOWER(c) (JS_CTYPE(c) == JSCT_LOWERCASE_LETTER)
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
#define JS_TOUPPER(c) ({uint32 _v = JS_CCODE(c); \
|
||||
(_v & 0x00100000) ? (c) - ((int32)_v >> 22) : (c);})
|
||||
#define JS_TOLOWER(c) ({uint32 _v = JS_CCODE(c); \
|
||||
(_v & 0x00200000) ? (c) + ((int32)_v >> 22) : (c);})
|
||||
|
||||
#else /* !__GNUC__ */
|
||||
|
||||
#define JS_TOUPPER(c) js_ToUpper((jschar)c)
|
||||
#define JS_TOLOWER(c) js_ToLower((jschar)c)
|
||||
|
||||
extern jschar js_ToUpper(jschar c);
|
||||
extern jschar js_ToLower(jschar c);
|
||||
|
||||
#endif /* !__GNUC__ */
|
||||
|
||||
#define JS_TOCTRL(c) ((c) ^ 64) /* XXX unsafe! requires uppercase c */
|
||||
|
||||
/* Shorthands for ASCII (7-bit) decimal and hex conversion. */
|
||||
#define JS7_ISDEC(c) ((c) < 128 && isdigit(c))
|
||||
#define JS7_UNDEC(c) ((c) - '0')
|
||||
#define JS7_ISHEX(c) ((c) < 128 && isxdigit(c))
|
||||
#define JS7_UNHEX(c) (uintN)(isdigit(c) ? (c) - '0' : 10 + tolower(c) - 'a')
|
||||
#define JS7_ISLET(c) ((c) < 128 && isalpha(c))
|
||||
|
||||
/* Initialize truly global state associated with JS strings. */
|
||||
extern JSBool
|
||||
js_InitStringGlobals(void);
|
||||
|
||||
extern void
|
||||
js_FreeStringGlobals(void);
|
||||
|
||||
/* Initialize the String class, returning its prototype object. */
|
||||
extern JSObject *
|
||||
js_InitStringClass(JSContext *cx, JSObject *obj);
|
||||
|
||||
/* GC-allocate a string descriptor for the given malloc-allocated chars. */
|
||||
extern JSString *
|
||||
js_NewString(JSContext *cx, jschar *chars, size_t length, uintN gcflag);
|
||||
|
||||
/* Copy a counted string and GC-allocate a descriptor for it. */
|
||||
extern JSString *
|
||||
js_NewStringCopyN(JSContext *cx, const jschar *s, size_t n, uintN gcflag);
|
||||
|
||||
/* Copy a C string and GC-allocate a descriptor for it. */
|
||||
extern JSString *
|
||||
js_NewStringCopyZ(JSContext *cx, const jschar *s, uintN gcflag);
|
||||
|
||||
/* Free the chars held by str when it is finalized by the GC. */
|
||||
extern void
|
||||
js_FinalizeString(JSContext *cx, JSString *str);
|
||||
|
||||
/* Wrap a string value in a String object. */
|
||||
extern JSObject *
|
||||
js_StringToObject(JSContext *cx, JSString *str);
|
||||
|
||||
/*
|
||||
* Convert a value to a string, returning null after reporting an error,
|
||||
* otherwise returning a new string reference.
|
||||
*/
|
||||
extern JSString *
|
||||
js_ValueToString(JSContext *cx, jsval v);
|
||||
|
||||
/*
|
||||
* Convert a value to its source expression, returning null after reporting
|
||||
* an error, otherwise returning a new string reference.
|
||||
*/
|
||||
extern JSString *
|
||||
js_ValueToSource(JSContext *cx, jsval v);
|
||||
|
||||
#ifdef HT_ENUMERATE_NEXT /* XXX don't require jshash.h */
|
||||
/*
|
||||
* Compute a hash function from str.
|
||||
*/
|
||||
extern JSHashNumber
|
||||
js_HashString(const JSString *str);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Return less than, equal to, or greater than zero depending on whether
|
||||
* str1 is less than, equal to, or greater than str2.
|
||||
*/
|
||||
extern intN
|
||||
js_CompareStrings(const JSString *str1, const JSString *str2);
|
||||
|
||||
/*
|
||||
* Boyer-Moore-Horspool superlinear search for pat:patlen in text:textlen.
|
||||
* The patlen argument must be positive and no greater than BMH_PATLEN_MAX.
|
||||
* The start argument tells where in text to begin the search.
|
||||
*
|
||||
* Return the index of pat in text, or -1 if not found.
|
||||
*/
|
||||
#define BMH_CHARSET_SIZE 256 /* ISO-Latin-1 */
|
||||
#define BMH_PATLEN_MAX 255 /* skip table element is uint8 */
|
||||
|
||||
#define BMH_BAD_PATTERN (-2) /* return value if pat is not ISO-Latin-1 */
|
||||
|
||||
extern jsint
|
||||
js_BoyerMooreHorspool(const jschar *text, jsint textlen,
|
||||
const jschar *pat, jsint patlen,
|
||||
jsint start);
|
||||
|
||||
extern size_t
|
||||
js_strlen(const jschar *s);
|
||||
|
||||
extern jschar *
|
||||
js_strchr(const jschar *s, jschar c);
|
||||
|
||||
extern jschar *
|
||||
js_strncpy(jschar *t, const jschar *s, size_t n);
|
||||
|
||||
/*
|
||||
* Return s advanced past any Unicode white space characters.
|
||||
*/
|
||||
extern const jschar *
|
||||
js_SkipWhiteSpace(const jschar *s);
|
||||
|
||||
/*
|
||||
* Inflate bytes to JS chars and vice versa. Report out of memory via cx
|
||||
* and return null on error, otherwise return the jschar or byte vector that
|
||||
* was JS_malloc'ed.
|
||||
*/
|
||||
extern jschar *
|
||||
js_InflateString(JSContext *cx, const char *bytes, size_t length);
|
||||
|
||||
extern char *
|
||||
js_DeflateString(JSContext *cx, const jschar *chars, size_t length);
|
||||
|
||||
/*
|
||||
* Associate bytes with str in the deflated string cache, returning true on
|
||||
* successful association, false on out of memory.
|
||||
*/
|
||||
extern JSBool
|
||||
js_SetStringBytes(JSString *str, char *bytes, size_t length);
|
||||
|
||||
/*
|
||||
* Find or create a deflated string cache entry for str that contains its
|
||||
* characters chopped from Unicode code points into bytes.
|
||||
*/
|
||||
extern char *
|
||||
js_GetStringBytes(JSString *str);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsstr_h___ */
|
||||
371
mozilla/js/src/jstypes.h
Normal file
371
mozilla/js/src/jstypes.h
Normal file
@@ -0,0 +1,371 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
** File: jstypes.h
|
||||
** Description: Definitions of NSPR's basic types
|
||||
**
|
||||
** Prototypes and macros used to make up for deficiencies in ANSI environments
|
||||
** that we have found.
|
||||
**
|
||||
** Since we do not wrap <stdlib.h> and all the other standard headers, authors
|
||||
** of portable code will not know in general that they need these definitions.
|
||||
** Instead of requiring these authors to find the dependent uses in their code
|
||||
** and take the following steps only in those C files, we take steps once here
|
||||
** for all C files.
|
||||
**/
|
||||
|
||||
#ifndef jstypes_h___
|
||||
#define jstypes_h___
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/***********************************************************************
|
||||
** MACROS: JS_EXTERN_API
|
||||
** JS_EXPORT_API
|
||||
** DESCRIPTION:
|
||||
** These are only for externally visible routines and globals. For
|
||||
** internal routines, just use "extern" for type checking and that
|
||||
** will not export internal cross-file or forward-declared symbols.
|
||||
** Define a macro for declaring procedures return types. We use this to
|
||||
** deal with windoze specific type hackery for DLL definitions. Use
|
||||
** JS_EXTERN_API when the prototype for the method is declared. Use
|
||||
** JS_EXPORT_API for the implementation of the method.
|
||||
**
|
||||
** Example:
|
||||
** in dowhim.h
|
||||
** JS_EXTERN_API( void ) DoWhatIMean( void );
|
||||
** in dowhim.c
|
||||
** JS_EXPORT_API( void ) DoWhatIMean( void ) { return; }
|
||||
**
|
||||
**
|
||||
***********************************************************************/
|
||||
#ifdef WIN32
|
||||
#define JS_EXTERN_API(__type) extern _declspec(dllexport) __type
|
||||
#define JS_EXPORT_API(__type) _declspec(dllexport) __type
|
||||
#define JS_EXTERN_DATA(__type) extern _declspec(dllexport) __type
|
||||
#define JS_EXPORT_DATA(__type) _declspec(dllexport) __type
|
||||
|
||||
#define JS_DLL_CALLBACK
|
||||
#define JS_STATIC_DLL_CALLBACK(__x) static __x
|
||||
|
||||
#elif defined(WIN16)
|
||||
|
||||
#ifdef _WINDLL
|
||||
#define JS_EXTERN_API(__type) extern __type _cdecl _export _loadds
|
||||
#define JS_EXPORT_API(__type) __type _cdecl _export _loadds
|
||||
#define JS_EXTERN_DATA(__type) extern __type _export
|
||||
#define JS_EXPORT_DATA(__type) __type _export
|
||||
|
||||
#define JS_DLL_CALLBACK __cdecl __loadds
|
||||
#define JS_STATIC_DLL_CALLBACK(__x) static __x CALLBACK
|
||||
|
||||
#else /* this must be .EXE */
|
||||
#define JS_EXTERN_API(__type) extern __type _cdecl _export
|
||||
#define JS_EXPORT_API(__type) __type _cdecl _export
|
||||
#define JS_EXTERN_DATA(__type) extern __type _export
|
||||
#define JS_EXPORT_DATA(__type) __type _export
|
||||
|
||||
#define JS_DLL_CALLBACK __cdecl __loadds
|
||||
#define JS_STATIC_DLL_CALLBACK(__x) __x JS_DLL_CALLBACK
|
||||
#endif /* _WINDLL */
|
||||
|
||||
#elif defined(XP_MAC)
|
||||
#define JS_EXTERN_API(__type) extern __declspec(export) __type
|
||||
#define JS_EXPORT_API(__type) __declspec(export) __type
|
||||
#define JS_EXTERN_DATA(__type) extern __declspec(export) __type
|
||||
#define JS_EXPORT_DATA(__type) __declspec(export) __type
|
||||
|
||||
#define JS_DLL_CALLBACK
|
||||
#define JS_STATIC_DLL_CALLBACK(__x) static __x
|
||||
|
||||
#elif defined(XP_OS2)
|
||||
#define JS_EXTERN_API(__type) extern __type
|
||||
#define JS_EXPORT_API(__type) __type
|
||||
#define JS_EXTERN_DATA(__type) extern __type
|
||||
#define JS_EXPORT_DATA(__type) __type
|
||||
#define JS_DLL_CALLBACK
|
||||
#define JS_STATIC_DLL_CALLBACK(__x) __x _Optlink
|
||||
|
||||
#else /* Unix */
|
||||
#define JS_EXTERN_API(__type) extern __type
|
||||
#define JS_EXPORT_API(__type) __type
|
||||
#define JS_EXTERN_DATA(__type) extern __type
|
||||
#define JS_EXPORT_DATA(__type) __type
|
||||
#define JS_DLL_CALLBACK
|
||||
#define JS_STATIC_DLL_CALLBACK(__x) static __x
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
# define JS_IMPORT_API(__x) _declspec(dllimport) __x
|
||||
#else
|
||||
# define JS_IMPORT_API(__x) JS_EXPORT_API (__x)
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
# define JS_IMPORT_DATA(__x) _declspec(dllimport) __x
|
||||
#else
|
||||
# define JS_IMPORT_DATA(__x) __x
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The linkage of JS API functions differs depending on whether the file is
|
||||
* used within the JS library or not. Any source file within the JS
|
||||
* interpreter should define EXPORT_JS_API whereas any client of the library
|
||||
* should not.
|
||||
*/
|
||||
#ifdef EXPORT_JS_API
|
||||
#define JS_PUBLIC_API(t) JS_EXPORT_API(t)
|
||||
#define JS_PUBLIC_DATA(t) JS_EXPORT_DATA(t)
|
||||
#else
|
||||
#define JS_PUBLIC_API(t) JS_IMPORT_API(t)
|
||||
#define JS_PUBLIC_DATA(t) JS_IMPORT_DATA(t)
|
||||
#endif
|
||||
|
||||
#define JS_FRIEND_API(t) JS_PUBLIC_API(t)
|
||||
#define JS_FRIEND_DATA(t) JS_PUBLIC_DATA(t)
|
||||
|
||||
#ifdef _WIN32
|
||||
# define JS_INLINE __inline
|
||||
#elif defined(__GNUC__)
|
||||
# define JS_INLINE
|
||||
#else
|
||||
# define JS_INLINE
|
||||
#endif
|
||||
|
||||
/***********************************************************************
|
||||
** MACROS: JS_BEGIN_MACRO
|
||||
** JS_END_MACRO
|
||||
** DESCRIPTION:
|
||||
** Macro body brackets so that macros with compound statement definitions
|
||||
** behave syntactically more like functions when called.
|
||||
***********************************************************************/
|
||||
#define JS_BEGIN_MACRO do {
|
||||
#define JS_END_MACRO } while (0)
|
||||
|
||||
/***********************************************************************
|
||||
** MACROS: JS_BEGIN_EXTERN_C
|
||||
** JS_END_EXTERN_C
|
||||
** DESCRIPTION:
|
||||
** Macro shorthands for conditional C++ extern block delimiters.
|
||||
***********************************************************************/
|
||||
#ifdef __cplusplus
|
||||
#define JS_BEGIN_EXTERN_C extern "C" {
|
||||
#define JS_END_EXTERN_C }
|
||||
#else
|
||||
#define JS_BEGIN_EXTERN_C
|
||||
#define JS_END_EXTERN_C
|
||||
#endif
|
||||
|
||||
/***********************************************************************
|
||||
** MACROS: JS_BIT
|
||||
** JS_BITMASK
|
||||
** DESCRIPTION:
|
||||
** Bit masking macros. XXX n must be <= 31 to be portable
|
||||
***********************************************************************/
|
||||
#define JS_BIT(n) ((JSUint32)1 << (n))
|
||||
#define JS_BITMASK(n) (JS_BIT(n) - 1)
|
||||
|
||||
/***********************************************************************
|
||||
** MACROS: JS_ROUNDUP
|
||||
** JS_MIN
|
||||
** JS_MAX
|
||||
** DESCRIPTION:
|
||||
** Commonly used macros for operations on compatible types.
|
||||
***********************************************************************/
|
||||
#define JS_ROUNDUP(x,y) ((((x)+((y)-1))/(y))*(y))
|
||||
#define JS_MIN(x,y) ((x)<(y)?(x):(y))
|
||||
#define JS_MAX(x,y) ((x)>(y)?(x):(y))
|
||||
|
||||
#if defined(XP_MAC) || defined(XP_PC)
|
||||
# include "jscpucfg.h" /* Use standard Mac or Windows configuration */
|
||||
#elif XP_UNIX
|
||||
# include "jsautocfg.h" /* Use auto-detected configuration */
|
||||
#else
|
||||
# error "Must define one of XP_PC, XP_MAC or XP_UNIX"
|
||||
#endif
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
/************************************************************************
|
||||
** TYPES: JSUint8
|
||||
** JSInt8
|
||||
** DESCRIPTION:
|
||||
** The int8 types are known to be 8 bits each. There is no type that
|
||||
** is equivalent to a plain "char".
|
||||
************************************************************************/
|
||||
#if JS_BYTES_PER_BYTE == 1
|
||||
typedef unsigned char JSUint8;
|
||||
typedef signed char JSInt8;
|
||||
#else
|
||||
#error No suitable type for JSInt8/JSUint8
|
||||
#endif
|
||||
|
||||
/************************************************************************
|
||||
** TYPES: JSUint16
|
||||
** JSInt16
|
||||
** DESCRIPTION:
|
||||
** The int16 types are known to be 16 bits each.
|
||||
************************************************************************/
|
||||
#if JS_BYTES_PER_SHORT == 2
|
||||
typedef unsigned short JSUint16;
|
||||
typedef short JSInt16;
|
||||
#else
|
||||
#error No suitable type for JSInt16/JSUint16
|
||||
#endif
|
||||
|
||||
/************************************************************************
|
||||
** TYPES: JSUint32
|
||||
** JSInt32
|
||||
** DESCRIPTION:
|
||||
** The int32 types are known to be 32 bits each.
|
||||
************************************************************************/
|
||||
#if JS_BYTES_PER_INT == 4
|
||||
typedef unsigned int JSUint32;
|
||||
typedef int JSInt32;
|
||||
#define JS_INT32(x) x
|
||||
#define JS_UINT32(x) x ## U
|
||||
#elif JS_BYTES_PER_LONG == 4
|
||||
typedef unsigned long JSUint32;
|
||||
typedef long JSInt32;
|
||||
#define JS_INT32(x) x ## L
|
||||
#define JS_UINT32(x) x ## UL
|
||||
#else
|
||||
#error No suitable type for JSInt32/JSUint32
|
||||
#endif
|
||||
|
||||
/************************************************************************
|
||||
** TYPES: JSUint64
|
||||
** JSInt64
|
||||
** DESCRIPTION:
|
||||
** The int64 types are known to be 64 bits each. Care must be used when
|
||||
** declaring variables of type JSUint64 or JSInt64. Different hardware
|
||||
** architectures and even different compilers have varying support for
|
||||
** 64 bit values. The only guaranteed portability requires the use of
|
||||
** the JSLL_ macros (see jslong.h).
|
||||
************************************************************************/
|
||||
#ifdef JS_HAVE_LONG_LONG
|
||||
#if JS_BYTES_PER_LONG == 8
|
||||
typedef long JSInt64;
|
||||
typedef unsigned long JSUint64;
|
||||
#elif defined(WIN16)
|
||||
typedef __int64 JSInt64;
|
||||
typedef unsigned __int64 JSUint64;
|
||||
#elif defined(WIN32)
|
||||
typedef __int64 JSInt64;
|
||||
typedef unsigned __int64 JSUint64;
|
||||
#else
|
||||
typedef long long JSInt64;
|
||||
typedef unsigned long long JSUint64;
|
||||
#endif /* JS_BYTES_PER_LONG == 8 */
|
||||
#else /* !JS_HAVE_LONG_LONG */
|
||||
typedef struct {
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
JSUint32 lo, hi;
|
||||
#else
|
||||
JSUint32 hi, lo;
|
||||
#endif
|
||||
} JSInt64;
|
||||
typedef JSInt64 JSUint64;
|
||||
#endif /* !JS_HAVE_LONG_LONG */
|
||||
|
||||
/************************************************************************
|
||||
** TYPES: JSUintn
|
||||
** JSIntn
|
||||
** DESCRIPTION:
|
||||
** The JSIntn types are most appropriate for automatic variables. They are
|
||||
** guaranteed to be at least 16 bits, though various architectures may
|
||||
** define them to be wider (e.g., 32 or even 64 bits). These types are
|
||||
** never valid for fields of a structure.
|
||||
************************************************************************/
|
||||
#if JS_BYTES_PER_INT >= 2
|
||||
typedef int JSIntn;
|
||||
typedef unsigned int JSUintn;
|
||||
#else
|
||||
#error 'sizeof(int)' not sufficient for platform use
|
||||
#endif
|
||||
|
||||
/************************************************************************
|
||||
** TYPES: JSFloat64
|
||||
** DESCRIPTION:
|
||||
** NSPR's floating point type is always 64 bits.
|
||||
************************************************************************/
|
||||
typedef double JSFloat64;
|
||||
|
||||
/************************************************************************
|
||||
** TYPES: JSSize
|
||||
** DESCRIPTION:
|
||||
** A type for representing the size of objects.
|
||||
************************************************************************/
|
||||
typedef size_t JSSize;
|
||||
|
||||
/************************************************************************
|
||||
** TYPES: JSPtrDiff
|
||||
** DESCRIPTION:
|
||||
** A type for pointer difference. Variables of this type are suitable
|
||||
** for storing a pointer or pointer sutraction.
|
||||
************************************************************************/
|
||||
typedef ptrdiff_t JSPtrdiff;
|
||||
|
||||
/************************************************************************
|
||||
** TYPES: JSUptrdiff
|
||||
** DESCRIPTION:
|
||||
** A type for pointer difference. Variables of this type are suitable
|
||||
** for storing a pointer or pointer sutraction.
|
||||
************************************************************************/
|
||||
typedef unsigned long JSUptrdiff;
|
||||
|
||||
/************************************************************************
|
||||
** TYPES: JSBool
|
||||
** DESCRIPTION:
|
||||
** Use JSBool for variables and parameter types. Use JS_FALSE and JS_TRUE
|
||||
** for clarity of target type in assignments and actual arguments. Use
|
||||
** 'if (bool)', 'while (!bool)', '(bool) ? x : y' etc., to test booleans
|
||||
** juast as you would C int-valued conditions.
|
||||
************************************************************************/
|
||||
typedef JSIntn JSBool;
|
||||
#define JS_TRUE (JSIntn)1
|
||||
#define JS_FALSE (JSIntn)0
|
||||
|
||||
/************************************************************************
|
||||
** TYPES: JSPackedBool
|
||||
** DESCRIPTION:
|
||||
** Use PRPackedBOol within structs where bitfields are not desireable
|
||||
** but minimum and consistant overhead matters.
|
||||
************************************************************************/
|
||||
typedef JSUint8 JSPackedBool;
|
||||
|
||||
/*
|
||||
** Status code used by some routines that have a single point of failure or
|
||||
** special status return.
|
||||
*/
|
||||
typedef enum { JS_FAILURE = -1, JS_SUCCESS = 0 } JSStatus;
|
||||
|
||||
/*
|
||||
** A JSWord is an integer that is the same size as a void*
|
||||
*/
|
||||
typedef long JSWord;
|
||||
typedef unsigned long JSUword;
|
||||
|
||||
#include "jsotypes.h"
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jstypes_h___ */
|
||||
|
||||
132
mozilla/js/src/jsutil.c
Normal file
132
mozilla/js/src/jsutil.c
Normal file
@@ -0,0 +1,132 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* PR assertion checker.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "jstypes.h"
|
||||
#include "jsutil.h"
|
||||
|
||||
#ifdef WIN32
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef XP_MAC
|
||||
# include <Types.h>
|
||||
# include <stdarg.h>
|
||||
# include "jsprf.h"
|
||||
#endif
|
||||
|
||||
#ifdef XP_MAC
|
||||
/*
|
||||
* PStrFromCStr converts the source C string to a destination
|
||||
* pascal string as it copies. The dest string will
|
||||
* be truncated to fit into an Str255 if necessary.
|
||||
* If the C String pointer is NULL, the pascal string's length is
|
||||
* set to zero.
|
||||
*/
|
||||
static void PStrFromCStr(const char* src, Str255 dst)
|
||||
{
|
||||
short length = 0;
|
||||
|
||||
/* handle case of overlapping strings */
|
||||
if ( (void*)src == (void*)dst )
|
||||
{
|
||||
unsigned char* curdst = &dst[1];
|
||||
unsigned char thisChar;
|
||||
|
||||
thisChar = *(const unsigned char*)src++;
|
||||
while ( thisChar != '\0' )
|
||||
{
|
||||
unsigned char nextChar;
|
||||
|
||||
/*
|
||||
* Use nextChar so we don't overwrite what we
|
||||
* are about to read
|
||||
*/
|
||||
nextChar = *(const unsigned char*)src++;
|
||||
*curdst++ = thisChar;
|
||||
thisChar = nextChar;
|
||||
|
||||
if ( ++length >= 255 )
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ( src != NULL )
|
||||
{
|
||||
unsigned char* curdst = &dst[1];
|
||||
/* count down so test it loop is faster */
|
||||
short overflow = 255;
|
||||
register char temp;
|
||||
|
||||
/*
|
||||
* Can't do the K&R C thing of while (*s++ = *t++)
|
||||
* because it will copy trailing zero which might
|
||||
* overrun pascal buffer. Instead we use a temp variable.
|
||||
*/
|
||||
while ( (temp = *src++) != 0 )
|
||||
{
|
||||
*(char*)curdst++ = temp;
|
||||
|
||||
if ( --overflow <= 0 )
|
||||
break;
|
||||
}
|
||||
length = 255 - overflow;
|
||||
}
|
||||
dst[0] = length;
|
||||
}
|
||||
|
||||
static void debugstr(const char *debuggerMsg)
|
||||
{
|
||||
Str255 pStr;
|
||||
|
||||
PStrFromCStr(debuggerMsg, pStr);
|
||||
DebugStr(pStr);
|
||||
}
|
||||
|
||||
static void dprintf(const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char *buffer;
|
||||
|
||||
va_start(ap, format);
|
||||
buffer = (char *)JS_vsmprintf(format, ap);
|
||||
va_end(ap);
|
||||
|
||||
debugstr(buffer);
|
||||
JS_DELETE(buffer);
|
||||
}
|
||||
#endif /* XP_MAC */
|
||||
|
||||
JS_EXPORT_API(void) JS_Assert(const char *s, const char *file, JSIntn ln)
|
||||
{
|
||||
#if defined(XP_UNIX) || defined(XP_OS2)
|
||||
fprintf(stderr, "Assertion failure: %s, at %s:%d\n", s, file, ln);
|
||||
#endif
|
||||
#ifdef XP_MAC
|
||||
dprintf("Assertion failure: %s, at %s:%d\n", s, file, ln);
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
DebugBreak();
|
||||
#endif
|
||||
#ifndef XP_MAC
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
84
mozilla/js/src/jsutil.h
Normal file
84
mozilla/js/src/jsutil.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* PR assertion checker.
|
||||
*/
|
||||
|
||||
#ifndef jsutil_h___
|
||||
#define jsutil_h___
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
/***********************************************************************
|
||||
** FUNCTION: JS_MALLOC()
|
||||
** DESCRIPTION:
|
||||
** JS_NEW() allocates an untyped item of size _size from the heap.
|
||||
** INPUTS: _size: size in bytes of item to be allocated
|
||||
** OUTPUTS: untyped pointer to the node allocated
|
||||
** RETURN: pointer to node or error returned from malloc().
|
||||
***********************************************************************/
|
||||
#define JS_MALLOC(_bytes) (malloc((_bytes)))
|
||||
|
||||
/***********************************************************************
|
||||
** FUNCTION: JS_DELETE()
|
||||
** DESCRIPTION:
|
||||
** JS_DELETE() unallocates an object previosly allocated via JS_NEW()
|
||||
** or JS_NEWZAP() to the heap.
|
||||
** INPUTS: pointer to previously allocated object
|
||||
** OUTPUTS: the referenced object is returned to the heap
|
||||
** RETURN: void
|
||||
***********************************************************************/
|
||||
#define JS_DELETE(_ptr) { free(_ptr); (_ptr) = NULL; }
|
||||
|
||||
/***********************************************************************
|
||||
** FUNCTION: JS_NEW()
|
||||
** DESCRIPTION:
|
||||
** JS_NEW() allocates an item of type _struct from the heap.
|
||||
** INPUTS: _struct: a data type
|
||||
** OUTPUTS: pointer to _struct
|
||||
** RETURN: pointer to _struct or error returns from malloc().
|
||||
***********************************************************************/
|
||||
#define JS_NEW(_struct) ((_struct *) JS_MALLOC(sizeof(_struct)))
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
JS_EXTERN_API(void) JS_Assert(const char *s, const char *file, JSIntn ln);
|
||||
#define JS_ASSERT(_expr) \
|
||||
((_expr)?((void)0):JS_Assert(# _expr,__FILE__,__LINE__))
|
||||
|
||||
#define JS_NOT_REACHED(_reasonStr) \
|
||||
JS_Assert(_reasonStr,__FILE__,__LINE__)
|
||||
|
||||
#else
|
||||
|
||||
#define JS_ASSERT(expr) ((void) 0)
|
||||
#define JS_NOT_REACHED(reasonStr)
|
||||
|
||||
#endif /* defined(DEBUG) */
|
||||
|
||||
/*
|
||||
** Abort the process in a non-graceful manner. This will cause a core file,
|
||||
** call to the debugger or other moral equivalent as well as causing the
|
||||
** entire process to stop.
|
||||
*/
|
||||
JS_EXTERN_API(void) JS_Abort(void);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsutil_h___ */
|
||||
559
mozilla/js/src/jsxdrapi.c
Normal file
559
mozilla/js/src/jsxdrapi.c
Normal file
@@ -0,0 +1,559 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
#include "jsstddef.h"
|
||||
|
||||
#include <string.h>
|
||||
#include "jstypes.h"
|
||||
#include "jsutil.h" /* Added by JSIFY */
|
||||
#include "jsprf.h"
|
||||
#include "jsapi.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsobj.h" /* js_XDRObject */
|
||||
#include "jsstr.h"
|
||||
#include "jsxdrapi.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DBG(x) x
|
||||
#else
|
||||
#define DBG(x) ((void)0)
|
||||
#endif
|
||||
|
||||
typedef struct JSXDRMemState {
|
||||
JSXDRState state;
|
||||
uint32 count;
|
||||
uint32 limit;
|
||||
} JSXDRMemState;
|
||||
|
||||
#define MEM_BLOCK 8192
|
||||
#define MEM_PRIV(xdr) ((JSXDRMemState *)(xdr))
|
||||
|
||||
#define MEM_COUNT(xdr) (MEM_PRIV(xdr)->count)
|
||||
#define MEM_LIMIT(xdr) (MEM_PRIV(xdr)->limit)
|
||||
|
||||
|
||||
#define MEM_LEFT(xdr, bytes) \
|
||||
JS_BEGIN_MACRO \
|
||||
if ((xdr)->mode == JSXDR_DECODE && \
|
||||
MEM_COUNT(xdr) + bytes > MEM_LIMIT(xdr)) { \
|
||||
JS_ReportErrorNumber((xdr)->cx, js_GetErrorMessage, NULL, \
|
||||
JSMSG_END_OF_DATA); \
|
||||
return 0; \
|
||||
} \
|
||||
JS_END_MACRO
|
||||
|
||||
/* XXXbe why does NEED even allow or cope with non-ENCODE mode? */
|
||||
#define MEM_NEED(xdr, bytes) \
|
||||
JS_BEGIN_MACRO \
|
||||
if ((xdr)->mode == JSXDR_ENCODE) { \
|
||||
if (MEM_LIMIT(xdr) && \
|
||||
MEM_COUNT(xdr) + bytes > MEM_LIMIT(xdr)) { \
|
||||
void *_data = JS_realloc((xdr)->cx, \
|
||||
(xdr)->data, \
|
||||
MEM_LIMIT(xdr) + MEM_BLOCK); \
|
||||
if (!_data) \
|
||||
return 0; \
|
||||
(xdr)->data = _data; \
|
||||
MEM_LIMIT(xdr) += MEM_BLOCK; \
|
||||
} \
|
||||
} else { \
|
||||
if (MEM_LIMIT(xdr) < MEM_COUNT(xdr) + bytes) { \
|
||||
JS_ReportErrorNumber((xdr)->cx, js_GetErrorMessage, NULL, \
|
||||
JSMSG_END_OF_DATA); \
|
||||
return 0; \
|
||||
} \
|
||||
} \
|
||||
JS_END_MACRO
|
||||
|
||||
#define MEM_DATA(xdr) ((void *)((char *)(xdr)->data + MEM_COUNT(xdr)))
|
||||
#define MEM_INCR(xdr,bytes) (MEM_COUNT(xdr) += (bytes))
|
||||
|
||||
static JSBool
|
||||
mem_get32(JSXDRState *xdr, uint32 *lp)
|
||||
{
|
||||
MEM_LEFT(xdr, 4);
|
||||
*lp = *(uint32 *)MEM_DATA(xdr);
|
||||
MEM_INCR(xdr, 4);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
mem_set32(JSXDRState *xdr, uint32 *lp)
|
||||
{
|
||||
MEM_NEED(xdr, 4);
|
||||
*(uint32 *)MEM_DATA(xdr) = *lp;
|
||||
MEM_INCR(xdr, 4);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
mem_getbytes(JSXDRState *xdr, char **bytesp, uint32 len)
|
||||
{
|
||||
MEM_LEFT(xdr, len);
|
||||
memcpy(*bytesp, MEM_DATA(xdr), len);
|
||||
MEM_INCR(xdr, len);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
mem_setbytes(JSXDRState *xdr, char **bytesp, uint32 len)
|
||||
{
|
||||
MEM_NEED(xdr, len);
|
||||
memcpy(MEM_DATA(xdr), *bytesp, len);
|
||||
MEM_INCR(xdr, len);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static void *
|
||||
mem_raw(JSXDRState *xdr, uint32 len)
|
||||
{
|
||||
void *data;
|
||||
if (xdr->mode == JSXDR_ENCODE) {
|
||||
MEM_NEED(xdr, len);
|
||||
} else if (xdr->mode == JSXDR_DECODE) {
|
||||
MEM_LEFT(xdr, len);
|
||||
}
|
||||
data = MEM_DATA(xdr);
|
||||
MEM_INCR(xdr, len);
|
||||
return data;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
mem_seek(JSXDRState *xdr, int32 offset, JSXDRWhence whence)
|
||||
{
|
||||
switch (whence) {
|
||||
case JSXDR_SEEK_CUR:
|
||||
if ((int32)MEM_COUNT(xdr) + offset < 0) {
|
||||
JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_SEEK_BEYOND_START);
|
||||
return JS_FALSE;
|
||||
}
|
||||
if (offset > 0)
|
||||
MEM_NEED(xdr, offset);
|
||||
MEM_COUNT(xdr) += offset;
|
||||
return JS_TRUE;
|
||||
case JSXDR_SEEK_SET:
|
||||
if (offset < 0) {
|
||||
JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_SEEK_BEYOND_START);
|
||||
return JS_FALSE;
|
||||
}
|
||||
if (xdr->mode == JSXDR_ENCODE) {
|
||||
if ((uint32)offset > MEM_COUNT(xdr))
|
||||
MEM_NEED(xdr, offset - MEM_COUNT(xdr));
|
||||
MEM_COUNT(xdr) = offset;
|
||||
} else {
|
||||
if ((uint32)offset > MEM_LIMIT(xdr)) {
|
||||
JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_SEEK_BEYOND_END);
|
||||
return JS_FALSE;
|
||||
}
|
||||
MEM_COUNT(xdr) = offset;
|
||||
}
|
||||
return JS_TRUE;
|
||||
case JSXDR_SEEK_END:
|
||||
if (offset >= 0 ||
|
||||
xdr->mode == JSXDR_ENCODE ||
|
||||
(int32)MEM_LIMIT(xdr) + offset < 0) {
|
||||
JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_END_SEEK);
|
||||
return JS_FALSE;
|
||||
}
|
||||
MEM_COUNT(xdr) = MEM_LIMIT(xdr) + offset;
|
||||
return JS_TRUE;
|
||||
default: {
|
||||
char numBuf[12];
|
||||
JS_snprintf(numBuf, sizeof numBuf, "%d", whence);
|
||||
JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_WHITHER_WHENCE, numBuf);
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint32
|
||||
mem_tell(JSXDRState *xdr)
|
||||
{
|
||||
return MEM_COUNT(xdr);
|
||||
}
|
||||
|
||||
static void
|
||||
mem_finalize(JSXDRState *xdr)
|
||||
{
|
||||
JSContext *cx = xdr->cx;
|
||||
JS_free(cx, xdr->data);
|
||||
}
|
||||
|
||||
static JSXDROps xdrmem_ops = {
|
||||
mem_get32, mem_set32, mem_getbytes, mem_setbytes,
|
||||
mem_raw, mem_seek, mem_tell, mem_finalize
|
||||
};
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_XDRNewBase(JSContext *cx, JSXDRState *xdr, JSXDRMode mode)
|
||||
{
|
||||
xdr->cx = cx;
|
||||
xdr->mode = mode;
|
||||
xdr->registry = NULL;
|
||||
xdr->nclasses = 0;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSXDRState *)
|
||||
JS_XDRNewMem(JSContext *cx, JSXDRMode mode)
|
||||
{
|
||||
JSXDRState *xdr = JS_malloc(cx, sizeof(JSXDRMemState));
|
||||
if (!xdr)
|
||||
return NULL;
|
||||
JS_XDRNewBase(cx, xdr, mode);
|
||||
if (mode == JSXDR_ENCODE) {
|
||||
if (!(xdr->data = JS_malloc(cx, MEM_BLOCK))) {
|
||||
JS_free(cx, xdr);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
/* XXXbe ok, so better not deref xdr->data if not ENCODE */
|
||||
xdr->data = NULL;
|
||||
}
|
||||
xdr->ops = &xdrmem_ops;
|
||||
MEM_PRIV(xdr)->count = 0;
|
||||
MEM_PRIV(xdr)->limit = MEM_BLOCK;
|
||||
return xdr;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void *)
|
||||
JS_XDRMemGetData(JSXDRState *xdr, uint32 *lp)
|
||||
{
|
||||
if (xdr->ops != &xdrmem_ops)
|
||||
return NULL;
|
||||
*lp = MEM_PRIV(xdr)->count;
|
||||
return xdr->data;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_XDRMemSetData(JSXDRState *xdr, void *data, uint32 len)
|
||||
{
|
||||
if (xdr->ops != &xdrmem_ops)
|
||||
return;
|
||||
MEM_PRIV(xdr)->limit = len;
|
||||
xdr->data = data;
|
||||
MEM_PRIV(xdr)->count = 0;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_XDRUint8(JSXDRState *xdr, uint8 *b)
|
||||
{
|
||||
uint32 l = *b;
|
||||
if (!JS_XDRUint32(xdr, &l))
|
||||
return JS_FALSE;
|
||||
*b = (uint8) l & 0xff;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_XDRUint16(JSXDRState *xdr, uint16 *s)
|
||||
{
|
||||
uint32 l = *s;
|
||||
if (!JS_XDRUint32(xdr, &l))
|
||||
return JS_FALSE;
|
||||
*s = (uint16) l & 0xffff;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_XDRUint32(JSXDRState *xdr, uint32 *lp)
|
||||
{
|
||||
JSBool ok = JS_FALSE;
|
||||
if (xdr->mode == JSXDR_ENCODE) {
|
||||
uint32 xl = JSXDR_SWAB32(*lp);
|
||||
ok = xdr->ops->set32(xdr, &xl);
|
||||
} else if (xdr->mode == JSXDR_DECODE) {
|
||||
ok = xdr->ops->get32(xdr, lp);
|
||||
*lp = JSXDR_SWAB32(*lp);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_XDRBytes(JSXDRState *xdr, char **bytesp, uint32 len)
|
||||
{
|
||||
if (xdr->mode == JSXDR_ENCODE) {
|
||||
if (!xdr->ops->setbytes(xdr, bytesp, len))
|
||||
return JS_FALSE;
|
||||
} else {
|
||||
if (!xdr->ops->getbytes(xdr, bytesp, len))
|
||||
return JS_FALSE;
|
||||
}
|
||||
len = xdr->ops->tell(xdr);
|
||||
if (len % JSXDR_ALIGN) {
|
||||
if (!xdr->ops->seek(xdr, JSXDR_ALIGN - (len % JSXDR_ALIGN),
|
||||
JSXDR_SEEK_CUR)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert between a C string and the XDR representation:
|
||||
* leading 32-bit count, then counted vector of chars,
|
||||
* then possibly \0 padding to multiple of 4.
|
||||
*/
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_XDRCString(JSXDRState *xdr, char **sp)
|
||||
{
|
||||
uint32 len;
|
||||
|
||||
if (xdr->mode == JSXDR_ENCODE)
|
||||
len = strlen(*sp);
|
||||
JS_XDRUint32(xdr, &len);
|
||||
if (xdr->mode == JSXDR_DECODE) {
|
||||
if (!(*sp = JS_malloc(xdr->cx, len + 1)))
|
||||
return JS_FALSE;
|
||||
}
|
||||
if (!JS_XDRBytes(xdr, sp, len)) {
|
||||
if (xdr->mode == JSXDR_DECODE)
|
||||
JS_free(xdr->cx, *sp);
|
||||
return JS_FALSE;
|
||||
}
|
||||
if (xdr->mode == JSXDR_DECODE) {
|
||||
(*sp)[len] = '\0';
|
||||
} else if (xdr->mode == JSXDR_FREE) {
|
||||
JS_free(xdr->cx, *sp);
|
||||
*sp = NULL;
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_XDRCStringOrNull(JSXDRState *xdr, char **sp)
|
||||
{
|
||||
uint32 null = (*sp == NULL);
|
||||
if (!JS_XDRUint32(xdr, &null))
|
||||
return JS_FALSE;
|
||||
if (null) {
|
||||
*sp = NULL;
|
||||
return JS_TRUE;
|
||||
}
|
||||
return JS_XDRCString(xdr, sp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert between a JS (Unicode) string and the XDR representation.
|
||||
*/
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_XDRString(JSXDRState *xdr, JSString **strp)
|
||||
{
|
||||
uint32 i, len, nbytes;
|
||||
jschar *chars = NULL, *raw;
|
||||
|
||||
if (xdr->mode == JSXDR_ENCODE)
|
||||
len = (*strp)->length;
|
||||
if (!JS_XDRUint32(xdr, &len))
|
||||
return JS_FALSE;
|
||||
nbytes = len * sizeof(jschar);
|
||||
|
||||
if (xdr->mode == JSXDR_ENCODE) {
|
||||
chars = (*strp)->chars;
|
||||
} else if (xdr->mode == JSXDR_DECODE) {
|
||||
if (!(chars = JS_malloc(xdr->cx, nbytes + sizeof(jschar))))
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (nbytes % JSXDR_ALIGN)
|
||||
nbytes += JSXDR_ALIGN - (nbytes % JSXDR_ALIGN);
|
||||
if (!(raw = xdr->ops->raw(xdr, nbytes)))
|
||||
goto bad;
|
||||
if (xdr->mode == JSXDR_ENCODE) {
|
||||
for (i = 0; i < len; i++)
|
||||
raw[i] = JSXDR_SWAB16(chars[i]);
|
||||
} else if (xdr->mode == JSXDR_DECODE) {
|
||||
for (i = 0; i < len; i++)
|
||||
chars[i] = JSXDR_SWAB16(raw[i]);
|
||||
if (!(*strp = JS_NewUCString(xdr->cx, chars, len)))
|
||||
goto bad;
|
||||
}
|
||||
return JS_TRUE;
|
||||
|
||||
bad:
|
||||
if (xdr->mode == JSXDR_DECODE)
|
||||
JS_free(xdr->cx, chars);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_XDRStringOrNull(JSXDRState *xdr, JSString **strp)
|
||||
{
|
||||
uint32 null = (*strp == NULL);
|
||||
if (!JS_XDRUint32(xdr, &null))
|
||||
return JS_FALSE;
|
||||
if (null) {
|
||||
*strp = NULL;
|
||||
return JS_TRUE;
|
||||
}
|
||||
return JS_XDRString(xdr, strp);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_XDRDouble(JSXDRState *xdr, jsdouble **dp)
|
||||
{
|
||||
jsdouble d;
|
||||
if (xdr->mode == JSXDR_ENCODE)
|
||||
d = **dp;
|
||||
#if IS_BIG_ENDIAN
|
||||
if (!JS_XDRUint32(xdr, (uint32 *)&d + 1) ||
|
||||
!JS_XDRUint32(xdr, (uint32 *)&d))
|
||||
#else /* !IS_BIG_ENDIAN */
|
||||
if (!JS_XDRUint32(xdr, (uint32 *)&d) ||
|
||||
!JS_XDRUint32(xdr, (uint32 *)&d + 1))
|
||||
#endif /* IS_BIG_ENDIAN */
|
||||
return JS_FALSE;
|
||||
if (xdr->mode == JSXDR_DECODE) {
|
||||
*dp = JS_NewDouble(xdr->cx, d);
|
||||
if (!*dp)
|
||||
return JS_FALSE;
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_XDRValue(JSXDRState *xdr, jsval *vp)
|
||||
{
|
||||
uint32 type = JSVAL_TAG(*vp);
|
||||
if (!JS_XDRUint32(xdr, &type))
|
||||
return JS_FALSE;
|
||||
|
||||
switch (type) {
|
||||
case JSVAL_STRING: {
|
||||
JSString *str = JSVAL_TO_STRING(*vp);
|
||||
if (!JS_XDRString(xdr, &str))
|
||||
return JS_FALSE;
|
||||
if (xdr->mode == JSXDR_DECODE)
|
||||
*vp = STRING_TO_JSVAL(str);
|
||||
break;
|
||||
}
|
||||
case JSVAL_DOUBLE: {
|
||||
jsdouble *dp;
|
||||
if (xdr->mode == JSXDR_ENCODE)
|
||||
dp = JSVAL_TO_DOUBLE(*vp);
|
||||
if (!JS_XDRDouble(xdr, &dp))
|
||||
return JS_FALSE;
|
||||
if (xdr->mode == JSXDR_DECODE)
|
||||
*vp = DOUBLE_TO_JSVAL(dp);
|
||||
break;
|
||||
}
|
||||
case JSVAL_OBJECT: {
|
||||
JSObject *obj;
|
||||
if (xdr->mode == JSXDR_ENCODE)
|
||||
obj = JSVAL_TO_OBJECT(*vp);
|
||||
if (!js_XDRObject(xdr, &obj))
|
||||
return JS_FALSE;
|
||||
if (xdr->mode == JSXDR_DECODE)
|
||||
*vp = OBJECT_TO_JSVAL(obj);
|
||||
break;
|
||||
}
|
||||
case JSVAL_BOOLEAN: {
|
||||
uint32 b;
|
||||
if (xdr->mode == JSXDR_ENCODE)
|
||||
b = (uint32)JSVAL_TO_BOOLEAN(*vp);
|
||||
if (!JS_XDRUint32(xdr, &b))
|
||||
return JS_FALSE;
|
||||
if (xdr->mode == JSXDR_DECODE)
|
||||
*vp = BOOLEAN_TO_JSVAL((JSBool)b);
|
||||
break;
|
||||
}
|
||||
case JSVAL_VOID:
|
||||
if (!JS_XDRUint32(xdr, (uint32 *)vp))
|
||||
return JS_FALSE;
|
||||
break;
|
||||
default: {
|
||||
char numBuf[12];
|
||||
if (type & JSVAL_INT) {
|
||||
uint32 i;
|
||||
if (xdr->mode == JSXDR_ENCODE)
|
||||
i = JSVAL_TO_INT(*vp);
|
||||
if (!JS_XDRUint32(xdr, &i))
|
||||
return JS_FALSE;
|
||||
if (xdr->mode == JSXDR_DECODE)
|
||||
*vp = INT_TO_JSVAL(i);
|
||||
break;
|
||||
}
|
||||
JS_snprintf(numBuf, sizeof numBuf, "%#lx", type);
|
||||
JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_BAD_JVAL_TYPE, type);
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_XDRDestroy(JSXDRState *xdr)
|
||||
{
|
||||
JSContext *cx = xdr->cx;
|
||||
xdr->ops->finalize(xdr);
|
||||
if (xdr->registry)
|
||||
JS_free(cx, xdr->registry);
|
||||
JS_free(cx, xdr);
|
||||
}
|
||||
|
||||
#define REGISTRY_CHUNK 4
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_RegisterClass(JSXDRState *xdr, JSClass *clasp, uint32 *idp)
|
||||
{
|
||||
uintN nclasses;
|
||||
JSClass **registry;
|
||||
|
||||
nclasses = xdr->nclasses;
|
||||
if (nclasses == 0) {
|
||||
registry = JS_malloc(xdr->cx, REGISTRY_CHUNK * sizeof(JSClass *));
|
||||
} else if (nclasses % REGISTRY_CHUNK == 0) {
|
||||
registry = JS_realloc(xdr->cx,
|
||||
xdr->registry,
|
||||
(nclasses + REGISTRY_CHUNK) * sizeof(JSClass *));
|
||||
} else {
|
||||
registry = xdr->registry;
|
||||
}
|
||||
if (!registry)
|
||||
return JS_FALSE;
|
||||
registry[nclasses++] = clasp;
|
||||
xdr->registry = registry;
|
||||
xdr->nclasses = nclasses;
|
||||
*idp = nclasses;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(uint32)
|
||||
JS_FindClassIdByName(JSXDRState *xdr, const char *name)
|
||||
{
|
||||
uintN i;
|
||||
|
||||
for (i = 0; i < xdr->nclasses; i++) {
|
||||
if (!strcmp(name, xdr->registry[i]->name))
|
||||
return i+1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSClass *)
|
||||
JS_FindClassById(JSXDRState *xdr, uint32 id)
|
||||
{
|
||||
if (id > xdr->nclasses)
|
||||
return NULL;
|
||||
return xdr->registry[id-1];
|
||||
}
|
||||
158
mozilla/js/src/jsxdrapi.h
Normal file
158
mozilla/js/src/jsxdrapi.h
Normal file
@@ -0,0 +1,158 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef jsxdrapi_h___
|
||||
#define jsxdrapi_h___
|
||||
|
||||
/*
|
||||
* JS external data representation interface API.
|
||||
*
|
||||
* The XDR system is comprised of three major parts:
|
||||
*
|
||||
* - the state serialization/deserialization APIs, which allow consumers
|
||||
* of the API to serialize JS runtime state (script bytecodes, atom maps,
|
||||
* object graphs, etc.) for later restoration. These portions
|
||||
* are implemented in various appropriate files, such as jsscript.c
|
||||
* for the script portions and jsobj.c for object state.
|
||||
* - the callback APIs through which the runtime requests an opaque
|
||||
* representation of a native object, and through which the runtime
|
||||
* constructs a live native object from an opaque representation. These
|
||||
* portions are the responsibility of the native object implementor.
|
||||
* - utility functions for en/decoding of primitive types, such as
|
||||
* JSStrings. This portion is implemented in jsxdrapi.c.
|
||||
*
|
||||
* Spiritually guided by Sun's XDR, where appropriate.
|
||||
*/
|
||||
|
||||
#include "jspubtd.h"
|
||||
#include "jsprvtd.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
/* We use little-endian byteorder for all encoded data */
|
||||
|
||||
#if defined IS_LITTLE_ENDIAN
|
||||
#define JSXDR_SWAB32(x) x
|
||||
#define JSXDR_SWAB16(x) x
|
||||
#elif defined IS_BIG_ENDIAN
|
||||
#define JSXDR_SWAB32(x) (((x) >> 24) | \
|
||||
(((x) >> 8) & 0xff00) | \
|
||||
(((x) << 8) & 0xff0000) | \
|
||||
((x) << 24))
|
||||
#define JSXDR_SWAB16(x) (((x) >> 8) | ((x) << 8))
|
||||
#else
|
||||
#error "unknown byte order"
|
||||
#endif
|
||||
|
||||
#define JSXDR_ALIGN 4
|
||||
|
||||
typedef enum JSXDRMode {
|
||||
JSXDR_ENCODE,
|
||||
JSXDR_DECODE,
|
||||
JSXDR_FREE
|
||||
} JSXDRMode;
|
||||
|
||||
typedef enum JSXDRWhence {
|
||||
JSXDR_SEEK_SET,
|
||||
JSXDR_SEEK_CUR,
|
||||
JSXDR_SEEK_END
|
||||
} JSXDRWhence;
|
||||
|
||||
typedef struct JSXDROps {
|
||||
JSBool (*get32)(JSXDRState *, uint32 *);
|
||||
JSBool (*set32)(JSXDRState *, uint32 *);
|
||||
JSBool (*getbytes)(JSXDRState *, char **, uint32);
|
||||
JSBool (*setbytes)(JSXDRState *, char **, uint32);
|
||||
void * (*raw)(JSXDRState *, uint32);
|
||||
JSBool (*seek)(JSXDRState *, int32, JSXDRWhence);
|
||||
uint32 (*tell)(JSXDRState *);
|
||||
void (*finalize)(JSXDRState *);
|
||||
} JSXDROps;
|
||||
|
||||
struct JSXDRState {
|
||||
JSXDRMode mode;
|
||||
JSXDROps *ops;
|
||||
JSContext *cx;
|
||||
JSClass **registry;
|
||||
uintN nclasses;
|
||||
void *data;
|
||||
};
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_XDRNewBase(JSContext *cx, JSXDRState *xdr, JSXDRMode mode);
|
||||
|
||||
JS_PUBLIC_API(JSXDRState *)
|
||||
JS_XDRNewMem(JSContext *cx, JSXDRMode mode);
|
||||
|
||||
JS_PUBLIC_API(void *)
|
||||
JS_XDRMemGetData(JSXDRState *xdr, uint32 *lp);
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_XDRMemSetData(JSXDRState *xdr, void *data, uint32 len);
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_XDRDestroy(JSXDRState *xdr);
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_XDRUint8(JSXDRState *xdr, uint8 *b);
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_XDRUint16(JSXDRState *xdr, uint16 *s);
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_XDRUint32(JSXDRState *xdr, uint32 *lp);
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_XDRBytes(JSXDRState *xdr, char **bytes, uint32 len);
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_XDRCString(JSXDRState *xdr, char **sp);
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_XDRCStringOrNull(JSXDRState *xdr, char **sp);
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_XDRString(JSXDRState *xdr, JSString **strp);
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_XDRStringOrNull(JSXDRState *xdr, JSString **strp);
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_XDRDouble(JSXDRState *xdr, jsdouble **dp);
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_XDRValue(JSXDRState *xdr, jsval *vp);
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_RegisterClass(JSXDRState *xdr, JSClass *clasp, uint32 *lp);
|
||||
|
||||
JS_PUBLIC_API(uint32)
|
||||
JS_FindClassIdByName(JSXDRState *xdr, const char *name);
|
||||
|
||||
JS_PUBLIC_API(JSClass *)
|
||||
JS_FindClassById(JSXDRState *xdr, uint32 id);
|
||||
|
||||
/* Magic values */
|
||||
|
||||
#define OBJ_XDRMAGIC 0xdead1000
|
||||
#define OBJ_XDRTYPE_OBJ 0xdead1001
|
||||
#define OBJ_XDRTYPE_FUN 0xdead1002
|
||||
#define OBJ_XDRTYPE_REGEXP 0xdead1003
|
||||
#define SCRIPT_XDRMAGIC 0xdead0001
|
||||
|
||||
#endif /* ! jsxdrapi_h___ */
|
||||
79
mozilla/js/src/lock_SunOS.s
Normal file
79
mozilla/js/src/lock_SunOS.s
Normal file
@@ -0,0 +1,79 @@
|
||||
!
|
||||
! atomic compare-and-swap routines for V8 sparc
|
||||
! and for V8+ (ultrasparc)
|
||||
!
|
||||
!
|
||||
! standard asm linkage macros; this module must be compiled
|
||||
! with the -P option (use C preprocessor)
|
||||
|
||||
#include <sys/asm_linkage.h>
|
||||
|
||||
! ======================================================================
|
||||
!
|
||||
! Perform the sequence *a = b atomically with respect to previous value
|
||||
! of a (a0). If *a==a0 then assign *a to b, all in one atomic operation.
|
||||
! Returns 1 if assignment happened, and 0 otherwise.
|
||||
!
|
||||
! usage : old_val = compare_and_swap(address, oldval, newval)
|
||||
!
|
||||
! -----------------------
|
||||
! Note on REGISTER USAGE:
|
||||
! as this is a LEAF procedure, a new stack frame is not created;
|
||||
! we use the caller stack frame so what would normally be %i (input)
|
||||
! registers are actually %o (output registers). Also, we must not
|
||||
! overwrite the contents of %l (local) registers as they are not
|
||||
! assumed to be volatile during calls.
|
||||
!
|
||||
! So, the registers used are:
|
||||
! %o0 [input] - the address of the value to increment
|
||||
! %o1 [input] - the old value to compare with
|
||||
! %o2 [input] - the new value to set for [%o0]
|
||||
! %o3 [local] - work register
|
||||
! -----------------------
|
||||
#ifndef ULTRA_SPARC
|
||||
! v8
|
||||
|
||||
ENTRY(compare_and_swap) ! standard assembler/ELF prologue
|
||||
|
||||
mov -1,%o3 ! busy flag
|
||||
swap [%o0],%o3 ! get current value
|
||||
l1: cmp %o3,-1 ! busy?
|
||||
be,a l1 ! if so, spin
|
||||
swap [%o0],%o3 ! using branch-delay to swap back value
|
||||
cmp %o1,%o3 ! compare old with current
|
||||
be,a l2 ! if equal then swap in new value
|
||||
swap [%o0],%o2 ! done.
|
||||
swap [%o0],%o3 ! otherwise, swap back current value
|
||||
retl
|
||||
mov 0,%o0 ! return false
|
||||
l2: retl
|
||||
mov 1,%o0 ! return true
|
||||
|
||||
SET_SIZE(compare_and_swap) ! standard assembler/ELF epilogue
|
||||
|
||||
!
|
||||
! end
|
||||
!
|
||||
#else /* ULTRA_SPARC */
|
||||
! ======================================================================
|
||||
!
|
||||
! v9
|
||||
|
||||
ENTRY(compare_and_swap) ! standard assembler/ELF prologue
|
||||
|
||||
cas [%o0],%o1,%o2 ! compare *w with old value and set to new if equal
|
||||
cmp %o1,%o2 ! did we succeed?
|
||||
be,a m1 ! yes
|
||||
mov 1,%o0 ! return true (annulled when no jump)
|
||||
mov 0,%o0 ! return false
|
||||
m1: retl
|
||||
nop
|
||||
|
||||
SET_SIZE(compare_and_swap) ! standard assembler/ELF epilogue
|
||||
|
||||
!
|
||||
! end
|
||||
!
|
||||
! ======================================================================
|
||||
!
|
||||
#endif
|
||||
196
mozilla/js/src/makefile.win
Normal file
196
mozilla/js/src/makefile.win
Normal file
@@ -0,0 +1,196 @@
|
||||
#// The contents of this file are subject to the Netscape Public License
|
||||
#// Version 1.0 (the "NPL"); you may not use this file except in
|
||||
#// compliance with the NPL. You may obtain a copy of the NPL at
|
||||
#// http://www.mozilla.org/NPL/
|
||||
#//
|
||||
#// Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
#// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
#// for the specific language governing rights and limitations under the
|
||||
#// NPL.
|
||||
#//
|
||||
#// The Initial Developer of this code under the NPL is Netscape
|
||||
#// Communications Corporation. Portions created by Netscape are
|
||||
#// Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
#// Reserved.
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#//
|
||||
#// Specify the depth of the current directory relative to the
|
||||
#// root of NS
|
||||
#//
|
||||
#//------------------------------------------------------------------------
|
||||
DEPTH=..\..
|
||||
include <$(DEPTH)\config\config.mak>
|
||||
|
||||
!ifdef MOZ_OJI
|
||||
DIRS = liveconnect
|
||||
!endif
|
||||
|
||||
DIRS = $(DIRS) fdlibm
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#//
|
||||
#// Define any Public Make Variables here: (ie. PDFFILE, MAPFILE, ...)
|
||||
#//
|
||||
#//------------------------------------------------------------------------
|
||||
|
||||
DLLNAME = js$(MOZ_BITS)$(VERSION_NUMBER)
|
||||
DLL1NAME = js1$(MOZ_BITS)$(VERSION_NUMBER)
|
||||
PDBFILE = $(DLLNAME).pdb
|
||||
MAPFILE = $(DLLNAME).map
|
||||
RESFILE = js$(MOZ_BITS)40.res
|
||||
DLL =.\$(OBJDIR)\$(DLLNAME).dll
|
||||
MAKE_OBJ_TYPE = DLL
|
||||
|
||||
!if "$(MOZ_BITS)" != "16"
|
||||
LINCS = -I$(PUBLIC)\layout \
|
||||
-I$(DEPTH)\include \
|
||||
-I$(PUBLIC)\liblayer
|
||||
!endif
|
||||
|
||||
!if "$(MOZ_BITS)" == "16"
|
||||
!ifdef NSPR20
|
||||
DEFFILE = $(DLL1NAME).def
|
||||
!else
|
||||
DEFFILE = $(DLLNAME).def
|
||||
!endif
|
||||
!endif
|
||||
|
||||
FDLIBM_LIBRARY = fdlibm\$(OBJDIR)\fdlibm.lib
|
||||
|
||||
LLIBS=$(LIBNSPR) $(FDLIBM_LIBRARY)
|
||||
LCFLAGS= $(LCFLAGS) -DEXPORT_JS_API
|
||||
!if "$(MOZ_BITS)"=="32" && defined(MOZ_DEBUG) && defined(GLOWCODE)
|
||||
LLIBS=$(LLIBS) $(GLOWDIR)\glowcode.lib
|
||||
!endif
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#//
|
||||
#// Define the files necessary to build the target (ie. OBJS)
|
||||
#//
|
||||
#//------------------------------------------------------------------------
|
||||
OBJS = \
|
||||
.\$(OBJDIR)\jsapi.obj \
|
||||
.\$(OBJDIR)\jsarena.obj \
|
||||
.\$(OBJDIR)\jsarray.obj \
|
||||
.\$(OBJDIR)\jsatom.obj \
|
||||
.\$(OBJDIR)\jsbool.obj \
|
||||
.\$(OBJDIR)\jscntxt.obj \
|
||||
.\$(OBJDIR)\jsdate.obj \
|
||||
.\$(OBJDIR)\jsdbgapi.obj \
|
||||
.\$(OBJDIR)\jsdtoa.obj \
|
||||
.\$(OBJDIR)\jsemit.obj \
|
||||
.\$(OBJDIR)\jsexn.obj \
|
||||
.\$(OBJDIR)\jsfun.obj \
|
||||
.\$(OBJDIR)\jsgc.obj \
|
||||
.\$(OBJDIR)\jshash.obj \
|
||||
.\$(OBJDIR)\jsinterp.obj \
|
||||
.\$(OBJDIR)\jslock.obj \
|
||||
.\$(OBJDIR)\jslog2.obj \
|
||||
.\$(OBJDIR)\jslong.obj \
|
||||
.\$(OBJDIR)\jsmath.obj \
|
||||
.\$(OBJDIR)\jsnum.obj \
|
||||
.\$(OBJDIR)\jsobj.obj \
|
||||
.\$(OBJDIR)\jsopcode.obj \
|
||||
.\$(OBJDIR)\jsparse.obj \
|
||||
.\$(OBJDIR)\jsprf.obj \
|
||||
.\$(OBJDIR)\jsregexp.obj \
|
||||
.\$(OBJDIR)\jsscan.obj \
|
||||
.\$(OBJDIR)\jsscope.obj \
|
||||
.\$(OBJDIR)\jsscript.obj \
|
||||
.\$(OBJDIR)\jsstr.obj \
|
||||
.\$(OBJDIR)\jsutil.obj \
|
||||
.\$(OBJDIR)\jsxdrapi.obj \
|
||||
.\$(OBJDIR)\prmjtime.obj \
|
||||
$(NULL)
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#//
|
||||
#// install headers
|
||||
#//
|
||||
#//------------------------------------------------------------------------
|
||||
INSTALL_DIR=$(PUBLIC)\js
|
||||
INSTALL_FILE_LIST= \
|
||||
js.msg \
|
||||
jsapi.h \
|
||||
jsarray.h \
|
||||
jsarena.h \
|
||||
jsatom.h \
|
||||
jsbit.h \
|
||||
jsbool.h \
|
||||
jsclist.h \
|
||||
jscntxt.h \
|
||||
jscompat.h \
|
||||
jsconfig.h \
|
||||
jscpucfg.h \
|
||||
jsdate.h \
|
||||
jsdbgapi.h \
|
||||
jsemit.h \
|
||||
jsfun.h \
|
||||
jsgc.h \
|
||||
jshash.h \
|
||||
jsinterp.h \
|
||||
jslock.h \
|
||||
jslong.h \
|
||||
jsmath.h \
|
||||
jsnum.h \
|
||||
jsobj.h \
|
||||
jsopcode.tbl \
|
||||
jsopcode.h \
|
||||
jsosdep.h \
|
||||
jsotypes.h \
|
||||
jsparse.h \
|
||||
jsprf.h \
|
||||
jsprvtd.h \
|
||||
jspubtd.h \
|
||||
jsregexp.h \
|
||||
jsscan.h \
|
||||
jsscope.h \
|
||||
jsscript.h \
|
||||
jsstr.h \
|
||||
jstypes.h \
|
||||
jsutil.h \
|
||||
jsxdrapi.h \
|
||||
$(NULL)
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#//
|
||||
#// Include the common makefile rules
|
||||
#//
|
||||
#//------------------------------------------------------------------------
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
||||
.\$(OBJDIR)\jsmath.obj: $(FDLIBM_LIBRARY)
|
||||
|
||||
#// Ripped from mozilla/config/rule.mak $(DIRS):: rule
|
||||
$(FDLIBM_LIBRARY):
|
||||
!if "$(WINOS)" == "WIN95"
|
||||
!if defined(VERBOSE)
|
||||
@echo +++ make: cannot recursively make on win95 using command.com, use w95make.
|
||||
!endif
|
||||
!else
|
||||
@echo +++ make: %MAKE_ARGS% in $(MAKEDIR)\$@
|
||||
@cd fdlibm
|
||||
@$(NMAKE) -f makefile.win %%MAKE_ARGS%%
|
||||
@cd $(MAKEDIR)
|
||||
!endif
|
||||
|
||||
export:: $(DLL) INSTALL_FILES
|
||||
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).dll $(DIST)\bin
|
||||
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).lib $(DIST)\lib
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#//
|
||||
#// Standalone js.exe interpreter
|
||||
#//
|
||||
#//------------------------------------------------------------------------
|
||||
|
||||
#//PROGRAM = $(OBJDIR)\js.exe
|
||||
#//js: $(PROGRAM)
|
||||
#//
|
||||
#//$(PROGRAM): $(OBJDIR)\js.obj $(LIBRARY)
|
||||
#// @$(MAKE_OBJDIR)
|
||||
#// $(link) /debug /out:$(PROGRAM) $(OBJDIR)\js.obj $(DIST)\lib\pr3240.lib $(LIBRARY) $(LDFLAGS)
|
||||
#//
|
||||
#//$(OBJDIR)\js.obj: js.c
|
||||
#// $(CC) /Fo$(OBJDIR)\js.obj js.c $(CFLAGS) -DJSFILE
|
||||
39
mozilla/js/src/perfect.js
Normal file
39
mozilla/js/src/perfect.js
Normal file
@@ -0,0 +1,39 @@
|
||||
// Some simple testing of new, eval and some string stuff.
|
||||
|
||||
// constructor -- expression array initialization
|
||||
function ExprArray(n,v)
|
||||
{
|
||||
// Initializes n values to v coerced to a string.
|
||||
for (var i = 0; i < n; i++) {
|
||||
this[i] = "" + v;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Print the perfect numbers up to n and the sum expression for n's divisors.
|
||||
function perfect(n)
|
||||
{
|
||||
print("The perfect numbers up to " + n + " are:");
|
||||
|
||||
// We build sumOfDivisors[i] to hold a string expression for
|
||||
// the sum of the divisors of i, excluding i itself.
|
||||
var sumOfDivisors = new ExprArray(n+1,1);
|
||||
for (var divisor = 2; divisor <= n; divisor++) {
|
||||
for (var j = divisor + divisor; j <= n; j += divisor) {
|
||||
sumOfDivisors[j] += " + " + divisor;
|
||||
}
|
||||
// At this point everything up to 'divisor' has its sumOfDivisors
|
||||
// expression calculated, so we can determine whether it's perfect
|
||||
// already by evaluating.
|
||||
if (eval(sumOfDivisors[divisor]) == divisor) {
|
||||
print("" + divisor + " = " + sumOfDivisors[divisor]);
|
||||
}
|
||||
}
|
||||
print("That's all.");
|
||||
}
|
||||
|
||||
|
||||
print("\nA number is 'perfect' if it is equal to the sum of its")
|
||||
print("divisors (excluding itself).\n");
|
||||
perfect(500);
|
||||
|
||||
565
mozilla/js/src/prmjtime.c
Normal file
565
mozilla/js/src/prmjtime.c
Normal file
@@ -0,0 +1,565 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* PR time code.
|
||||
*/
|
||||
#ifdef SOLARIS
|
||||
#define _REENTRANT 1
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include "jstypes.h"
|
||||
|
||||
#include "jsprf.h"
|
||||
#include "prmjtime.h"
|
||||
|
||||
#define PRMJ_DO_MILLISECONDS 1
|
||||
|
||||
#ifdef XP_PC
|
||||
#include <sys/timeb.h>
|
||||
#endif
|
||||
|
||||
#ifdef XP_MAC
|
||||
#include <OSUtils.h>
|
||||
#include <TextUtils.h>
|
||||
#include <Resources.h>
|
||||
#include <Timer.h>
|
||||
#endif
|
||||
|
||||
#ifdef XP_UNIX
|
||||
|
||||
#ifdef _SVID_GETTOD /* Defined only on Solaris, see Solaris <sys/types.h> */
|
||||
extern int gettimeofday(struct timeval *tv);
|
||||
#endif
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
#endif /* XP_UNIX */
|
||||
|
||||
#ifdef XP_MAC
|
||||
static UnsignedWide dstLocalBaseMicroseconds;
|
||||
static unsigned long gJanuaryFirst1970Seconds;
|
||||
|
||||
static void MacintoshInitializeTime(void)
|
||||
{
|
||||
UnsignedWide upTime;
|
||||
unsigned long currentLocalTimeSeconds,
|
||||
startupTimeSeconds;
|
||||
uint64 startupTimeMicroSeconds;
|
||||
uint32 upTimeSeconds;
|
||||
uint64 oneMillion, upTimeSecondsLong, microSecondsToSeconds;
|
||||
DateTimeRec firstSecondOfUnixTime;
|
||||
|
||||
// Figure out in local time what time the machine
|
||||
// started up. This information can be added to
|
||||
// upTime to figure out the current local time
|
||||
// as well as GMT.
|
||||
|
||||
Microseconds(&upTime);
|
||||
|
||||
GetDateTime(¤tLocalTimeSeconds);
|
||||
|
||||
JSLL_I2L(microSecondsToSeconds, PRMJ_USEC_PER_SEC);
|
||||
JSLL_DIV(upTimeSecondsLong, *((uint64 *)&upTime), microSecondsToSeconds);
|
||||
JSLL_L2I(upTimeSeconds, upTimeSecondsLong);
|
||||
|
||||
startupTimeSeconds = currentLocalTimeSeconds - upTimeSeconds;
|
||||
|
||||
// Make sure that we normalize the macintosh base seconds
|
||||
// to the unix base of January 1, 1970.
|
||||
|
||||
firstSecondOfUnixTime.year = 1970;
|
||||
firstSecondOfUnixTime.month = 1;
|
||||
firstSecondOfUnixTime.day = 1;
|
||||
firstSecondOfUnixTime.hour = 0;
|
||||
firstSecondOfUnixTime.minute = 0;
|
||||
firstSecondOfUnixTime.second = 0;
|
||||
firstSecondOfUnixTime.dayOfWeek = 0;
|
||||
|
||||
DateToSeconds(&firstSecondOfUnixTime, &gJanuaryFirst1970Seconds);
|
||||
|
||||
startupTimeSeconds -= gJanuaryFirst1970Seconds;
|
||||
|
||||
// Now convert the startup time into a wide so that we
|
||||
// can figure out GMT and DST.
|
||||
|
||||
JSLL_I2L(startupTimeMicroSeconds, startupTimeSeconds);
|
||||
JSLL_I2L(oneMillion, PRMJ_USEC_PER_SEC);
|
||||
JSLL_MUL(dstLocalBaseMicroseconds, oneMillion, startupTimeMicroSeconds);
|
||||
}
|
||||
|
||||
// Because serial port and SLIP conflict with ReadXPram calls,
|
||||
// we cache the call here
|
||||
|
||||
static void MyReadLocation(MachineLocation * loc)
|
||||
{
|
||||
static MachineLocation storedLoc; // InsideMac, OSUtilities, page 4-20
|
||||
static JSBool didReadLocation = JS_FALSE;
|
||||
if (!didReadLocation)
|
||||
{
|
||||
MacintoshInitializeTime();
|
||||
ReadLocation(&storedLoc);
|
||||
didReadLocation = JS_TRUE;
|
||||
}
|
||||
*loc = storedLoc;
|
||||
}
|
||||
#endif /* XP_MAC */
|
||||
|
||||
#define IS_LEAP(year) \
|
||||
(year != 0 && ((((year & 0x3) == 0) && \
|
||||
((year - ((year/100) * 100)) != 0)) || \
|
||||
(year - ((year/400) * 400)) == 0))
|
||||
|
||||
#define PRMJ_HOUR_SECONDS 3600L
|
||||
#define PRMJ_DAY_SECONDS (24L * PRMJ_HOUR_SECONDS)
|
||||
#define PRMJ_YEAR_SECONDS (PRMJ_DAY_SECONDS * 365L)
|
||||
#define PRMJ_MAX_UNIX_TIMET 2145859200L /*time_t value equiv. to 12/31/2037 */
|
||||
/* function prototypes */
|
||||
static void PRMJ_basetime(JSInt64 tsecs, PRMJTime *prtm);
|
||||
/*
|
||||
* get the difference in seconds between this time zone and UTC (GMT)
|
||||
*/
|
||||
time_t
|
||||
PRMJ_LocalGMTDifference()
|
||||
{
|
||||
#if defined(XP_UNIX) || defined(XP_PC)
|
||||
struct tm ltime;
|
||||
|
||||
/* get the difference between this time zone and GMT */
|
||||
memset((char *)<ime,0,sizeof(ltime));
|
||||
ltime.tm_mday = 2;
|
||||
ltime.tm_year = 70;
|
||||
#ifdef SUNOS4
|
||||
ltime.tm_zone = 0;
|
||||
ltime.tm_gmtoff = 0;
|
||||
return timelocal(<ime) - (24 * 3600);
|
||||
#else
|
||||
return mktime(<ime) - (24L * 3600L);
|
||||
#endif
|
||||
#endif
|
||||
#if defined(XP_MAC)
|
||||
static time_t zone = -1L;
|
||||
MachineLocation machineLocation;
|
||||
JSUint64 gmtOffsetSeconds;
|
||||
JSUint64 gmtDelta;
|
||||
JSUint64 dlsOffset;
|
||||
JSInt32 offset;
|
||||
|
||||
/* difference has been set no need to recalculate */
|
||||
if(zone != -1)
|
||||
return zone;
|
||||
|
||||
/* Get the information about the local machine, including
|
||||
* its GMT offset and its daylight savings time info.
|
||||
* Convert each into wides that we can add to
|
||||
* startupTimeMicroSeconds.
|
||||
*/
|
||||
|
||||
MyReadLocation(&machineLocation);
|
||||
|
||||
/* Mask off top eight bits of gmtDelta, sign extend lower three. */
|
||||
|
||||
if ((machineLocation.u.gmtDelta & 0x00800000) != 0) {
|
||||
gmtOffsetSeconds.lo = (machineLocation.u.gmtDelta & 0x00FFFFFF) | 0xFF000000;
|
||||
gmtOffsetSeconds.hi = 0xFFFFFFFF;
|
||||
JSLL_UI2L(gmtDelta,0);
|
||||
} else {
|
||||
gmtOffsetSeconds.lo = (machineLocation.u.gmtDelta & 0x00FFFFFF);
|
||||
gmtOffsetSeconds.hi = 0;
|
||||
JSLL_UI2L(gmtDelta,PRMJ_DAY_SECONDS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Normalize time to be positive if you are behind GMT. gmtDelta will
|
||||
* always be positive.
|
||||
*/
|
||||
JSLL_SUB(gmtDelta,gmtDelta,gmtOffsetSeconds);
|
||||
|
||||
/* Is Daylight Savings On? If so, we need to add an hour to the offset. */
|
||||
if (machineLocation.u.dlsDelta != 0) {
|
||||
JSLL_UI2L(dlsOffset, PRMJ_HOUR_SECONDS);
|
||||
} else {
|
||||
JSLL_I2L(dlsOffset, 0);
|
||||
}
|
||||
|
||||
JSLL_ADD(gmtDelta,gmtDelta, dlsOffset);
|
||||
JSLL_L2I(offset,gmtDelta);
|
||||
|
||||
zone = offset;
|
||||
return (time_t)offset;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Constants for GMT offset from 1970 */
|
||||
#define G1970GMTMICROHI 0x00dcdcad /* micro secs to 1970 hi */
|
||||
#define G1970GMTMICROLOW 0x8b3fa000 /* micro secs to 1970 low */
|
||||
|
||||
#define G2037GMTMICROHI 0x00e45fab /* micro secs to 2037 high */
|
||||
#define G2037GMTMICROLOW 0x7a238000 /* micro secs to 2037 low */
|
||||
|
||||
/* Convert from base time to extended time */
|
||||
static JSInt64
|
||||
PRMJ_ToExtendedTime(JSInt32 time)
|
||||
{
|
||||
JSInt64 exttime;
|
||||
JSInt64 g1970GMTMicroSeconds;
|
||||
JSInt64 low;
|
||||
time_t diff;
|
||||
JSInt64 tmp;
|
||||
JSInt64 tmp1;
|
||||
|
||||
diff = PRMJ_LocalGMTDifference();
|
||||
JSLL_UI2L(tmp, PRMJ_USEC_PER_SEC);
|
||||
JSLL_I2L(tmp1,diff);
|
||||
JSLL_MUL(tmp,tmp,tmp1);
|
||||
|
||||
JSLL_UI2L(g1970GMTMicroSeconds,G1970GMTMICROHI);
|
||||
JSLL_UI2L(low,G1970GMTMICROLOW);
|
||||
#ifndef JS_HAVE_LONG_LONG
|
||||
JSLL_SHL(g1970GMTMicroSeconds,g1970GMTMicroSeconds,16);
|
||||
JSLL_SHL(g1970GMTMicroSeconds,g1970GMTMicroSeconds,16);
|
||||
#else
|
||||
JSLL_SHL(g1970GMTMicroSeconds,g1970GMTMicroSeconds,32);
|
||||
#endif
|
||||
JSLL_ADD(g1970GMTMicroSeconds,g1970GMTMicroSeconds,low);
|
||||
|
||||
JSLL_I2L(exttime,time);
|
||||
JSLL_ADD(exttime,exttime,g1970GMTMicroSeconds);
|
||||
JSLL_SUB(exttime,exttime,tmp);
|
||||
return exttime;
|
||||
}
|
||||
|
||||
JSInt64
|
||||
PRMJ_Now(void)
|
||||
{
|
||||
#ifdef XP_PC
|
||||
JSInt64 s, us, ms2us, s2us;
|
||||
struct timeb b;
|
||||
#endif /* XP_PC */
|
||||
#ifdef XP_UNIX
|
||||
struct timeval tv;
|
||||
JSInt64 s, us, s2us;
|
||||
#endif /* XP_UNIX */
|
||||
#ifdef XP_MAC
|
||||
UnsignedWide upTime;
|
||||
JSInt64 localTime;
|
||||
JSInt64 gmtOffset;
|
||||
JSInt64 dstOffset;
|
||||
time_t gmtDiff;
|
||||
JSInt64 s2us;
|
||||
#endif /* XP_MAC */
|
||||
|
||||
#ifdef XP_PC
|
||||
ftime(&b);
|
||||
JSLL_UI2L(ms2us, PRMJ_USEC_PER_MSEC);
|
||||
JSLL_UI2L(s2us, PRMJ_USEC_PER_SEC);
|
||||
JSLL_UI2L(s, b.time);
|
||||
JSLL_UI2L(us, b.millitm);
|
||||
JSLL_MUL(us, us, ms2us);
|
||||
JSLL_MUL(s, s, s2us);
|
||||
JSLL_ADD(s, s, us);
|
||||
return s;
|
||||
#endif
|
||||
|
||||
#ifdef XP_UNIX
|
||||
#ifdef _SVID_GETTOD /* Defined only on Solaris, see Solaris <sys/types.h> */
|
||||
gettimeofday(&tv);
|
||||
#else
|
||||
gettimeofday(&tv, 0);
|
||||
#endif /* _SVID_GETTOD */
|
||||
JSLL_UI2L(s2us, PRMJ_USEC_PER_SEC);
|
||||
JSLL_UI2L(s, tv.tv_sec);
|
||||
JSLL_UI2L(us, tv.tv_usec);
|
||||
JSLL_MUL(s, s, s2us);
|
||||
JSLL_ADD(s, s, us);
|
||||
return s;
|
||||
#endif /* XP_UNIX */
|
||||
#ifdef XP_MAC
|
||||
JSLL_UI2L(localTime,0);
|
||||
gmtDiff = PRMJ_LocalGMTDifference();
|
||||
JSLL_I2L(gmtOffset,gmtDiff);
|
||||
JSLL_UI2L(s2us, PRMJ_USEC_PER_SEC);
|
||||
JSLL_MUL(gmtOffset,gmtOffset,s2us);
|
||||
JSLL_UI2L(dstOffset,0);
|
||||
dstOffset = PRMJ_DSTOffset(dstOffset);
|
||||
JSLL_SUB(gmtOffset,gmtOffset,dstOffset);
|
||||
/* don't adjust for DST since it sets ctime and gmtime off on the MAC */
|
||||
Microseconds(&upTime);
|
||||
JSLL_ADD(localTime,localTime,gmtOffset);
|
||||
JSLL_ADD(localTime,localTime, *((JSUint64 *)&dstLocalBaseMicroseconds));
|
||||
JSLL_ADD(localTime,localTime, *((JSUint64 *)&upTime));
|
||||
|
||||
return *((JSUint64 *)&localTime);
|
||||
#endif /* XP_MAC */
|
||||
}
|
||||
|
||||
/* Get the DST timezone offset for the time passed in */
|
||||
JSInt64
|
||||
PRMJ_DSTOffset(JSInt64 time)
|
||||
{
|
||||
JSInt64 us2s;
|
||||
#ifdef XP_MAC
|
||||
MachineLocation machineLocation;
|
||||
JSInt64 dlsOffset;
|
||||
/* Get the information about the local machine, including
|
||||
* its GMT offset and its daylight savings time info.
|
||||
* Convert each into wides that we can add to
|
||||
* startupTimeMicroSeconds.
|
||||
*/
|
||||
MyReadLocation(&machineLocation);
|
||||
|
||||
/* Is Daylight Savings On? If so, we need to add an hour to the offset. */
|
||||
if (machineLocation.u.dlsDelta != 0) {
|
||||
JSLL_UI2L(us2s, PRMJ_USEC_PER_SEC); /* seconds in a microseconds */
|
||||
JSLL_UI2L(dlsOffset, PRMJ_HOUR_SECONDS); /* seconds in one hour */
|
||||
JSLL_MUL(dlsOffset, dlsOffset, us2s);
|
||||
} else {
|
||||
JSLL_I2L(dlsOffset, 0);
|
||||
}
|
||||
return(dlsOffset);
|
||||
#else
|
||||
time_t local;
|
||||
JSInt32 diff;
|
||||
JSInt64 maxtimet;
|
||||
struct tm tm;
|
||||
PRMJTime prtm;
|
||||
#if defined( XP_PC ) || defined( FREEBSD ) || defined ( HPUX9 ) || defined ( SNI ) || defined ( NETBSD ) || defined ( OPENBSD ) || defined( RHAPSODY )
|
||||
struct tm *ptm;
|
||||
#endif
|
||||
|
||||
|
||||
JSLL_UI2L(us2s, PRMJ_USEC_PER_SEC);
|
||||
JSLL_DIV(time, time, us2s);
|
||||
|
||||
/* get the maximum of time_t value */
|
||||
JSLL_UI2L(maxtimet,PRMJ_MAX_UNIX_TIMET);
|
||||
|
||||
if(JSLL_CMP(time,>,maxtimet)){
|
||||
JSLL_UI2L(time,PRMJ_MAX_UNIX_TIMET);
|
||||
} else if(!JSLL_GE_ZERO(time)){
|
||||
/*go ahead a day to make localtime work (does not work with 0) */
|
||||
JSLL_UI2L(time,PRMJ_DAY_SECONDS);
|
||||
}
|
||||
JSLL_L2UI(local,time);
|
||||
PRMJ_basetime(time,&prtm);
|
||||
#if defined( XP_PC ) || defined( FREEBSD ) || defined ( HPUX9 ) || defined ( SNI ) || defined ( NETBSD ) || defined ( OPENBSD ) || defined( RHAPSODY )
|
||||
ptm = localtime(&local);
|
||||
if(!ptm){
|
||||
return JSLL_ZERO;
|
||||
}
|
||||
tm = *ptm;
|
||||
#else
|
||||
localtime_r(&local,&tm); /* get dst information */
|
||||
#endif
|
||||
|
||||
diff = ((tm.tm_hour - prtm.tm_hour) * PRMJ_HOUR_SECONDS) +
|
||||
((tm.tm_min - prtm.tm_min) * 60);
|
||||
|
||||
if(diff < 0){
|
||||
diff += PRMJ_DAY_SECONDS;
|
||||
}
|
||||
|
||||
JSLL_UI2L(time,diff);
|
||||
|
||||
JSLL_MUL(time,time,us2s);
|
||||
|
||||
return(time);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Format a time value into a buffer. Same semantics as strftime() */
|
||||
size_t
|
||||
PRMJ_FormatTime(char *buf, int buflen, char *fmt, PRMJTime *prtm)
|
||||
{
|
||||
#if defined(XP_UNIX) || defined(XP_PC) || defined(XP_MAC)
|
||||
struct tm a;
|
||||
|
||||
/* Zero out the tm struct. Linux, SunOS 4 struct tm has extra members int
|
||||
* tm_gmtoff, char *tm_zone; when tm_zone is garbage, strftime gets
|
||||
* confused and dumps core. NSPR20 prtime.c attempts to fill these in by
|
||||
* calling mktime on the partially filled struct, but this doesn't seem to
|
||||
* work as well; the result string has "can't get timezone" for ECMA-valid
|
||||
* years. Might still make sense to use this, but find the range of years
|
||||
* for which valid tz information exists, and map (per ECMA hint) from the
|
||||
* given year into that range.
|
||||
|
||||
* N.B. This hasn't been tested with anything that actually _uses_
|
||||
* tm_gmtoff; zero might be the wrong thing to set it to if you really need
|
||||
* to format a time. This fix is for jsdate.c, which only uses
|
||||
* JS_FormatTime to get a string representing the time zone. */
|
||||
memset(&a, 0, sizeof(struct tm));
|
||||
|
||||
a.tm_sec = prtm->tm_sec;
|
||||
a.tm_min = prtm->tm_min;
|
||||
a.tm_hour = prtm->tm_hour;
|
||||
a.tm_mday = prtm->tm_mday;
|
||||
a.tm_mon = prtm->tm_mon;
|
||||
a.tm_wday = prtm->tm_wday;
|
||||
a.tm_year = prtm->tm_year - 1900;
|
||||
a.tm_yday = prtm->tm_yday;
|
||||
a.tm_isdst = prtm->tm_isdst;
|
||||
|
||||
/* Even with the above, SunOS 4 seems to detonate if tm_zone and tm_gmtoff
|
||||
* are null. This doesn't quite work, though - the timezone is off by
|
||||
* tzoff + dst. (And mktime seems to return -1 for the exact dst
|
||||
* changeover time.)
|
||||
|
||||
* Still not sure if MKLINUX is necessary; this is borrowed from the NSPR20
|
||||
* prtime.c. I'm leaving it out - My Linux does the right thing without it
|
||||
* (and the wrong thing with it) even though it has the tm_gmtoff, tm_zone
|
||||
* fields. Linux seems to be happy so long as the tm struct is zeroed out.
|
||||
* The #ifdef in nspr is:
|
||||
* #if defined(SUNOS4) || defined(MKLINUX) || defined (__GLIBC >= 2)
|
||||
*/
|
||||
|
||||
#if defined(SUNOS4)
|
||||
if (mktime(&a) == -1) {
|
||||
/* Seems to fail whenever the requested date is outside of the 32-bit
|
||||
* UNIX epoch. We could proceed at this point (setting a.tm_zone to
|
||||
* "") but then strftime returns a string with a 2-digit field of
|
||||
* garbage for the year. So we return 0 and hope jsdate.c
|
||||
* will fall back on toString.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return strftime(buf, buflen, fmt, &a);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* table for number of days in a month */
|
||||
static int mtab[] = {
|
||||
/* jan, feb,mar,apr,may,jun */
|
||||
31,28,31,30,31,30,
|
||||
/* july,aug,sep,oct,nov,dec */
|
||||
31,31,30,31,30,31
|
||||
};
|
||||
|
||||
/*
|
||||
* basic time calculation functionality for localtime and gmtime
|
||||
* setups up prtm argument with correct values based upon input number
|
||||
* of seconds.
|
||||
*/
|
||||
static void
|
||||
PRMJ_basetime(JSInt64 tsecs, PRMJTime *prtm)
|
||||
{
|
||||
/* convert tsecs back to year,month,day,hour,secs */
|
||||
JSInt32 year = 0;
|
||||
JSInt32 month = 0;
|
||||
JSInt32 yday = 0;
|
||||
JSInt32 mday = 0;
|
||||
JSInt32 wday = 6; /* start on a Sunday */
|
||||
JSInt32 days = 0;
|
||||
JSInt32 seconds = 0;
|
||||
JSInt32 minutes = 0;
|
||||
JSInt32 hours = 0;
|
||||
JSInt32 isleap = 0;
|
||||
JSInt64 result;
|
||||
JSInt64 result1;
|
||||
JSInt64 result2;
|
||||
JSInt64 base;
|
||||
|
||||
JSLL_UI2L(result,0);
|
||||
JSLL_UI2L(result1,0);
|
||||
JSLL_UI2L(result2,0);
|
||||
|
||||
/* get the base time via UTC */
|
||||
base = PRMJ_ToExtendedTime(0);
|
||||
JSLL_UI2L(result, PRMJ_USEC_PER_SEC);
|
||||
JSLL_DIV(base,base,result);
|
||||
JSLL_ADD(tsecs,tsecs,base);
|
||||
|
||||
JSLL_UI2L(result, PRMJ_YEAR_SECONDS);
|
||||
JSLL_UI2L(result1,PRMJ_DAY_SECONDS);
|
||||
JSLL_ADD(result2,result,result1);
|
||||
|
||||
/* get the year */
|
||||
while ((isleap == 0) ? !JSLL_CMP(tsecs,<,result) : !JSLL_CMP(tsecs,<,result2)) {
|
||||
/* subtract a year from tsecs */
|
||||
JSLL_SUB(tsecs,tsecs,result);
|
||||
days += 365;
|
||||
/* is it a leap year ? */
|
||||
if(IS_LEAP(year)){
|
||||
JSLL_SUB(tsecs,tsecs,result1);
|
||||
days++;
|
||||
}
|
||||
year++;
|
||||
isleap = IS_LEAP(year);
|
||||
}
|
||||
|
||||
JSLL_UI2L(result1,PRMJ_DAY_SECONDS);
|
||||
|
||||
JSLL_DIV(result,tsecs,result1);
|
||||
JSLL_L2I(mday,result);
|
||||
|
||||
/* let's find the month */
|
||||
while(((month == 1 && isleap) ?
|
||||
(mday >= mtab[month] + 1) :
|
||||
(mday >= mtab[month]))){
|
||||
yday += mtab[month];
|
||||
days += mtab[month];
|
||||
|
||||
mday -= mtab[month];
|
||||
|
||||
/* it's a Feb, check if this is a leap year */
|
||||
if(month == 1 && isleap != 0){
|
||||
yday++;
|
||||
days++;
|
||||
mday--;
|
||||
}
|
||||
month++;
|
||||
}
|
||||
|
||||
/* now adjust tsecs */
|
||||
JSLL_MUL(result,result,result1);
|
||||
JSLL_SUB(tsecs,tsecs,result);
|
||||
|
||||
mday++; /* day of month always start with 1 */
|
||||
days += mday;
|
||||
wday = (days + wday) % 7;
|
||||
|
||||
yday += mday;
|
||||
|
||||
/* get the hours */
|
||||
JSLL_UI2L(result1,PRMJ_HOUR_SECONDS);
|
||||
JSLL_DIV(result,tsecs,result1);
|
||||
JSLL_L2I(hours,result);
|
||||
JSLL_MUL(result,result,result1);
|
||||
JSLL_SUB(tsecs,tsecs,result);
|
||||
|
||||
/* get minutes */
|
||||
JSLL_UI2L(result1,60);
|
||||
JSLL_DIV(result,tsecs,result1);
|
||||
JSLL_L2I(minutes,result);
|
||||
JSLL_MUL(result,result,result1);
|
||||
JSLL_SUB(tsecs,tsecs,result);
|
||||
|
||||
JSLL_L2I(seconds,tsecs);
|
||||
|
||||
prtm->tm_usec = 0L;
|
||||
prtm->tm_sec = (JSInt8)seconds;
|
||||
prtm->tm_min = (JSInt8)minutes;
|
||||
prtm->tm_hour = (JSInt8)hours;
|
||||
prtm->tm_mday = (JSInt8)mday;
|
||||
prtm->tm_mon = (JSInt8)month;
|
||||
prtm->tm_wday = (JSInt8)wday;
|
||||
prtm->tm_year = (JSInt16)year;
|
||||
prtm->tm_yday = (JSInt16)yday;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user