From 81d445e052e4c153e23519271b1f2388de160fdf Mon Sep 17 00:00:00 2001 From: Gervase Markham Date: Wed, 18 Jun 2008 15:02:51 +0100 Subject: [PATCH 01/66] Bug 438585: First round of registry-submitted changes to Public Suffix List. --- netwerk/dns/src/effective_tld_names.dat | 226 +++++++++++++++++++++--- 1 file changed, 202 insertions(+), 24 deletions(-) diff --git a/netwerk/dns/src/effective_tld_names.dat b/netwerk/dns/src/effective_tld_names.dat index 72562bb0afd9..61b5ad4b065d 100644 --- a/netwerk/dns/src/effective_tld_names.dat +++ b/netwerk/dns/src/effective_tld_names.dat @@ -20,6 +20,8 @@ // // Contributor(s): // Ruben Arakelyan +// Gervase Markham +// The kind representatives of many TLD registries // // Alternatively, the contents of this file may be used under the terms of // either the GNU General Public License Version 2 or later (the "GPL"), or @@ -35,8 +37,6 @@ // // ***** END LICENSE BLOCK ***** -// $Id$ - // ac : http://en.wikipedia.org/wiki/.ac ac com.ac @@ -223,12 +223,17 @@ urn.arpa as // at : http://en.wikipedia.org/wiki/.at +// Confirmed by registry 2008-06-17 at gv.at ac.at co.at or.at +// priv.at : http://www.nic.priv.at/ +// Submitted by registry 2008-06-09 +priv.at + // au : http://en.wikipedia.org/wiki/.au *.au // au geographical names (vic.au etc... are covered above) @@ -296,6 +301,7 @@ org.bb *.bd // be : http://en.wikipedia.org/wiki/.be +// Confirmed by registry 2008-06-08 be ac.be @@ -420,6 +426,9 @@ gov.bs // bt : http://en.wikipedia.org/wiki/.bt *.bt +// bv : No registrations at this time. +// Submitted by registry 2006-06-16 + // bw : http://en.wikipedia.org/wiki/.bw // list of 2nd level tlds ? bw @@ -482,6 +491,7 @@ cl cm // cn : http://en.wikipedia.org/wiki/.cn +// Submitted by registry 2008-06-11 cn ac.cn com.cn @@ -489,6 +499,10 @@ edu.cn gov.cn net.cn org.cn +mil.cn +公司.cn +网络.cn +網絡.cn // cn geographic names ah.cn bj.cn @@ -521,13 +535,53 @@ xj.cn xz.cn yn.cn zj.cn +hk.cn +mo.cn +tw.cn // co : http://en.wikipedia.org/wiki/.co -*.co +// Submitted by registry 2008-06-11 +co +arts.co +com.co +edu.co +firm.co +gov.co +info.co +int.co +mil.co +net.co +nom.co +org.co +rec.co +web.co + + // com : http://en.wikipedia.org/wiki/.com com +// CentralNic names : http://www.centralnic.com/names/domains +// Confirmed by registry 2008-06-09 +ar.com +br.com +cn.com +de.com +eu.com +gb.com +hu.com +jpn.com +kr.com +no.com +qc.com +ru.com +sa.com +se.com +uk.com +us.com +uy.com +za.com + // coop : http://en.wikipedia.org/wiki/.coop coop @@ -562,6 +616,7 @@ de dj // dk : http://en.wikipedia.org/wiki/.dk +// Confirmed by registry 2008-06-17 dk // dm : http://en.wikipedia.org/wiki/.dm @@ -674,6 +729,9 @@ veterinaire.fr // ga : http://en.wikipedia.org/wiki/.ga ga +// gb : This registry is effectively dormant +// Submitted by registry 2008-06-12 + // gd : http://en.wikipedia.org/wiki/.gd gd @@ -717,7 +775,13 @@ gl gm // gn : http://psg.com/dns/gn/gn.txt -*.gn +// Submitted by registry 2008-06-17 +ac.gn +com.gn +edu.gn +gov.gn +org.gn +net.gn // gov : http://en.wikipedia.org/wiki/.gov gov @@ -732,7 +796,8 @@ org.gp // gq : http://en.wikipedia.org/wiki/.gq gq -// gr : https://grweb.ics.forth.gr/english/1617-B-2002.html +// gr : https://grweb.ics.forth.gr/english/1617-B-2005.html +// Submitted by registry 2008-06-09 gr com.gr edu.gr @@ -755,7 +820,8 @@ gw // gy : http://en.wikipedia.org/wiki/.gy gy -// hk : http://en.wikipedia.org/wiki/.hk +// hk : https://www.hkdnr.hk +// Submitted by registry 2008-06-11 hk com.hk edu.hk @@ -763,6 +829,21 @@ gov.hk idv.hk net.hk org.hk +公司.hk +教育.hk +敎育.hk +政府.hk +個人.hk +个人.hk +箇人.hk +網络.hk +网络.hk +组織.hk +網絡.hk +网絡.hk +组织.hk +組織.hk +組织.hk // hm : http://en.wikipedia.org/wiki/.hm hm @@ -804,6 +885,7 @@ gouv.ht perso.ht // hu : http://www.domain.hu/domain/English/sld.html +// Confirmed by registry 2008-06-12 hu co.hu info.hu @@ -900,6 +982,7 @@ org.ir sch.ir // is : http://www.isnic.is/domain/rules.php +// Confirmed by registry 2008-12-06 is net.is com.is @@ -1159,21 +1242,26 @@ gov.je // jm : http://www.com.jm/register.html *.jm -// jo : http://www.nis.gov.jo/dns/reg.html +// jo : http://www.dns.jo/Registration_policy.aspx jo com.jo org.jo net.jo edu.jo +sch.jo gov.jo mil.jo +name.jo myname.jo // jobs : http://en.wikipedia.org/wiki/.jobs jobs // jp : http://en.wikipedia.org/wiki/.jp +// http://jprs.co.jp/en/jpdomain.html +// Submitted by registry 2008-06-11 jp +// jp organizational type names ac.jp ad.jp co.jp @@ -1183,8 +1271,8 @@ gr.jp lg.jp ne.jp or.jp -// jp geographical names -// I can't find an official English explanation, but used https://bugzilla.mozilla.org/show_bug.cgi?id=252342#c31 +// jp geographic type names +// http://jprs.jp/doc/rule/saisoku-1.html *.aichi.jp *.akita.jp *.aomori.jp @@ -1294,6 +1382,7 @@ or.jp !city.kobe.jp !city.kyoto.jp !city.nagoya.jp +!city.niigata.jp !city.osaka.jp !city.saitama.jp !city.sapporo.jp @@ -1370,6 +1459,7 @@ ulsan.kr *.kw // ky : http://www.icta.ky/da_ky_reg_dom.php +// Confirmed by registry 2008-06-17 ky edu.ky gov.ky @@ -1387,10 +1477,26 @@ mil.kz com.kz // la : http://en.wikipedia.org/wiki/.la +// Submitted by registry 2008-06-10 la +int.la +net.la +info.la +edu.la +gov.la +per.la +com.la +org.la +// see http://www.c.la/ +c.la // lb : http://en.wikipedia.org/wiki/.lb -*.lb +// Submitted by registry 2008-06-17 +com.lb +edu.lb +gov.lb +net.lb +org.lb // lc : http://en.wikipedia.org/wiki/.lc lc @@ -1420,7 +1526,12 @@ grp.lk hotel.lk // lr : http://psg.com/dns/lr/lr.txt -*.lr +// Submitted by registry 2008-06-17 +com.lr +edu.lr +gov.lr +org.lr +net.lr // ls : http://en.wikipedia.org/wiki/.ls ls @@ -1523,6 +1634,7 @@ gov.mo mobi // mp : http://www.dot.mp/ +// Confirmed by registry 2008-06-17 mp // mq : http://en.wikipedia.org/wiki/.mq @@ -1586,6 +1698,12 @@ ne // net : http://en.wikipedia.org/wiki/.net net +// CentralNic names : http://www.centralnic.com/names/domains +// Submitted by registry 2008-06-17 +gb.net +se.net +uk.net + // nf : http://en.wikipedia.org/wiki/.nf nf com.nf @@ -1600,22 +1718,36 @@ other.nf store.nf // ng : http://psg.com/dns/ng/ -ng +// Submitted by registry 2008-06-17 +ac.ng +com.ng +edu.ng +gov.ng +net.ng +org.ng // ni : http://www.nic.ni/dominios.htm *.ni // nl : http://www.domain-registry.nl/ace.php/c,728,122,,,,Home.html +// Confirmed by registry (with technical +// reservations) 2008-06-08 nl // no : http://www.norid.no/regelverk/index.en.html +// The Norwegian registry has declined to notify us of updates. The web pages +// referenced below are the official source of the data. There is also an +// announce mailing list: +// https://postlister.uninett.no/sympa/info/norid-diskusjon no +// Norid generic domains : http://www.norid.no/regelverk/vedlegg-c.en.html fhs.no vgs.no fylkesbibl.no folkebibl.no museum.no idrett.no +// Non-Norid generic domains : http://www.norid.no/regelverk/vedlegg-d.en.html mil.no stat.no dep.no @@ -2186,6 +2318,7 @@ råde.no salangen.no siellak.no saltdal.no +salat.no sálát.no sálat.no samnanger.no @@ -2325,7 +2458,7 @@ utsira.no vadso.no vadsø.no cahcesuolo.no -cáhcesuolo.no +čáhcesuolo.no vaksdal.no valle.no vang.no @@ -2372,6 +2505,7 @@ våler.hedmark.no *.np // nr : http://cenpac.net.nr/dns/index.html +// Confirmed by registry 2008-06-17 nr biz.nr info.nr @@ -2390,9 +2524,13 @@ nu // om : http://en.wikipedia.org/wiki/.om *.om -// org : http://en.wikipedia.org/wiki/.og +// org : http://en.wikipedia.org/wiki/.org org +// CentralNic names : http://www.centralnic.com/names/domains +// Submitted by registry 2008-06-17 +ae.org + // pa : http://www.nic.pa/ *.pa @@ -2409,7 +2547,7 @@ edu.pf *.pg // ph : http://www.domains.ph/FAQ2.asp -// list of 2nd level tlds ? +// Submitted by registry 2008-06-13 ph com.ph net.ph @@ -2418,6 +2556,7 @@ gov.ph edu.ph ngo.ph mil.ph +i.ph // pk : http://pk5.pknic.net.pk/pk5/msgNamepk.PK pk @@ -2736,7 +2875,13 @@ gouv.rw *.sa // sb : http://www.sbnic.net.sb/ -*.sb +// Submitted by registry 2008-06-08 +sb +com.sb +edu.sb +gov.sb +net.sb +org.sb // sc : http://www.nic.sc/ sc @@ -2747,14 +2892,14 @@ org.sc edu.sc // sd : http://www.isoc.sd/sudanic.isoc.sd/billing_pricing.htm +// Submitted by registry 2008-06-17 sd com.sd net.sd org.sd edu.sd med.sd -tv.sd -gov.sd + gov.sd info.sd // se : http://en.wikipedia.org/wiki/.se @@ -2804,12 +2949,20 @@ sh // si : http://en.wikipedia.org/wiki/.si si +// sj : No registrations at this time. +// Submitted by registry 2008-06-16 + // sk : http://en.wikipedia.org/wiki/.sk sk -// sl : http://en.wikipedia.org/wiki/.sl -// list of 2nd level domains ? +// sl : http://www.nic.sl +// Submitted by registry 2008-06-12 sl +com.sl +net.sl +edu.sl +gov.sl +org.sl // sm : http://en.wikipedia.org/wiki/.sm sm @@ -2851,7 +3004,15 @@ tf tg // th : http://en.wikipedia.org/wiki/.th -*.th +// Submitted by registry 2008-06-17 +th +ac.th +co.th +go.th +in.th +mi.th +net.th +or.th // tj : http://www.nic.tj/policy.htm tj @@ -2885,8 +3046,14 @@ tm tn // to : http://en.wikipedia.org/wiki/.to -// list of 2nd level tlds ? +// Submitted by registry 2008-06-17 to +com.to +gov.to +net.to +org.to +edu.to +mil.to // tr : http://en.wikipedia.org/wiki/.tr *.tr @@ -2935,7 +3102,12 @@ club.tw 商業.tw // tz : http://en.wikipedia.org/wiki/.tz -*.tz +// Submitted by registry 2008-06-17 +ac.tz +co.tz +go.tz +ne.tz +or.tz // ua : http://www.nic.net.ua/ ua @@ -3101,8 +3273,14 @@ co.uz va // vc : http://en.wikipedia.org/wiki/.vc -// list of 2nd level tlds ? +// Submitted by registry 2008-06-13 vc +com.vc +net.vc +org.vc +gov.vc +mil.vc +edu.vc // ve : http://registro.nic.ve/nicve/registro/index.html *.ve From d000fcbd77cce5c00d94eb78e71ade6a23848d6a Mon Sep 17 00:00:00 2001 From: Shawn Wilsher Date: Wed, 18 Jun 2008 11:06:23 -0400 Subject: [PATCH 02/66] Bug 417037 - mozStorage chokes on databases over AFP This patch adds the SQLITE_ENABLE_LOCKING_STYLE=1 on the macintosh platform only. This will enable Apple-contributed code in SQLite that does file locking that works on AFP (Apple File Protocol), as well as some additional network filesystems that the platform supports. r=bsmedberg --- db/sqlite3/src/Makefile.in | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/db/sqlite3/src/Makefile.in b/db/sqlite3/src/Makefile.in index 85f9b246336a..be609c9e6126 100644 --- a/db/sqlite3/src/Makefile.in +++ b/db/sqlite3/src/Makefile.in @@ -91,7 +91,17 @@ CSRCS = \ # don't have to vacuum to make sure the data is not visible in the file. # -DSQLITE_ENABLE_FTS3=1 enables the full-text index module. # -DSQLITE_CORE=1 statically links that module into the SQLite library. -DEFINES = -DSQLITE_SECURE_DELETE=1 -DTHREADSAFE=1 -DSQLITE_CORE=1 -DSQLITE_ENABLE_FTS3=1 +DEFINES = \ + -DSQLITE_SECURE_DELETE=1 \ + -DTHREADSAFE=1 \ + -DSQLITE_CORE=1 \ + -DSQLITE_ENABLE_FTS3=1 \ + $(NULL) + +# -DSQLITE_ENABLE_LOCKING_STYLE=1 to help with AFP folders +ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa) +DEFINES += -DSQLITE_ENABLE_LOCKING_STYLE=1 +endif ifeq ($(OS_ARCH),OS2) ifdef MOZ_OS2_HIGH_MEMORY From 8a7a52178e6a6b632016b31a8c80137fef8dbe51 Mon Sep 17 00:00:00 2001 From: Gervase Markham Date: Wed, 18 Jun 2008 16:32:40 +0100 Subject: [PATCH 03/66] Backed out changeset 8473190b24b0 Tinderboxes going orange. --- netwerk/dns/src/effective_tld_names.dat | 226 +++--------------------- 1 file changed, 24 insertions(+), 202 deletions(-) diff --git a/netwerk/dns/src/effective_tld_names.dat b/netwerk/dns/src/effective_tld_names.dat index 61b5ad4b065d..72562bb0afd9 100644 --- a/netwerk/dns/src/effective_tld_names.dat +++ b/netwerk/dns/src/effective_tld_names.dat @@ -20,8 +20,6 @@ // // Contributor(s): // Ruben Arakelyan -// Gervase Markham -// The kind representatives of many TLD registries // // Alternatively, the contents of this file may be used under the terms of // either the GNU General Public License Version 2 or later (the "GPL"), or @@ -37,6 +35,8 @@ // // ***** END LICENSE BLOCK ***** +// $Id$ + // ac : http://en.wikipedia.org/wiki/.ac ac com.ac @@ -223,17 +223,12 @@ urn.arpa as // at : http://en.wikipedia.org/wiki/.at -// Confirmed by registry 2008-06-17 at gv.at ac.at co.at or.at -// priv.at : http://www.nic.priv.at/ -// Submitted by registry 2008-06-09 -priv.at - // au : http://en.wikipedia.org/wiki/.au *.au // au geographical names (vic.au etc... are covered above) @@ -301,7 +296,6 @@ org.bb *.bd // be : http://en.wikipedia.org/wiki/.be -// Confirmed by registry 2008-06-08 be ac.be @@ -426,9 +420,6 @@ gov.bs // bt : http://en.wikipedia.org/wiki/.bt *.bt -// bv : No registrations at this time. -// Submitted by registry 2006-06-16 - // bw : http://en.wikipedia.org/wiki/.bw // list of 2nd level tlds ? bw @@ -491,7 +482,6 @@ cl cm // cn : http://en.wikipedia.org/wiki/.cn -// Submitted by registry 2008-06-11 cn ac.cn com.cn @@ -499,10 +489,6 @@ edu.cn gov.cn net.cn org.cn -mil.cn -公司.cn -网络.cn -網絡.cn // cn geographic names ah.cn bj.cn @@ -535,53 +521,13 @@ xj.cn xz.cn yn.cn zj.cn -hk.cn -mo.cn -tw.cn // co : http://en.wikipedia.org/wiki/.co -// Submitted by registry 2008-06-11 -co -arts.co -com.co -edu.co -firm.co -gov.co -info.co -int.co -mil.co -net.co -nom.co -org.co -rec.co -web.co - - +*.co // com : http://en.wikipedia.org/wiki/.com com -// CentralNic names : http://www.centralnic.com/names/domains -// Confirmed by registry 2008-06-09 -ar.com -br.com -cn.com -de.com -eu.com -gb.com -hu.com -jpn.com -kr.com -no.com -qc.com -ru.com -sa.com -se.com -uk.com -us.com -uy.com -za.com - // coop : http://en.wikipedia.org/wiki/.coop coop @@ -616,7 +562,6 @@ de dj // dk : http://en.wikipedia.org/wiki/.dk -// Confirmed by registry 2008-06-17 dk // dm : http://en.wikipedia.org/wiki/.dm @@ -729,9 +674,6 @@ veterinaire.fr // ga : http://en.wikipedia.org/wiki/.ga ga -// gb : This registry is effectively dormant -// Submitted by registry 2008-06-12 - // gd : http://en.wikipedia.org/wiki/.gd gd @@ -775,13 +717,7 @@ gl gm // gn : http://psg.com/dns/gn/gn.txt -// Submitted by registry 2008-06-17 -ac.gn -com.gn -edu.gn -gov.gn -org.gn -net.gn +*.gn // gov : http://en.wikipedia.org/wiki/.gov gov @@ -796,8 +732,7 @@ org.gp // gq : http://en.wikipedia.org/wiki/.gq gq -// gr : https://grweb.ics.forth.gr/english/1617-B-2005.html -// Submitted by registry 2008-06-09 +// gr : https://grweb.ics.forth.gr/english/1617-B-2002.html gr com.gr edu.gr @@ -820,8 +755,7 @@ gw // gy : http://en.wikipedia.org/wiki/.gy gy -// hk : https://www.hkdnr.hk -// Submitted by registry 2008-06-11 +// hk : http://en.wikipedia.org/wiki/.hk hk com.hk edu.hk @@ -829,21 +763,6 @@ gov.hk idv.hk net.hk org.hk -公司.hk -教育.hk -敎育.hk -政府.hk -個人.hk -个人.hk -箇人.hk -網络.hk -网络.hk -组織.hk -網絡.hk -网絡.hk -组织.hk -組織.hk -組织.hk // hm : http://en.wikipedia.org/wiki/.hm hm @@ -885,7 +804,6 @@ gouv.ht perso.ht // hu : http://www.domain.hu/domain/English/sld.html -// Confirmed by registry 2008-06-12 hu co.hu info.hu @@ -982,7 +900,6 @@ org.ir sch.ir // is : http://www.isnic.is/domain/rules.php -// Confirmed by registry 2008-12-06 is net.is com.is @@ -1242,26 +1159,21 @@ gov.je // jm : http://www.com.jm/register.html *.jm -// jo : http://www.dns.jo/Registration_policy.aspx +// jo : http://www.nis.gov.jo/dns/reg.html jo com.jo org.jo net.jo edu.jo -sch.jo gov.jo mil.jo -name.jo myname.jo // jobs : http://en.wikipedia.org/wiki/.jobs jobs // jp : http://en.wikipedia.org/wiki/.jp -// http://jprs.co.jp/en/jpdomain.html -// Submitted by registry 2008-06-11 jp -// jp organizational type names ac.jp ad.jp co.jp @@ -1271,8 +1183,8 @@ gr.jp lg.jp ne.jp or.jp -// jp geographic type names -// http://jprs.jp/doc/rule/saisoku-1.html +// jp geographical names +// I can't find an official English explanation, but used https://bugzilla.mozilla.org/show_bug.cgi?id=252342#c31 *.aichi.jp *.akita.jp *.aomori.jp @@ -1382,7 +1294,6 @@ or.jp !city.kobe.jp !city.kyoto.jp !city.nagoya.jp -!city.niigata.jp !city.osaka.jp !city.saitama.jp !city.sapporo.jp @@ -1459,7 +1370,6 @@ ulsan.kr *.kw // ky : http://www.icta.ky/da_ky_reg_dom.php -// Confirmed by registry 2008-06-17 ky edu.ky gov.ky @@ -1477,26 +1387,10 @@ mil.kz com.kz // la : http://en.wikipedia.org/wiki/.la -// Submitted by registry 2008-06-10 la -int.la -net.la -info.la -edu.la -gov.la -per.la -com.la -org.la -// see http://www.c.la/ -c.la // lb : http://en.wikipedia.org/wiki/.lb -// Submitted by registry 2008-06-17 -com.lb -edu.lb -gov.lb -net.lb -org.lb +*.lb // lc : http://en.wikipedia.org/wiki/.lc lc @@ -1526,12 +1420,7 @@ grp.lk hotel.lk // lr : http://psg.com/dns/lr/lr.txt -// Submitted by registry 2008-06-17 -com.lr -edu.lr -gov.lr -org.lr -net.lr +*.lr // ls : http://en.wikipedia.org/wiki/.ls ls @@ -1634,7 +1523,6 @@ gov.mo mobi // mp : http://www.dot.mp/ -// Confirmed by registry 2008-06-17 mp // mq : http://en.wikipedia.org/wiki/.mq @@ -1698,12 +1586,6 @@ ne // net : http://en.wikipedia.org/wiki/.net net -// CentralNic names : http://www.centralnic.com/names/domains -// Submitted by registry 2008-06-17 -gb.net -se.net -uk.net - // nf : http://en.wikipedia.org/wiki/.nf nf com.nf @@ -1718,36 +1600,22 @@ other.nf store.nf // ng : http://psg.com/dns/ng/ -// Submitted by registry 2008-06-17 -ac.ng -com.ng -edu.ng -gov.ng -net.ng -org.ng +ng // ni : http://www.nic.ni/dominios.htm *.ni // nl : http://www.domain-registry.nl/ace.php/c,728,122,,,,Home.html -// Confirmed by registry (with technical -// reservations) 2008-06-08 nl // no : http://www.norid.no/regelverk/index.en.html -// The Norwegian registry has declined to notify us of updates. The web pages -// referenced below are the official source of the data. There is also an -// announce mailing list: -// https://postlister.uninett.no/sympa/info/norid-diskusjon no -// Norid generic domains : http://www.norid.no/regelverk/vedlegg-c.en.html fhs.no vgs.no fylkesbibl.no folkebibl.no museum.no idrett.no -// Non-Norid generic domains : http://www.norid.no/regelverk/vedlegg-d.en.html mil.no stat.no dep.no @@ -2318,7 +2186,6 @@ råde.no salangen.no siellak.no saltdal.no -salat.no sálát.no sálat.no samnanger.no @@ -2458,7 +2325,7 @@ utsira.no vadso.no vadsø.no cahcesuolo.no -čáhcesuolo.no +cáhcesuolo.no vaksdal.no valle.no vang.no @@ -2505,7 +2372,6 @@ våler.hedmark.no *.np // nr : http://cenpac.net.nr/dns/index.html -// Confirmed by registry 2008-06-17 nr biz.nr info.nr @@ -2524,13 +2390,9 @@ nu // om : http://en.wikipedia.org/wiki/.om *.om -// org : http://en.wikipedia.org/wiki/.org +// org : http://en.wikipedia.org/wiki/.og org -// CentralNic names : http://www.centralnic.com/names/domains -// Submitted by registry 2008-06-17 -ae.org - // pa : http://www.nic.pa/ *.pa @@ -2547,7 +2409,7 @@ edu.pf *.pg // ph : http://www.domains.ph/FAQ2.asp -// Submitted by registry 2008-06-13 +// list of 2nd level tlds ? ph com.ph net.ph @@ -2556,7 +2418,6 @@ gov.ph edu.ph ngo.ph mil.ph -i.ph // pk : http://pk5.pknic.net.pk/pk5/msgNamepk.PK pk @@ -2875,13 +2736,7 @@ gouv.rw *.sa // sb : http://www.sbnic.net.sb/ -// Submitted by registry 2008-06-08 -sb -com.sb -edu.sb -gov.sb -net.sb -org.sb +*.sb // sc : http://www.nic.sc/ sc @@ -2892,14 +2747,14 @@ org.sc edu.sc // sd : http://www.isoc.sd/sudanic.isoc.sd/billing_pricing.htm -// Submitted by registry 2008-06-17 sd com.sd net.sd org.sd edu.sd med.sd - gov.sd +tv.sd +gov.sd info.sd // se : http://en.wikipedia.org/wiki/.se @@ -2949,20 +2804,12 @@ sh // si : http://en.wikipedia.org/wiki/.si si -// sj : No registrations at this time. -// Submitted by registry 2008-06-16 - // sk : http://en.wikipedia.org/wiki/.sk sk -// sl : http://www.nic.sl -// Submitted by registry 2008-06-12 +// sl : http://en.wikipedia.org/wiki/.sl +// list of 2nd level domains ? sl -com.sl -net.sl -edu.sl -gov.sl -org.sl // sm : http://en.wikipedia.org/wiki/.sm sm @@ -3004,15 +2851,7 @@ tf tg // th : http://en.wikipedia.org/wiki/.th -// Submitted by registry 2008-06-17 -th -ac.th -co.th -go.th -in.th -mi.th -net.th -or.th +*.th // tj : http://www.nic.tj/policy.htm tj @@ -3046,14 +2885,8 @@ tm tn // to : http://en.wikipedia.org/wiki/.to -// Submitted by registry 2008-06-17 +// list of 2nd level tlds ? to -com.to -gov.to -net.to -org.to -edu.to -mil.to // tr : http://en.wikipedia.org/wiki/.tr *.tr @@ -3102,12 +2935,7 @@ club.tw 商業.tw // tz : http://en.wikipedia.org/wiki/.tz -// Submitted by registry 2008-06-17 -ac.tz -co.tz -go.tz -ne.tz -or.tz +*.tz // ua : http://www.nic.net.ua/ ua @@ -3273,14 +3101,8 @@ co.uz va // vc : http://en.wikipedia.org/wiki/.vc -// Submitted by registry 2008-06-13 +// list of 2nd level tlds ? vc -com.vc -net.vc -org.vc -gov.vc -mil.vc -edu.vc // ve : http://registro.nic.ve/nicve/registro/index.html *.ve From a8da42070f1b9948d0ea5091aaa5f974db6b53c9 Mon Sep 17 00:00:00 2001 From: Ted Mielczarek Date: Wed, 18 Jun 2008 11:06:57 -0400 Subject: [PATCH 04/66] bug 428303 - Mercurial integration for breakpad. r=bsmedberg --- toolkit/crashreporter/tools/symbolstore.py | 91 +++++++++++++++++++--- 1 file changed, 80 insertions(+), 11 deletions(-) diff --git a/toolkit/crashreporter/tools/symbolstore.py b/toolkit/crashreporter/tools/symbolstore.py index 8a9a639ce576..78f655019437 100755 --- a/toolkit/crashreporter/tools/symbolstore.py +++ b/toolkit/crashreporter/tools/symbolstore.py @@ -193,21 +193,22 @@ class CVSFileInfo(VCSFileInfo): return "cvs:%s:%s:%s" % (self.clean_root, file, self.revision) return file +# This regex separates protocol and optional username/password from a url. +# For instance, all the following urls will be transformed into +# 'foo.com/bar': +# +# http://foo.com/bar +# svn+ssh://user@foo.com/bar +# svn+ssh://user:pass@foo.com/bar +# +# This is used by both SVN and HG +rootRegex = re.compile(r'^\S+?:/+(?:[^\s/]*@)?(\S+)$') + class SVNFileInfo(VCSFileInfo): url = None repo = None svndata = {} - # This regex separates protocol and optional username/password from a url. - # For instance, all the following urls will be transformed into - # 'foo.com/bar': - # - # http://foo.com/bar - # svn+ssh://user@foo.com/bar - # svn+ssh://user:pass@foo.com/bar - # - rootRegex = re.compile(r'^\S+?:/+(?:[^\s/]*@)?(\S+)$') - def __init__(self, file): """ We only want to run subversion's info tool once so pull all the data here. """ @@ -232,7 +233,7 @@ class SVNFileInfo(VCSFileInfo): def GetRoot(self): key = "Repository Root" if key in self.svndata: - match = self.rootRegex.match(self.svndata[key]) + match = rootRegex.match(self.svndata[key]) if match: return match.group(1) print >> sys.stderr, "Failed to get SVN Root for %s" % self.file @@ -258,12 +259,77 @@ class SVNFileInfo(VCSFileInfo): print >> sys.stderr, "Failed to get SVN Filename for %s" % self.file return self.file +class HGRepoInfo(): + # HG info is per-repo, so cache it in a static + # member var + repos = {} + def __init__(self, path, rev, cleanroot): + self.path = path + self.rev = rev + self.cleanroot = cleanroot + +class HGFileInfo(VCSFileInfo): + def __init__(self, file, srcdir): + VCSFileInfo.__init__(self, file) + # we should only have to collect this info once per-repo + if not srcdir in HGRepoInfo.repos: + rev = os.popen('hg identify -i "%s"' % srcdir, "r").readlines()[0].rstrip() + # could have a + if there are uncommitted local changes + if rev.endswith('+'): + rev = rev[:-1] + + path = os.popen('hg -R "%s" showconfig paths.default' % srcdir, "r").readlines()[0].rstrip() + if path == '': + hg_root = os.environ.get("SRCSRV_ROOT") + if hg_root: + path = hg_root + else: + print >> sys.stderr, "Failed to get HG Repo for %s" % srcdir + if path != '': # not there? + match = rootRegex.match(path) + if match: + cleanroot = match.group(1) + if cleanroot.endswith('/'): + cleanroot = cleanroot[:-1] + HGRepoInfo.repos[srcdir] = HGRepoInfo(path, rev, cleanroot) + self.repo = HGRepoInfo.repos[srcdir] + self.file = file + self.srcdir = srcdir + + def GetRoot(self): + return self.repo.path + + def GetCleanRoot(self): + return self.repo.cleanroot + + def GetRevision(self): + return self.repo.rev + + def GetFilename(self): + file = self.file + if self.revision and self.clean_root: + if self.srcdir: + # strip the base path off + file = os.path.normpath(file) + if IsInDir(file, self.srcdir): + file = file[len(self.srcdir):] + if file.startswith('/') or file.startswith('\\'): + file = file[1:] + return "hg:%s:%s:%s" % (self.clean_root, file, self.revision) + return file + # Utility functions # A cache of files for which VCS info has already been determined. Used to # prevent extra filesystem activity or process launching. vcsFileInfoCache = {} +def IsInDir(file, dir): + # the lower() is to handle win32+vc8, where + # the source filenames come out all lowercase, + # but the srcdir can be mixed case + return os.path.abspath(file).lower().startswith(os.path.abspath(dir).lower()) + def GetVCSFilename(file, srcdir): """Given a full path to a file, and the top source directory, look for version control information about this file, and return @@ -291,6 +357,9 @@ def GetVCSFilename(file, srcdir): elif os.path.isdir(os.path.join(path, ".svn")) or \ os.path.isdir(os.path.join(path, "_svn")): fileInfo = SVNFileInfo(file); + elif os.path.isdir(os.path.join(srcdir, '.hg')) and \ + IsInDir(file, srcdir): + fileInfo = HGFileInfo(file, srcdir) vcsFileInfoCache[file] = fileInfo if fileInfo: From 7c88a890448a1342bda08bbdf016e89fda24b3bb Mon Sep 17 00:00:00 2001 From: Kai Engert Date: Wed, 18 Jun 2008 21:20:16 +0200 Subject: [PATCH 05/66] Bug 436870, FF3 RC1 loses SSL certificate exceptions Patch contributed by Honza Bambas r=kaie --- security/manager/ssl/src/nsCertOverrideService.h | 1 + 1 file changed, 1 insertion(+) diff --git a/security/manager/ssl/src/nsCertOverrideService.h b/security/manager/ssl/src/nsCertOverrideService.h index 645f4c22c7de..153cf361dada 100644 --- a/security/manager/ssl/src/nsCertOverrideService.h +++ b/security/manager/ssl/src/nsCertOverrideService.h @@ -109,6 +109,7 @@ class nsCertOverrideEntry : public PLDHashEntryHdr nsCertOverrideEntry(const nsCertOverrideEntry& toCopy) { mSettings = toCopy.mSettings; + mHostWithPort = toCopy.mHostWithPort; } ~nsCertOverrideEntry() From 0f228913f3514439c27c8a8e69bfba3ec5297405 Mon Sep 17 00:00:00 2001 From: Kai Engert Date: Wed, 18 Jun 2008 21:36:29 +0200 Subject: [PATCH 06/66] Bug 431819, SSL client auth, repeated prompts for client certificate r=rrelyea, r=dveditz --- netwerk/base/public/security-prefs.js | 1 + .../pki/resources/content/clientauthask.js | 26 ++ .../pki/resources/content/clientauthask.xul | 1 + security/manager/pki/src/nsNSSDialogs.cpp | 10 +- .../ssl/public/nsIClientAuthDialogs.idl | 6 + security/manager/ssl/src/Makefile.in | 1 + .../manager/ssl/src/nsClientAuthRemember.cpp | 256 ++++++++++++++++++ .../manager/ssl/src/nsClientAuthRemember.h | 172 ++++++++++++ security/manager/ssl/src/nsNSSComponent.cpp | 11 +- security/manager/ssl/src/nsNSSComponent.h | 5 + security/manager/ssl/src/nsNSSIOLayer.cpp | 98 +++++-- security/manager/ssl/src/nsNSSIOLayer.h | 4 + 12 files changed, 572 insertions(+), 19 deletions(-) create mode 100644 security/manager/ssl/src/nsClientAuthRemember.cpp create mode 100644 security/manager/ssl/src/nsClientAuthRemember.h diff --git a/netwerk/base/public/security-prefs.js b/netwerk/base/public/security-prefs.js index c1ac20e9ab78..cc43f33f4d7e 100644 --- a/netwerk/base/public/security-prefs.js +++ b/netwerk/base/public/security-prefs.js @@ -61,6 +61,7 @@ pref("security.ssl3.rsa_null_sha", false); pref("security.ssl3.rsa_null_md5", false); pref("security.default_personal_cert", "Ask Every Time"); +pref("security.remember_cert_checkbox_default_setting", true); pref("security.ask_for_password", 0); pref("security.password_lifetime", 30); pref("security.warn_entering_secure", false); diff --git a/security/manager/pki/resources/content/clientauthask.js b/security/manager/pki/resources/content/clientauthask.js index 9f9db3aaa8d4..ae35604c6c04 100644 --- a/security/manager/pki/resources/content/clientauthask.js +++ b/security/manager/pki/resources/content/clientauthask.js @@ -42,6 +42,7 @@ const nsIDialogParamBlock = Components.interfaces.nsIDialogParamBlock; var dialogParams; var itemCount = 0; +var rememberBox; function onLoad() { @@ -54,6 +55,28 @@ function onLoad() org = dialogParams.GetString(1); issuer = dialogParams.GetString(2); + // added with bug 431819. reuse string from caps in order to avoid string changes + var capsBundle = srGetStrBundle("chrome://global/locale/security/caps.properties"); + var rememberString = capsBundle.GetStringFromName("CheckMessage"); + var rememberSetting = true; + + var pref = Components.classes['@mozilla.org/preferences-service;1'] + .getService(Components.interfaces.nsIPrefService); + if (pref) { + pref = pref.getBranch(null); + try { + rememberSetting = + pref.getBoolPref("security.remember_cert_checkbox_default_setting"); + } + catch(e) { + // pref is missing + } + } + + rememberBox = document.getElementById("rememberBox"); + rememberBox.label = rememberString; + rememberBox.checked = rememberSetting; + var bundle = srGetStrBundle("chrome://pippki/locale/pippki.properties"); var message1 = bundle.formatStringFromName("clientAuthMessage1", [org], @@ -98,11 +121,14 @@ function doOK() dialogParams.SetInt(0,1); var index = parseInt(document.getElementById("nicknames").value); dialogParams.SetInt(1, index); + dialogParams.SetInt(2, rememberBox.checked); return true; } function doCancel() { dialogParams.SetInt(0,0); + dialogParams.SetInt(1, -1); // invalid value + dialogParams.SetInt(2, rememberBox.checked); return true; } diff --git a/security/manager/pki/resources/content/clientauthask.xul b/security/manager/pki/resources/content/clientauthask.xul index 3baacae55267..66b0bf2799d5 100644 --- a/security/manager/pki/resources/content/clientauthask.xul +++ b/security/manager/pki/resources/content/clientauthask.xul @@ -73,6 +73,7 @@ &clientAuthAsk.message3; + diff --git a/security/manager/pki/src/nsNSSDialogs.cpp b/security/manager/pki/src/nsNSSDialogs.cpp index 65d8f5c8eeb2..5805159244d2 100644 --- a/security/manager/pki/src/nsNSSDialogs.cpp +++ b/security/manager/pki/src/nsNSSDialogs.cpp @@ -309,10 +309,18 @@ nsNSSDialogs::ChooseCertificate(nsIInterfaceRequestor *ctx, const PRUnichar *cn, if (NS_FAILED(rv)) return rv; PRInt32 status; - rv = block->GetInt(0, &status); if (NS_FAILED(rv)) return rv; + nsCOMPtr extraResult = do_QueryInterface(ctx); + if (extraResult) { + PRInt32 rememberSelection; + rv = block->GetInt(2, &rememberSelection); + if (NS_SUCCEEDED(rv)) { + extraResult->SetRememberClientAuthCertificate(rememberSelection!=0); + } + } + *canceled = (status == 0)?PR_TRUE:PR_FALSE; if (!*canceled) { // retrieve the nickname diff --git a/security/manager/ssl/public/nsIClientAuthDialogs.idl b/security/manager/ssl/public/nsIClientAuthDialogs.idl index 667bb97b08f5..fc7638792be5 100644 --- a/security/manager/ssl/public/nsIClientAuthDialogs.idl +++ b/security/manager/ssl/public/nsIClientAuthDialogs.idl @@ -61,6 +61,12 @@ interface nsIClientAuthDialogs : nsISupports out boolean canceled); }; +[scriptable, uuid(95c4373e-bdd4-4a63-b431-f5b000367721)] +interface nsIClientAuthUserDecision : nsISupports +{ + attribute boolean rememberClientAuthCertificate; +}; + %{C++ #define NS_CLIENTAUTHDIALOGS_CONTRACTID "@mozilla.org/nsClientAuthDialogs;1" %} diff --git a/security/manager/ssl/src/Makefile.in b/security/manager/ssl/src/Makefile.in index 031be55a5712..39a1579286b7 100644 --- a/security/manager/ssl/src/Makefile.in +++ b/security/manager/ssl/src/Makefile.in @@ -60,6 +60,7 @@ CPPSRCS = \ nsNSSCleaner.cpp \ nsCertOverrideService.cpp \ nsRecentBadCerts.cpp \ + nsClientAuthRemember.cpp \ nsPSMBackgroundThread.cpp \ nsSSLThread.cpp \ nsCertVerificationThread.cpp \ diff --git a/security/manager/ssl/src/nsClientAuthRemember.cpp b/security/manager/ssl/src/nsClientAuthRemember.cpp new file mode 100644 index 000000000000..fcb3ebc14552 --- /dev/null +++ b/security/manager/ssl/src/nsClientAuthRemember.cpp @@ -0,0 +1,256 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * 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.org code. + * + * The Initial Developer of the Original Code is + * Red Hat, Inc. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Kai Engert + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsClientAuthRemember.h" + +#include "nsIX509Cert.h" +#include "nsCRT.h" +#include "nsNetUtil.h" +#include "nsIObserverService.h" +#include "nsNetUtil.h" +#include "nsISupportsPrimitives.h" +#include "nsPromiseFlatString.h" +#include "nsProxiedService.h" +#include "nsStringBuffer.h" +#include "nsAutoLock.h" +#include "nspr.h" +#include "pk11pub.h" +#include "certdb.h" +#include "sechash.h" +#include "ssl.h" // For SSL_ClearSessionCache + +#include "nsNSSCleaner.h" +NSSCleanupAutoPtrClass(CERTCertificate, CERT_DestroyCertificate) + +NS_IMPL_THREADSAFE_ISUPPORTS1(nsClientAuthRememberService, + nsIObserver) + +nsClientAuthRememberService::nsClientAuthRememberService() +{ + monitor = PR_NewMonitor(); +} + +nsClientAuthRememberService::~nsClientAuthRememberService() +{ + RemoveAllFromMemory(); + if (monitor) + PR_DestroyMonitor(monitor); +} + +nsresult +nsClientAuthRememberService::Init() +{ + if (!mSettingsTable.Init()) + return NS_ERROR_OUT_OF_MEMORY; + + nsCOMPtr proxyman(do_GetService(NS_XPCOMPROXY_CONTRACTID)); + if (!proxyman) + return NS_ERROR_FAILURE; + + nsCOMPtr observerService(do_GetService("@mozilla.org/observer-service;1")); + nsCOMPtr proxiedObserver; + + NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, + NS_GET_IID(nsIObserverService), + observerService, + NS_PROXY_SYNC, + getter_AddRefs(proxiedObserver)); + + if (proxiedObserver) { + proxiedObserver->AddObserver(this, "profile-before-change", PR_TRUE); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsClientAuthRememberService::Observe(nsISupports *aSubject, + const char *aTopic, + const PRUnichar *aData) +{ + // check the topic + if (!nsCRT::strcmp(aTopic, "profile-before-change")) { + // The profile is about to change, + // or is going away because the application is shutting down. + + nsAutoMonitor lock(monitor); + RemoveAllFromMemory(); + } + + return NS_OK; +} + +void nsClientAuthRememberService::ClearRememberedDecisions() +{ + nsAutoMonitor lock(monitor); + RemoveAllFromMemory(); +} + +void +nsClientAuthRememberService::RemoveAllFromMemory() +{ + mSettingsTable.Clear(); +} + +static nsresult +GetCertFingerprintByOidTag(CERTCertificate* nsscert, + SECOidTag aOidTag, + nsCString &fp) +{ + unsigned int hash_len = HASH_ResultLenByOidTag(aOidTag); + nsRefPtr fingerprint = nsStringBuffer::Alloc(hash_len); + if (!fingerprint) + return NS_ERROR_OUT_OF_MEMORY; + + PK11_HashBuf(aOidTag, (unsigned char*)fingerprint->Data(), + nsscert->derCert.data, nsscert->derCert.len); + + SECItem fpItem; + fpItem.data = (unsigned char*)fingerprint->Data(); + fpItem.len = hash_len; + + fp.Adopt(CERT_Hexify(&fpItem, 1)); + return NS_OK; +} + +nsresult +nsClientAuthRememberService::RememberDecision(const nsACString & aHostName, + CERTCertificate *aServerCert, CERTCertificate *aClientCert) +{ + // aClientCert == NULL means: remember that user does not want to use a cert + NS_ENSURE_ARG_POINTER(aServerCert); + if (aHostName.IsEmpty()) + return NS_ERROR_INVALID_ARG; + + nsCAutoString fpStr; + nsresult rv = GetCertFingerprintByOidTag(aServerCert, SEC_OID_SHA256, fpStr); + if (NS_FAILED(rv)) + return rv; + + { + nsAutoMonitor lock(monitor); + if (aClientCert) { + AddEntryToList(aHostName, fpStr, + nsDependentCString(aClientCert->nickname)); + } + else { + nsCString empty; + AddEntryToList(aHostName, fpStr, empty); + } + } + + return NS_OK; +} + +nsresult +nsClientAuthRememberService::HasRememberedDecision(const nsACString & aHostName, + CERTCertificate *aCert, + nsACString & aClientNickname, + PRBool *_retval) +{ + if (aHostName.IsEmpty()) + return NS_ERROR_INVALID_ARG; + + NS_ENSURE_ARG_POINTER(aCert); + NS_ENSURE_ARG_POINTER(_retval); + *_retval = PR_FALSE; + + nsresult rv; + nsCAutoString fpStr; + rv = GetCertFingerprintByOidTag(aCert, SEC_OID_SHA256, fpStr); + if (NS_FAILED(rv)) + return rv; + + nsCAutoString hostCert; + GetHostWithCert(aHostName, fpStr, hostCert); + nsClientAuthRemember settings; + + { + nsAutoMonitor lock(monitor); + nsClientAuthRememberEntry *entry = mSettingsTable.GetEntry(hostCert.get()); + if (!entry) + return NS_OK; + settings = entry->mSettings; // copy + } + + aClientNickname = settings.mClientNickname; + *_retval = PR_TRUE; + return NS_OK; +} + +nsresult +nsClientAuthRememberService::AddEntryToList(const nsACString &aHostName, + const nsACString &fingerprint, + const nsACString &client_nickname) + +{ + nsCAutoString hostCert; + GetHostWithCert(aHostName, fingerprint, hostCert); + + { + nsAutoMonitor lock(monitor); + nsClientAuthRememberEntry *entry = mSettingsTable.PutEntry(hostCert.get()); + + if (!entry) { + NS_ERROR("can't insert a null entry!"); + return NS_ERROR_OUT_OF_MEMORY; + } + + entry->mHostWithCert = hostCert; + + nsClientAuthRemember &settings = entry->mSettings; + settings.mAsciiHost = aHostName; + settings.mFingerprint = fingerprint; + settings.mClientNickname = client_nickname; + } + + return NS_OK; +} + +void +nsClientAuthRememberService::GetHostWithCert(const nsACString & aHostName, + const nsACString & fingerprint, + nsACString& _retval) +{ + nsCAutoString hostCert(aHostName); + hostCert.AppendLiteral(":"); + hostCert.Append(fingerprint); + + _retval.Assign(hostCert); +} diff --git a/security/manager/ssl/src/nsClientAuthRemember.h b/security/manager/ssl/src/nsClientAuthRemember.h new file mode 100644 index 000000000000..efa7c959f599 --- /dev/null +++ b/security/manager/ssl/src/nsClientAuthRemember.h @@ -0,0 +1,172 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * 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.org code. + * + * The Initial Developer of the Original Code is + * Red Hat, Inc. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Kai Engert + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef __NSCLIENTAUTHREMEMBER_H__ +#define __NSCLIENTAUTHREMEMBER_H__ + +#include "nsTHashtable.h" +#include "nsIObserver.h" +#include "nsIX509Cert.h" +#include "nsAutoPtr.h" +#include "nsNSSCertificate.h" +#include "nsString.h" +#include "prmon.h" + +class nsClientAuthRemember +{ +public: + + nsClientAuthRemember() + { + } + + nsClientAuthRemember(const nsClientAuthRemember &other) + { + this->operator=(other); + } + + nsClientAuthRemember &operator=(const nsClientAuthRemember &other) + { + mAsciiHost = other.mAsciiHost; + mFingerprint = other.mFingerprint; + mClientNickname = other.mClientNickname; + return *this; + } + + nsCString mAsciiHost; + nsCString mFingerprint; + nsCString mClientNickname; +}; + + +// hash entry class +class nsClientAuthRememberEntry : public PLDHashEntryHdr +{ + public: + // Hash methods + typedef const char* KeyType; + typedef const char* KeyTypePointer; + + // do nothing with aHost - we require mHead to be set before we're live! + nsClientAuthRememberEntry(KeyTypePointer aHostWithCertUTF8) + { + } + + nsClientAuthRememberEntry(const nsClientAuthRememberEntry& toCopy) + { + mSettings = toCopy.mSettings; + } + + ~nsClientAuthRememberEntry() + { + } + + KeyType GetKey() const + { + return HostWithCertPtr(); + } + + KeyTypePointer GetKeyPointer() const + { + return HostWithCertPtr(); + } + + PRBool KeyEquals(KeyTypePointer aKey) const + { + return !strcmp(HostWithCertPtr(), aKey); + } + + static KeyTypePointer KeyToPointer(KeyType aKey) + { + return aKey; + } + + static PLDHashNumber HashKey(KeyTypePointer aKey) + { + // PL_DHashStringKey doesn't use the table parameter, so we can safely + // pass nsnull + return PL_DHashStringKey(nsnull, aKey); + } + + enum { ALLOW_MEMMOVE = PR_FALSE }; + + // get methods + inline const nsCString &HostWithCert() const { return mHostWithCert; } + + inline KeyTypePointer HostWithCertPtr() const + { + return mHostWithCert.get(); + } + + nsClientAuthRemember mSettings; + nsCString mHostWithCert; +}; + +class nsClientAuthRememberService : public nsIObserver +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIOBSERVER + + nsClientAuthRememberService(); + ~nsClientAuthRememberService(); + + nsresult Init(); + + static void GetHostWithCert(const nsACString & aHostName, + const nsACString & nickname, nsACString& _retval); + + nsresult RememberDecision(const nsACString & aHostName, + CERTCertificate *aServerCert, CERTCertificate *aClientCert); + nsresult HasRememberedDecision(const nsACString & aHostName, + CERTCertificate *aCert, nsACString & aClientNickname, PRBool *_retval); + + void ClearRememberedDecisions(); + +protected: + PRMonitor *monitor; + nsTHashtable mSettingsTable; + + void RemoveAllFromMemory(); + nsresult AddEntryToList(const nsACString &host, + const nsACString &server_fingerprint, + const nsACString &client_nickname); +}; + +#endif diff --git a/security/manager/ssl/src/nsNSSComponent.cpp b/security/manager/ssl/src/nsNSSComponent.cpp index 45adcb91b2a1..f180f1d121ba 100644 --- a/security/manager/ssl/src/nsNSSComponent.cpp +++ b/security/manager/ssl/src/nsNSSComponent.cpp @@ -296,6 +296,7 @@ nsNSSComponent::nsNSSComponent() memset(&mIdentityInfoCallOnce, 0, sizeof(PRCallOnceType)); nsSSLIOLayerHelpers::Init(); + mClientAuthRememberService.Init(); NS_ASSERTION( (0 == mInstanceCount), "nsNSSComponent is a singleton, but instantiated multiple times!"); ++mInstanceCount; @@ -1683,6 +1684,7 @@ nsNSSComponent::ShutdownNSS() ShutdownSmartCardThreads(); SSL_ClearSessionCache(); + mClientAuthRememberService.ClearRememberedDecisions(); UnloadLoadableRoots(); CleanupIdentityInfo(); PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("evaporating psm resources\n")); @@ -2148,6 +2150,7 @@ void nsNSSComponent::ShowAlert(AlertIdentifier ai) nsresult nsNSSComponent::LogoutAuthenticatedPK11() { + mClientAuthRememberService.ClearRememberedDecisions(); return mShutdownObjectList->doPK11Logout(); } @@ -2409,6 +2412,13 @@ nsNSSComponent::DoProfileChangeNetRestore() mIsNetworkDown = PR_FALSE; } +NS_IMETHODIMP +nsNSSComponent::GetClientAuthRememberService(nsClientAuthRememberService **cars) +{ + NS_ENSURE_ARG_POINTER(cars); + *cars = &mClientAuthRememberService; +} + //--------------------------------------------- // Implementing nsICryptoHash //--------------------------------------------- @@ -3178,4 +3188,3 @@ PSMContentListener::SetParentContentListener(nsIURIContentListener * aContentLis mParentContentListener = aContentListener; return NS_OK; } - diff --git a/security/manager/ssl/src/nsNSSComponent.h b/security/manager/ssl/src/nsNSSComponent.h index e3d1f66ba178..eada819c8600 100644 --- a/security/manager/ssl/src/nsNSSComponent.h +++ b/security/manager/ssl/src/nsNSSComponent.h @@ -69,6 +69,7 @@ #include "nsNSSCallbacks.h" #include "nsNSSHelper.h" +#include "nsClientAuthRemember.h" #define NS_NSSCOMPONENT_CID \ {0xa277189c, 0x1dd1, 0x11b2, {0xa8, 0xc9, 0xe4, 0xe8, 0xbf, 0xb1, 0x33, 0x8e}} @@ -171,6 +172,8 @@ class NS_NO_VTABLE nsINSSComponent : public nsISupports { NS_IMETHOD DispatchEvent(const nsAString &eventType, const nsAString &token) = 0; + NS_IMETHOD GetClientAuthRememberService(nsClientAuthRememberService **cars) = 0; + NS_IMETHOD EnsureIdentityInfoLoaded() = 0; }; @@ -259,6 +262,7 @@ public: NS_IMETHOD ShutdownSmartCardThread(SECMODModule *module); NS_IMETHOD PostEvent(const nsAString &eventType, const nsAString &token); NS_IMETHOD DispatchEvent(const nsAString &eventType, const nsAString &token); + NS_IMETHOD GetClientAuthRememberService(nsClientAuthRememberService **cars); NS_IMETHOD EnsureIdentityInfoLoaded(); private: @@ -324,6 +328,7 @@ private: nsSSLThread *mSSLThread; nsCertVerificationThread *mCertVerificationThread; nsNSSHttpInterface mHttpForNSS; + nsClientAuthRememberService mClientAuthRememberService; static PRStatus PR_CALLBACK IdentityInfoInit(void); PRCallOnceType mIdentityInfoCallOnce; diff --git a/security/manager/ssl/src/nsNSSIOLayer.cpp b/security/manager/ssl/src/nsNSSIOLayer.cpp index d7cc58357b02..0a4882189ad7 100644 --- a/security/manager/ssl/src/nsNSSIOLayer.cpp +++ b/security/manager/ssl/src/nsNSSIOLayer.cpp @@ -58,6 +58,7 @@ #include "nsIDateTimeFormat.h" #include "nsDateTimeFormatCID.h" #include "nsIClientAuthDialogs.h" +#include "nsClientAuthRemember.h" #include "nsICertOverrideService.h" #include "nsIBadCertListener2.h" #include "nsISSLErrorListener.h" @@ -237,7 +238,7 @@ void nsNSSSocketInfo::virtualDestroyNSSReference() { } -NS_IMPL_THREADSAFE_ISUPPORTS8(nsNSSSocketInfo, +NS_IMPL_THREADSAFE_ISUPPORTS9(nsNSSSocketInfo, nsITransportSecurityInfo, nsISSLSocketControl, nsIInterfaceRequestor, @@ -245,7 +246,8 @@ NS_IMPL_THREADSAFE_ISUPPORTS8(nsNSSSocketInfo, nsIIdentityInfo, nsIAssociatedContentSecurity, nsISerializable, - nsIClassInfo) + nsIClassInfo, + nsIClientAuthUserDecision) nsresult nsNSSSocketInfo::GetHandshakePending(PRBool *aHandshakePending) @@ -299,6 +301,19 @@ PRBool nsNSSSocketInfo::GetCanceled() return mCanceled; } +NS_IMETHODIMP nsNSSSocketInfo::GetRememberClientAuthCertificate(PRBool *aRememberClientAuthCertificate) +{ + NS_ENSURE_ARG_POINTER(aRememberClientAuthCertificate); + *aRememberClientAuthCertificate = mRememberClientAuthCertificate; + return NS_OK; +} + +NS_IMETHODIMP nsNSSSocketInfo::SetRememberClientAuthCertificate(PRBool aRememberClientAuthCertificate) +{ + mRememberClientAuthCertificate = aRememberClientAuthCertificate; + return NS_OK; +} + void nsNSSSocketInfo::SetHasCleartextPhase(PRBool aHasCleartextPhase) { mHasCleartextPhase = aHasCleartextPhase; @@ -2464,12 +2479,10 @@ SECStatus nsNSS_SSLGetClientAuthData(void* arg, PRFileDesc* socket, nsNSSShutDownPreventionLock locker; void* wincx = NULL; SECStatus ret = SECFailure; - nsresult rv; nsNSSSocketInfo* info = NULL; PRArenaPool* arena = NULL; char** caNameStrings; CERTCertificate* cert = NULL; - CERTCertificate* serverCert = NULL; SECKEYPrivateKey* privKey = NULL; CERTCertList* certList = NULL; CERTCertListNode* node; @@ -2593,13 +2606,63 @@ SECStatus nsNSS_SSLGetClientAuthData(void* arg, PRFileDesc* socket, goto noCert; } } + else { // Not Auto => ask + /* Get the SSL Certificate */ + CERTCertificate* serverCert = NULL; + CERTCertificateCleaner serverCertCleaner(serverCert); + serverCert = SSL_PeerCertificate(socket); + if (serverCert == NULL) { + /* couldn't get the server cert: what do I do? */ + goto loser; + } + + nsXPIDLCString hostname; + info->GetHostName(getter_Copies(hostname)); + + nsresult rv; + NS_DEFINE_CID(nssComponentCID, NS_NSSCOMPONENT_CID); + nsCOMPtr nssComponent(do_GetService(nssComponentCID, &rv)); + // it's ok to keep our raw pointer to the nsClientAuthRememberService + // as long as we hold the reference to the nssComponent. + // Yes, this sucks, but this is branch only code, + // and I don't want to deal with new interfaces, and want to use full + // typed pointers. + // Note nsINSSComponent is NOT exposed to anywhere outside of PSM. + nsClientAuthRememberService *cars = nsnull; + if (nssComponent) { + nssComponent->GetClientAuthRememberService(&cars); + } + + PRBool hasRemembered = PR_FALSE; + nsCString rememberedNickname; + if (cars) { + PRBool found; + nsresult rv = cars->HasRememberedDecision(hostname, + serverCert, + rememberedNickname, &found); + if (NS_SUCCEEDED(rv) && found) { + hasRemembered = PR_TRUE; + } + } + + PRBool canceled = PR_FALSE; + +if (hasRemembered) +{ + if (rememberedNickname.IsEmpty()) + canceled = PR_TRUE; else { + char *const_nickname = const_cast(rememberedNickname.get()); + cert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(), const_nickname); + } +} +else +{ /* user selects a cert to present */ nsIClientAuthDialogs *dialogs = NULL; PRInt32 selectedIndex = -1; PRUnichar **certNicknameList = NULL; PRUnichar **certDetailsList = NULL; - PRBool canceled; /* find all user certs that are for SSL */ /* note that we are allowing expired certs in this list */ @@ -2656,13 +2719,6 @@ SECStatus nsNSS_SSLGetClientAuthData(void* arg, PRFileDesc* socket, NS_ASSERTION(nicknames->numnicknames == NumberOfCerts, "nicknames->numnicknames != NumberOfCerts"); - /* Get the SSL Certificate */ - serverCert = SSL_PeerCertificate(socket); - if (serverCert == NULL) { - /* couldn't get the server cert: what do I do? */ - goto loser; - } - /* Get CN and O of the subject and O of the issuer */ char *ccn = CERT_GetCommonName(&serverCert->subject); charCleaner ccnCleaner(ccn); @@ -2670,8 +2726,6 @@ SECStatus nsNSS_SSLGetClientAuthData(void* arg, PRFileDesc* socket, PRInt32 port; info->GetPort(&port); - char *hostname = SSL_RevealURL(socket); - charCleaner hostnameCleaner(hostname); nsString cn_host_port; if (ccn && strcmp(ccn, hostname) == 0) { @@ -2695,8 +2749,6 @@ SECStatus nsNSS_SSLGetClientAuthData(void* arg, PRFileDesc* socket, NS_ConvertUTF8toUTF16 issuer(cissuer); if (cissuer) PORT_Free(cissuer); - CERT_DestroyCertificate(serverCert); - certNicknameList = (PRUnichar **)nsMemory::Alloc(sizeof(PRUnichar *) * nicknames->numnicknames); if (!certNicknameList) goto loser; @@ -2764,9 +2816,12 @@ SECStatus nsNSS_SSLGetClientAuthData(void* arg, PRFileDesc* socket, if (NS_FAILED(rv)) goto loser; - if (canceled) { rv = NS_ERROR_NOT_AVAILABLE; goto loser; } + // even if the user has canceled, we want to remember that, to avoid repeating prompts + PRBool wantRemember = PR_FALSE; + info->GetRememberClientAuthCertificate(&wantRemember); int i; + if (!canceled) for (i = 0, node = CERT_LIST_HEAD(certList); !CERT_LIST_END(node, certList); ++i, node = CERT_LIST_NEXT(node)) { @@ -2777,6 +2832,15 @@ SECStatus nsNSS_SSLGetClientAuthData(void* arg, PRFileDesc* socket, } } + if (cars && wantRemember) { + cars->RememberDecision(hostname, + serverCert, + canceled ? 0 : cert); + } +} + + if (canceled) { rv = NS_ERROR_NOT_AVAILABLE; goto loser; } + if (cert == NULL) { goto loser; } diff --git a/security/manager/ssl/src/nsNSSIOLayer.h b/security/manager/ssl/src/nsNSSIOLayer.h index b530d98f9f89..1087e7fbe254 100644 --- a/security/manager/ssl/src/nsNSSIOLayer.h +++ b/security/manager/ssl/src/nsNSSIOLayer.h @@ -55,6 +55,7 @@ #include "nsIAssociatedContentSecurity.h" #include "nsXPIDLString.h" #include "nsNSSShutDown.h" +#include "nsIClientAuthDialogs.h" #include "nsAutoPtr.h" #include "nsNSSCertificate.h" @@ -132,6 +133,7 @@ class nsNSSSocketInfo : public nsITransportSecurityInfo, public nsIAssociatedContentSecurity, public nsISerializable, public nsIClassInfo, + public nsIClientAuthUserDecision, public nsNSSShutDownObject, public nsOnPK11LogoutCancelObject { @@ -148,6 +150,7 @@ public: NS_DECL_NSIASSOCIATEDCONTENTSECURITY NS_DECL_NSISERIALIZABLE NS_DECL_NSICLASSINFO + NS_DECL_NSICLIENTAUTHUSERDECISION nsresult SetSecurityState(PRUint32 aState); nsresult SetShortSecurityDescription(const PRUnichar *aText); @@ -220,6 +223,7 @@ protected: PRPackedBool mHasCleartextPhase; PRPackedBool mHandshakeInProgress; PRPackedBool mAllowTLSIntoleranceTimeout; + PRPackedBool mRememberClientAuthCertificate; PRIntervalTime mHandshakeStartTime; PRInt32 mPort; nsXPIDLCString mHostName; From d3f13b3bfdf4ca65d99b8933f35b00474f7882d1 Mon Sep 17 00:00:00 2001 From: Ted Mielczarek Date: Wed, 18 Jun 2008 16:31:21 -0400 Subject: [PATCH 07/66] bug 406088 - crash reporter sucks in rtl, fix for Win32. r=dcamp --- .../client/crashreporter_win.cpp | 71 +++++++++++++++++-- .../en-US/crashreporter/crashreporter.ini | 5 ++ 2 files changed, 71 insertions(+), 5 deletions(-) diff --git a/toolkit/crashreporter/client/crashreporter_win.cpp b/toolkit/crashreporter/client/crashreporter_win.cpp index eb4719db333c..653ffcddfb5b 100644 --- a/toolkit/crashreporter/client/crashreporter_win.cpp +++ b/toolkit/crashreporter/client/crashreporter_win.cpp @@ -84,6 +84,22 @@ typedef struct { wstring serverResponse; } SendThreadData; +/* + * Per http://msdn2.microsoft.com/en-us/library/ms645398(VS.85).aspx + * "The DLGTEMPLATEEX structure is not defined in any standard header file. + * The structure definition is provided here to explain the format of an + * extended template for a dialog box. +*/ +typedef struct { + WORD dlgVer; + WORD signature; + DWORD helpID; + DWORD exStyle; + // There's more to this struct, but it has weird variable-length + // members, and I only actually need to touch exStyle on an existing + // instance, so I've omitted the rest. +} DLGTEMPLATEEX; + static HANDLE gThreadHandle; static SendThreadData gSendData = { 0, }; static vector gRestartArgs; @@ -91,6 +107,7 @@ static map gQueryParameters; static wstring gCrashReporterKey(L"Software\\Mozilla\\Crash Reporter"); static wstring gURLParameter; static int gCheckboxPadding = 6; +static bool gRTLlayout = false; // When vertically resizing the dialog, these items should move down static set gAttachedBottom; @@ -272,6 +289,10 @@ typedef HRESULT (WINAPI*CloseThemeDataPtr)(HANDLE hTheme); typedef HRESULT (WINAPI*GetThemePartSizePtr)(HANDLE hTheme, HDC hdc, int iPartId, int iStateId, RECT* prc, int ts, SIZE* psz); +typedef HRESULT (WINAPI*GetThemeContentRectPtr)(HANDLE hTheme, HDC hdc, int iPartId, + int iStateId, const RECT* pRect, + RECT* pContentRect); + static void GetThemeSizes(HWND hwnd) { @@ -650,9 +671,11 @@ static LRESULT CALLBACK EditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, wchar_t* txt = (wchar_t*)GetProp(hwnd, L"PROP_GRAYTEXT"); // Get the actual edit control rect CallWindowProc(super, hwnd, EM_GETRECT, 0, (LPARAM)&r); + UINT format = DT_EDITCONTROL | DT_NOPREFIX | DT_WORDBREAK | DT_INTERNAL; + if (gRTLlayout) + format |= DT_RIGHT; if (txt) - DrawText(hdc, txt, wcslen(txt), &r, - DT_EDITCONTROL | DT_NOPREFIX | DT_WORDBREAK | DT_INTERNAL); + DrawText(hdc, txt, wcslen(txt), &r, format); EndPaint(hwnd, &ps); return 0; } @@ -806,6 +829,39 @@ static void SubmitReportChecked(HWND hwndDlg) SetDlgItemVisible(hwndDlg, IDC_PROGRESSTEXT, enabled); } +static INT_PTR DialogBoxParamMaybeRTL(UINT idd, HWND hwndParent, + DLGPROC dlgProc, LPARAM param) +{ + INT_PTR rv = 0; + if (gRTLlayout) { + // We need to toggle the WS_EX_LAYOUTRTL style flag on the dialog + // template. + HRSRC hDialogRC = FindResource(NULL, MAKEINTRESOURCE(idd), + RT_DIALOG); + HGLOBAL hDlgTemplate = LoadResource(NULL, hDialogRC); + DLGTEMPLATEEX* pDlgTemplate = (DLGTEMPLATEEX*)LockResource(hDlgTemplate); + unsigned long sizeDlg = SizeofResource(NULL, hDialogRC); + HGLOBAL hMyDlgTemplate = GlobalAlloc(GPTR, sizeDlg); + DLGTEMPLATEEX* pMyDlgTemplate = + (DLGTEMPLATEEX*)GlobalLock(hMyDlgTemplate); + memcpy(pMyDlgTemplate, pDlgTemplate, sizeDlg); + + pMyDlgTemplate->exStyle |= WS_EX_LAYOUTRTL; + + rv = DialogBoxIndirectParam(NULL, (LPCDLGTEMPLATE)pMyDlgTemplate, + hwndParent, dlgProc, param); + GlobalUnlock(hMyDlgTemplate); + GlobalFree(hMyDlgTemplate); + } + else { + rv = DialogBoxParam(NULL, MAKEINTRESOURCE(idd), hwndParent, + dlgProc, param); + } + + return rv; +} + + static BOOL CALLBACK CrashReporterDialogProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam) { @@ -991,6 +1047,7 @@ static BOOL CALLBACK CrashReporterDialogProc(HWND hwndDlg, UINT message, SendDlgItemMessage(hwndDlg, IDC_DESCRIPTIONTEXT, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&fmt); SendDlgItemMessage(hwndDlg, IDC_DESCRIPTIONTEXT, EM_SETSEL, 0, 0); + SendDlgItemMessage(hwndDlg, IDC_DESCRIPTIONTEXT, EM_SETTARGETDEVICE, (WPARAM)NULL, 0); @@ -1054,7 +1111,7 @@ static BOOL CALLBACK CrashReporterDialogProc(HWND hwndDlg, UINT message, if (HIWORD(wParam) == BN_CLICKED) { switch(LOWORD(wParam)) { case IDC_VIEWREPORTBUTTON: - DialogBoxParam(NULL, MAKEINTRESOURCE(IDD_VIEWREPORTDIALOG), hwndDlg, + DialogBoxParamMaybeRTL(IDD_VIEWREPORTDIALOG, hwndDlg, (DLGPROC)ViewReportDialogProc, 0); break; case IDC_SUBMITREPORTCHECK: @@ -1245,8 +1302,12 @@ bool UIShowCrashUI(const string& dumpFile, gRestartArgs = restartArgs; - return DialogBoxParam(NULL, MAKEINTRESOURCE(IDD_SENDDIALOG), NULL, - (DLGPROC)CrashReporterDialogProc, 0) == 1; + if (gStrings.find("isRTL") != gStrings.end() && + gStrings["isRTL"] == "yes") + gRTLlayout = true; + + return 1 == DialogBoxParamMaybeRTL(IDD_SENDDIALOG, NULL, + (DLGPROC)CrashReporterDialogProc, 0); } void UIError_impl(const string& message) diff --git a/toolkit/locales/en-US/crashreporter/crashreporter.ini b/toolkit/locales/en-US/crashreporter/crashreporter.ini index eaf80fe50f04..dee34b5bee6a 100644 --- a/toolkit/locales/en-US/crashreporter/crashreporter.ini +++ b/toolkit/locales/en-US/crashreporter/crashreporter.ini @@ -1,5 +1,10 @@ # This file is in the UTF-8 encoding [Strings] +# LOCALIZATION NOTE (isRTL): +# Leave this entry empty unless your language requires right-to-left layout, +# for example like Arabic, Hebrew, Persian. If your language needs RTL, please +# use the untranslated English word "yes" as value +isRTL= CrashReporterTitle=Crash Reporter # LOCALIZATION NOTE (CrashReporterVendorTitle): %s is replaced with the vendor name. (i.e. "Mozilla") CrashReporterVendorTitle=%s Crash Reporter From 68ce1d3fe803c5c5deb3e03bf366e0952a5430af Mon Sep 17 00:00:00 2001 From: "bcrowder@mozilla.com" Date: Wed, 18 Jun 2008 13:33:54 -0700 Subject: [PATCH 08/66] Bug 439110: xpcshell's load() just silently fails for non-existent files, r=brendan, sr=jst --- js/src/xpconnect/shell/xpcshell.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/js/src/xpconnect/shell/xpcshell.cpp b/js/src/xpconnect/shell/xpcshell.cpp index eb0e8e2f9433..c4d315a8b7cd 100644 --- a/js/src/xpconnect/shell/xpcshell.cpp +++ b/js/src/xpconnect/shell/xpcshell.cpp @@ -226,7 +226,7 @@ Load(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) JSScript *script; JSBool ok; jsval result; - FILE *file; + uint32 oldopts; for (i = 0; i < argc; i++) { str = JS_ValueToString(cx, argv[i]); @@ -234,20 +234,23 @@ Load(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) return JS_FALSE; argv[i] = STRING_TO_JSVAL(str); filename = JS_GetStringBytes(str); - file = fopen(filename, "r"); - script = JS_CompileFileHandleForPrincipals(cx, obj, filename, file, - gJSPrincipals); - if (!script) + errno = 0; + oldopts = JS_GetOptions(cx); + JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO); + script = JS_CompileFile(cx, obj, filename); + if (!script) { ok = JS_FALSE; - else { + } else { ok = !compileOnly ? JS_ExecuteScript(cx, obj, script, &result) : JS_TRUE; JS_DestroyScript(cx, script); } + JS_SetOptions(cx, oldopts); if (!ok) return JS_FALSE; } + return JS_TRUE; } From 568d8bf46ca68014adb0bf65976171c66359e6b6 Mon Sep 17 00:00:00 2001 From: Igor Bukanov Date: Wed, 18 Jun 2008 23:35:53 +0200 Subject: [PATCH 09/66] [Bug 439624] renaming decltype to declType as the former is a keyword in the next C++ standard. --- js/src/jsemit.cpp | 16 ++++++++-------- js/src/jsemit.h | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/js/src/jsemit.cpp b/js/src/jsemit.cpp index af043998f347..fd9876e2a5d2 100644 --- a/js/src/jsemit.cpp +++ b/js/src/jsemit.cpp @@ -1525,7 +1525,7 @@ js_DefineCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom, #define VAR_DECL 2 JSStmtInfo * -js_LexicalLookup(JSTreeContext *tc, JSAtom *atom, jsint *slotp, uintN decltype) +js_LexicalLookup(JSTreeContext *tc, JSAtom *atom, jsint *slotp, uintN declType) { JSStmtInfo *stmt; JSObject *obj; @@ -1536,7 +1536,7 @@ js_LexicalLookup(JSTreeContext *tc, JSAtom *atom, jsint *slotp, uintN decltype) for (stmt = tc->topScopeStmt; stmt; stmt = stmt->downScope) { if (stmt->type == STMT_WITH) { /* Ignore with statements enclosing a single let declaration. */ - if (decltype == LET_DECL) + if (declType == LET_DECL) continue; break; } @@ -1813,7 +1813,7 @@ EmitSlotIndexOp(JSContext *cx, JSOp op, uintN slot, uintN index, */ static JSBool BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn, - uintN decltype) + uintN declType) { JSTreeContext *tc; JSAtom *atom; @@ -1842,8 +1842,8 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn, */ tc = &cg->treeContext; atom = pn->pn_atom; - if (decltype != VAR_DECL && - (stmt = js_LexicalLookup(tc, atom, &slot, decltype))) { + if (declType != VAR_DECL && + (stmt = js_LexicalLookup(tc, atom, &slot, declType))) { if (stmt->type == STMT_WITH) return JS_TRUE; @@ -3243,11 +3243,11 @@ static JSBool EmitDestructuringDecl(JSContext *cx, JSCodeGenerator *cg, JSOp prologOp, JSParseNode *pn) { - JSOp decltype; + JSOp declType; JS_ASSERT(pn->pn_type == TOK_NAME); - decltype = (JSOp) ((prologOp == JSOP_NOP) ? LET_DECL : VAR_DECL); - if (!BindNameToSlot(cx, cg, pn, decltype)) + declType = (JSOp) ((prologOp == JSOP_NOP) ? LET_DECL : VAR_DECL); + if (!BindNameToSlot(cx, cg, pn, declType)) return JS_FALSE; JS_ASSERT(pn->pn_op != JSOP_ARGUMENTS); diff --git a/js/src/jsemit.h b/js/src/jsemit.h index 5a7af255bf18..4659b8b750a8 100644 --- a/js/src/jsemit.h +++ b/js/src/jsemit.h @@ -505,7 +505,7 @@ js_DefineCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom, */ extern JSStmtInfo * js_LexicalLookup(JSTreeContext *tc, JSAtom *atom, jsint *slotp, - uintN decltype); + uintN declType); /* * Emit code into cg for the tree rooted at pn. From 3a29271ed3bd7731e9836ebc244fed085ca8df84 Mon Sep 17 00:00:00 2001 From: "bcrowder@mozilla.com" Date: Wed, 18 Jun 2008 15:49:51 -0700 Subject: [PATCH 10/66] Backed out changeset f201baf7bf04 (bug 439110), was causing unit-test failures --- js/src/xpconnect/shell/xpcshell.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/js/src/xpconnect/shell/xpcshell.cpp b/js/src/xpconnect/shell/xpcshell.cpp index c4d315a8b7cd..eb0e8e2f9433 100644 --- a/js/src/xpconnect/shell/xpcshell.cpp +++ b/js/src/xpconnect/shell/xpcshell.cpp @@ -226,7 +226,7 @@ Load(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) JSScript *script; JSBool ok; jsval result; - uint32 oldopts; + FILE *file; for (i = 0; i < argc; i++) { str = JS_ValueToString(cx, argv[i]); @@ -234,23 +234,20 @@ Load(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) return JS_FALSE; argv[i] = STRING_TO_JSVAL(str); filename = JS_GetStringBytes(str); - errno = 0; - oldopts = JS_GetOptions(cx); - JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO); - script = JS_CompileFile(cx, obj, filename); - if (!script) { + file = fopen(filename, "r"); + script = JS_CompileFileHandleForPrincipals(cx, obj, filename, file, + gJSPrincipals); + if (!script) ok = JS_FALSE; - } else { + else { ok = !compileOnly ? JS_ExecuteScript(cx, obj, script, &result) : JS_TRUE; JS_DestroyScript(cx, script); } - JS_SetOptions(cx, oldopts); if (!ok) return JS_FALSE; } - return JS_TRUE; } From 86a2c30b71124f7a1af3acb1cf23d403d350f2fa Mon Sep 17 00:00:00 2001 From: Johnny Stenback Date: Wed, 18 Jun 2008 16:55:38 -0700 Subject: [PATCH 11/66] Fixing bug 433880. Stop the flash player from crashing when entering full-screen mode. Patch by mats.palmgren@bredband.net, r+sr=jst@mozilla.org --- modules/plugin/base/src/ns4xPlugin.cpp | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/modules/plugin/base/src/ns4xPlugin.cpp b/modules/plugin/base/src/ns4xPlugin.cpp index f8630990f552..8a9038815b69 100644 --- a/modules/plugin/base/src/ns4xPlugin.cpp +++ b/modules/plugin/base/src/ns4xPlugin.cpp @@ -181,18 +181,12 @@ PR_BEGIN_EXTERN_C static void* NP_CALLBACK _memalloc (uint32 size); -#ifdef OJI - static JRIEnv* NP_CALLBACK + static void* /* OJI type: JRIEnv* */ NP_CALLBACK _getJavaEnv(void); -#if 1 - - static jref NP_CALLBACK + static void* /* OJI type: jref */ NP_CALLBACK _getJavaPeer(NPP npp); -#endif -#endif /* OJI */ - PR_END_EXTERN_C #if defined(XP_MACOSX) && defined(__POWERPC__) @@ -312,13 +306,11 @@ ns4xPlugin::CheckClassInitialized(void) CALLBACKS.reloadplugins = NewNPN_ReloadPluginsProc(FP2TV(_reloadplugins)); -#ifdef OJI CALLBACKS.getJavaEnv = NewNPN_GetJavaEnvProc(FP2TV(_getJavaEnv)); CALLBACKS.getJavaPeer = NewNPN_GetJavaPeerProc(FP2TV(_getJavaPeer)); -#endif CALLBACKS.geturlnotify = NewNPN_GetURLNotifyProc(FP2TV(_geturlnotify)); @@ -2520,14 +2512,12 @@ _requestread(NPStream *pstream, NPByteRange *rangeList) } //////////////////////////////////////////////////////////////////////// -#ifdef OJI -JRIEnv* NP_CALLBACK +void* /* OJI type: JRIEnv* */ NP_CALLBACK _getJavaEnv(void) { NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("NPN_GetJavaEnv\n")); return NULL; } -#endif //////////////////////////////////////////////////////////////////////// const char * NP_CALLBACK @@ -2563,17 +2553,14 @@ _memalloc (uint32 size) return nsMemory::Alloc(size); } -#ifdef OJI //////////////////////////////////////////////////////////////////////// -jref NP_CALLBACK +void* /* OJI type: jref */ NP_CALLBACK _getJavaPeer(NPP npp) { NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("NPN_GetJavaPeer: npp=%p\n", (void*)npp)); return NULL; } -#endif /* OJI */ - void NP_CALLBACK _pushpopupsenabledstate(NPP npp, NPBool enabled) { From 10661f4ec3ffbc11977f23a88761b20910a1b025 Mon Sep 17 00:00:00 2001 From: Brendan Eich Date: Wed, 18 Jun 2008 18:50:33 -0700 Subject: [PATCH 12/66] Fix bogus js_Emit return value tests (438986, r=igor). --- js/src/js.cpp | 2 +- js/src/jsemit.cpp | 12 ++++++------ js/src/jsemit.h | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/js/src/js.cpp b/js/src/js.cpp index dddd49547a46..645fbd2d1680 100644 --- a/js/src/js.cpp +++ b/js/src/js.cpp @@ -865,7 +865,7 @@ typedef struct JSCountHeapNode JSCountHeapNode; struct JSCountHeapNode { void *thing; - uint32 kind; + int32 kind; JSCountHeapNode *next; }; diff --git a/js/src/jsemit.cpp b/js/src/jsemit.cpp index fd9876e2a5d2..daff25c9e53a 100644 --- a/js/src/jsemit.cpp +++ b/js/src/jsemit.cpp @@ -4429,7 +4429,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) * or increment i at all). */ emitIFEQ = JS_FALSE; - if (!js_Emit1(cx, cg, JSOP_FORELEM)) + if (js_Emit1(cx, cg, JSOP_FORELEM) < 0) return JS_FALSE; /* @@ -4460,7 +4460,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) JS_ASSERT(pn3->pn_op == JSOP_SETCALL); if (!js_EmitTree(cx, cg, pn3)) return JS_FALSE; - if (!js_Emit1(cx, cg, JSOP_ENUMELEM)) + if (js_Emit1(cx, cg, JSOP_ENUMELEM) < 0) return JS_FALSE; break; } @@ -4470,7 +4470,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) JS_ASSERT(pn3->pn_op == JSOP_BINDXMLNAME); if (!js_EmitTree(cx, cg, pn3)) return JS_FALSE; - if (!js_Emit1(cx, cg, JSOP_ENUMELEM)) + if (js_Emit1(cx, cg, JSOP_ENUMELEM) < 0) return JS_FALSE; break; } @@ -5915,7 +5915,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) * Push null as a placeholder for the global object, per ECMA-262 * 11.2.3 step 6. */ - if (!js_EmitTree(cx, cg, pn2) || !js_Emit1(cx, cg, JSOP_NULL) < 0) + if (!js_EmitTree(cx, cg, pn2) || js_Emit1(cx, cg, JSOP_NULL) < 0) return JS_FALSE; } @@ -6669,7 +6669,7 @@ js_GetSrcNoteOffset(jssrcnote *sn, uintN which) { /* Find the offset numbered which (i.e., skip exactly which offsets). */ JS_ASSERT(SN_TYPE(sn) != SRC_XDELTA); - JS_ASSERT(which < js_SrcNoteSpec[SN_TYPE(sn)].arity); + JS_ASSERT((intN) which < js_SrcNoteSpec[SN_TYPE(sn)].arity); for (sn++; which; sn++, which--) { if (*sn & SN_3BYTE_OFFSET_FLAG) sn += 2; @@ -6697,7 +6697,7 @@ js_SetSrcNoteOffset(JSContext *cx, JSCodeGenerator *cg, uintN index, /* Find the offset numbered which (i.e., skip exactly which offsets). */ sn = &CG_NOTES(cg)[index]; JS_ASSERT(SN_TYPE(sn) != SRC_XDELTA); - JS_ASSERT(which < js_SrcNoteSpec[SN_TYPE(sn)].arity); + JS_ASSERT((intN) which < js_SrcNoteSpec[SN_TYPE(sn)].arity); for (sn++; which; sn++, which--) { if (*sn & SN_3BYTE_OFFSET_FLAG) sn += 2; diff --git a/js/src/jsemit.h b/js/src/jsemit.h index 4659b8b750a8..b1451312d322 100644 --- a/js/src/jsemit.h +++ b/js/src/jsemit.h @@ -648,7 +648,7 @@ typedef enum JSSrcNoteType { typedef struct JSSrcNoteSpec { const char *name; /* name for disassembly/debugging output */ - uint8 arity; /* number of offset operands */ + int8 arity; /* number of offset operands */ uint8 offsetBias; /* bias of offset(s) from annotated pc */ int8 isSpanDep; /* 1 or -1 if offsets could span extended ops, 0 otherwise; sign tells span direction */ From a044334304228db7caece1fc7d74365e30609fef Mon Sep 17 00:00:00 2001 From: Alexander Surkov Date: Thu, 19 Jun 2008 11:11:46 +0800 Subject: [PATCH 13/66] =?UTF-8?q?Bug=20439077=20=E2=80=93=20Anchor=20tags?= =?UTF-8?q?=20with=20no=20attributes=20should=20not=20expose=20linked=20ac?= =?UTF-8?q?cessible=20state,=20r=3DMarcoZ?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- accessible/src/html/nsHTMLLinkAccessible.cpp | 11 ++- .../test_nsIAccessibleHyperLink.html | 75 ++++++++++++++++--- 2 files changed, 72 insertions(+), 14 deletions(-) diff --git a/accessible/src/html/nsHTMLLinkAccessible.cpp b/accessible/src/html/nsHTMLLinkAccessible.cpp index 1c9d3345c3d7..44652b8aa1db 100644 --- a/accessible/src/html/nsHTMLLinkAccessible.cpp +++ b/accessible/src/html/nsHTMLLinkAccessible.cpp @@ -102,9 +102,14 @@ nsHTMLLinkAccessible::GetState(PRUint32 *aState, PRUint32 *aExtraState) nsLinkState linkState; link->GetLinkState(linkState); - if (linkState == eLinkState_NotLink) { - // This is a named anchor, not a link with also a name attribute. bail out. - return NS_OK; + if (linkState == eLinkState_NotLink || linkState == eLinkState_Unknown) { + // This is a either named anchor (a link with also a name attribute) or + // it doesn't have any attributes. Check if 'click' event handler is + // registered, otherwise bail out. + PRBool isOnclick = nsAccUtils::HasListener(content, + NS_LITERAL_STRING("click")); + if (!isOnclick) + return NS_OK; } *aState |= nsIAccessibleStates::STATE_LINKED; diff --git a/accessible/tests/mochitest/test_nsIAccessibleHyperLink.html b/accessible/tests/mochitest/test_nsIAccessibleHyperLink.html index 5f9ffb867cbb..82176d2c6c98 100644 --- a/accessible/tests/mochitest/test_nsIAccessibleHyperLink.html +++ b/accessible/tests/mochitest/test_nsIAccessibleHyperLink.html @@ -11,6 +11,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=418368 + + +

+

+ +
+
+ + + diff --git a/toolkit/content/tests/chrome/window_keys.xul b/toolkit/content/tests/chrome/window_keys.xul new file mode 100644 index 000000000000..3413ce754c96 --- /dev/null +++ b/toolkit/content/tests/chrome/window_keys.xul @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+

+ +
+
+ + +
From a413d2079766620cb2dd86adcce0e99dd16302eb Mon Sep 17 00:00:00 2001 From: Bo Yang Date: Thu, 19 Jun 2008 10:24:30 -0400 Subject: [PATCH 17/66] Bug 439593 - GCC can't convert types automatically when cross-compiling, r=roc --- widget/src/windows/nsBidiKeyboard.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/widget/src/windows/nsBidiKeyboard.cpp b/widget/src/windows/nsBidiKeyboard.cpp index 03c7df9c72cc..6a1beafe1968 100644 --- a/widget/src/windows/nsBidiKeyboard.cpp +++ b/widget/src/windows/nsBidiKeyboard.cpp @@ -156,11 +156,11 @@ nsresult nsBidiKeyboard::SetupBidiKeyboards() while (keyboards--) { locale = buf[keyboards]; if (IsRTLLanguage(locale)) { - sprintf(mRTLKeyboard, "%.*x", KL_NAMELENGTH - 1, LANGIDFROMLCID(locale)); + sprintf(mRTLKeyboard, "%.*x", KL_NAMELENGTH - 1, LANGIDFROMLCID((DWORD)locale)); isRTLKeyboardSet = PR_TRUE; } else { - sprintf(mLTRKeyboard, "%.*x", KL_NAMELENGTH - 1, LANGIDFROMLCID(locale)); + sprintf(mLTRKeyboard, "%.*x", KL_NAMELENGTH - 1, LANGIDFROMLCID((DWORD)locale)); isLTRKeyboardSet = PR_TRUE; } } @@ -210,7 +210,7 @@ nsresult nsBidiKeyboard::SetupBidiKeyboards() PRBool nsBidiKeyboard::IsRTLLanguage(HKL aLocale) { LOCALESIGNATURE localesig; - return (::GetLocaleInfoW(PRIMARYLANGID(aLocale), + return (::GetLocaleInfoW(PRIMARYLANGID((DWORD)aLocale), LOCALE_FONTSIGNATURE, (LPWSTR)&localesig, (sizeof(localesig)/sizeof(WCHAR))) && From 6d4dc631e47e4cc56cc34e717668ac29c88c86bc Mon Sep 17 00:00:00 2001 From: Bo Yang Date: Thu, 19 Jun 2008 10:32:04 -0400 Subject: [PATCH 18/66] Bug 439593 - compile error in mingw casting HKL to DWORD, r=roc --- widget/src/windows/nsWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widget/src/windows/nsWindow.cpp b/widget/src/windows/nsWindow.cpp index f5dfda68844e..dea882b3ba5c 100644 --- a/widget/src/windows/nsWindow.cpp +++ b/widget/src/windows/nsWindow.cpp @@ -3123,7 +3123,7 @@ StringCaseInsensitiveEquals(const PRUint16* aChars1, const PRUint32 aNumChars1, return PR_FALSE; nsCaseInsensitiveStringComparator comp; - return comp(aChars1, aChars2, aNumChars1) == 0; + return comp((PRUnichar*)aChars1, (PRUnichar*)aChars2, aNumChars1) == 0; } /** From 325c013e351348dd7d4cdfc5916b2a309b37eb81 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 19 Jun 2008 09:17:08 -0700 Subject: [PATCH 19/66] Backed out changeset b0d1180627db (caused tinderbox oranges from leaks) --- content/xbl/public/nsIXBLService.h | 5 +- content/xbl/src/nsXBLService.cpp | 50 +------ content/xbl/src/nsXBLService.h | 1 - content/xbl/src/nsXBLWindowKeyHandler.cpp | 7 - content/xul/document/src/nsXULDocument.cpp | 8 -- toolkit/content/tests/chrome/Makefile.in | 2 - toolkit/content/tests/chrome/test_keys.xul | 31 ----- toolkit/content/tests/chrome/window_keys.xul | 129 ------------------- 8 files changed, 4 insertions(+), 229 deletions(-) delete mode 100644 toolkit/content/tests/chrome/test_keys.xul delete mode 100644 toolkit/content/tests/chrome/window_keys.xul diff --git a/content/xbl/public/nsIXBLService.h b/content/xbl/public/nsIXBLService.h index 0830e514124a..4da9624d004b 100644 --- a/content/xbl/public/nsIXBLService.h +++ b/content/xbl/public/nsIXBLService.h @@ -58,8 +58,8 @@ class nsIAtom; class nsIPrincipal; #define NS_IXBLSERVICE_IID \ -{ 0x8d3b37f5, 0xde7e, 0x4595, \ - { 0xb8, 0x56, 0xf7, 0x11, 0xe8, 0xe7, 0xb5, 0x59 } } +{ 0x98b28f4e, 0x698f, 0x4f77, \ + { 0xa8, 0x9e, 0x65, 0xf5, 0xd0, 0xde, 0x6a, 0xbf } } class nsIXBLService : public nsISupports { @@ -90,7 +90,6 @@ public: // Hooks up the global key event handlers to the document root. NS_IMETHOD AttachGlobalKeyHandler(nsPIDOMEventTarget* aTarget)=0; - NS_IMETHOD DetachGlobalKeyHandler(nsPIDOMEventTarget* aTarget)=0; }; diff --git a/content/xbl/src/nsXBLService.cpp b/content/xbl/src/nsXBLService.cpp index b5c2e280fc31..6a863158fac8 100644 --- a/content/xbl/src/nsXBLService.cpp +++ b/content/xbl/src/nsXBLService.cpp @@ -673,10 +673,6 @@ nsXBLService::AttachGlobalKeyHandler(nsPIDOMEventTarget* aTarget) if (!piTarget) return NS_ERROR_FAILURE; - - // the listener already exists, so skip this - if (contentNode && contentNode->GetProperty(nsGkAtoms::listener)) - return NS_OK; nsCOMPtr elt(do_QueryInterface(contentNode)); @@ -698,50 +694,8 @@ nsXBLService::AttachGlobalKeyHandler(nsPIDOMEventTarget* aTarget) target->AddGroupedEventListener(NS_LITERAL_STRING("keypress"), handler, PR_FALSE, systemGroup); - // the reference added in NS_NewXBLWindowKeyHandler will be taken by the property - if (contentNode) - return contentNode->SetProperty(nsGkAtoms::listener, handler, - nsPropertyTable::SupportsDtorFunc, PR_TRUE); - return NS_OK; -} - -// -// DetachGlobalKeyHandler -// -// Removes a key handler added by DeatchGlobalKeyHandler. -// -NS_IMETHODIMP -nsXBLService::DetachGlobalKeyHandler(nsPIDOMEventTarget* aTarget) -{ - nsCOMPtr piTarget = aTarget; - nsCOMPtr contentNode(do_QueryInterface(aTarget)); - if (!contentNode) // detaching is only supported for content nodes - return NS_ERROR_FAILURE; - - // Only attach if we're really in a document - nsCOMPtr doc = contentNode->GetCurrentDoc(); - if (doc) - piTarget = do_QueryInterface(doc); - if (!piTarget) - return NS_ERROR_FAILURE; - - nsIDOMEventListener* handler = - static_cast(contentNode->GetProperty(nsGkAtoms::listener)); - if (!handler) - return NS_ERROR_FAILURE; - - nsCOMPtr systemGroup; - piTarget->GetSystemEventGroup(getter_AddRefs(systemGroup)); - nsCOMPtr target = do_QueryInterface(piTarget); - - target->RemoveGroupedEventListener(NS_LITERAL_STRING("keydown"), handler, - PR_FALSE, systemGroup); - target->RemoveGroupedEventListener(NS_LITERAL_STRING("keyup"), handler, - PR_FALSE, systemGroup); - target->RemoveGroupedEventListener(NS_LITERAL_STRING("keypress"), handler, - PR_FALSE, systemGroup); - - contentNode->DeleteProperty(nsGkAtoms::listener); + // Release. Do this so that only the event receiver holds onto the key handler. + NS_RELEASE(handler); return NS_OK; } diff --git a/content/xbl/src/nsXBLService.h b/content/xbl/src/nsXBLService.h index 62ed170adf58..b6bb9a2ebdc4 100644 --- a/content/xbl/src/nsXBLService.h +++ b/content/xbl/src/nsXBLService.h @@ -88,7 +88,6 @@ class nsXBLService : public nsIXBLService, // Used by XUL key bindings and for window XBL. NS_IMETHOD AttachGlobalKeyHandler(nsPIDOMEventTarget* aTarget); - NS_IMETHOD DetachGlobalKeyHandler(nsPIDOMEventTarget* aTarget); NS_DECL_NSIOBSERVER diff --git a/content/xbl/src/nsXBLWindowKeyHandler.cpp b/content/xbl/src/nsXBLWindowKeyHandler.cpp index c501904e77cd..265f519a13d7 100644 --- a/content/xbl/src/nsXBLWindowKeyHandler.cpp +++ b/content/xbl/src/nsXBLWindowKeyHandler.cpp @@ -356,13 +356,6 @@ nsXBLWindowKeyHandler::WalkHandlers(nsIDOMEvent* aKeyEvent, nsIAtom* aEventType) } } - nsCOMPtr content = do_QueryInterface(el); - // skip keysets that are disabled - if (content && content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::disabled, - nsGkAtoms::_true, eCaseMatters)) { - return NS_OK; - } - WalkHandlersInternal(aKeyEvent, aEventType, mHandler); nsINativeKeyBindings *nativeBindings; diff --git a/content/xul/document/src/nsXULDocument.cpp b/content/xul/document/src/nsXULDocument.cpp index e87721dc31d1..b79d94b90db5 100644 --- a/content/xul/document/src/nsXULDocument.cpp +++ b/content/xul/document/src/nsXULDocument.cpp @@ -1689,14 +1689,6 @@ nsXULDocument::RemoveSubtreeFromDocument(nsIContent* aElement) // document. nsresult rv; - if (aElement->NodeInfo()->Equals(nsGkAtoms::keyset, kNameSpaceID_XUL)) { - nsCOMPtr xblService(do_GetService("@mozilla.org/xbl;1")); - if (xblService) { - nsCOMPtr piTarget(do_QueryInterface(aElement)); - xblService->DetachGlobalKeyHandler(piTarget); - } - } - // 1. Remove any children from the document. PRUint32 count = aElement->GetChildCount(); diff --git a/toolkit/content/tests/chrome/Makefile.in b/toolkit/content/tests/chrome/Makefile.in index 43d258ed0a21..c3df3388a48d 100644 --- a/toolkit/content/tests/chrome/Makefile.in +++ b/toolkit/content/tests/chrome/Makefile.in @@ -64,8 +64,6 @@ _TEST_FILES = bug288254_window.xul \ frame_popup_anchor.xul \ test_preferences.xul \ window_preferences.xul \ - test_keys.xul \ - window_keys.xul \ $(NULL) ifeq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT))) diff --git a/toolkit/content/tests/chrome/test_keys.xul b/toolkit/content/tests/chrome/test_keys.xul deleted file mode 100644 index 96758a9be59f..000000000000 --- a/toolkit/content/tests/chrome/test_keys.xul +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - -

-

- -
-
- - -
diff --git a/toolkit/content/tests/chrome/window_keys.xul b/toolkit/content/tests/chrome/window_keys.xul deleted file mode 100644 index 3413ce754c96..000000000000 --- a/toolkit/content/tests/chrome/window_keys.xul +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

-

- -
-
- - -
From befb38e6532706459a57f31ad654136287f791dc Mon Sep 17 00:00:00 2001 From: Ted Mielczarek Date: Thu, 19 Jun 2008 14:04:57 -0400 Subject: [PATCH 20/66] bug 406088 - crash reporter sucks in rtl. fix for linux. r=dcamp --- toolkit/crashreporter/client/crashreporter_linux.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/toolkit/crashreporter/client/crashreporter_linux.cpp b/toolkit/crashreporter/client/crashreporter_linux.cpp index 681832a3f7de..d383d93d7904 100644 --- a/toolkit/crashreporter/client/crashreporter_linux.cpp +++ b/toolkit/crashreporter/client/crashreporter_linux.cpp @@ -218,7 +218,7 @@ static void LoadProxyinfo() g_free(httpproxy); if(gconf_client_get_bool(conf, HTTP_PROXY_DIR "/use_authentication", NULL)) { - gchar *user, *password, *auth; + gchar *user, *password, *auth = NULL; user = gconf_client_get_string(conf, HTTP_PROXY_DIR "/authentication_user", @@ -591,6 +591,11 @@ bool UIInit() if (gtk_init_check(&gArgc, &gArgv)) { gInitialized = true; + + if (gStrings.find("isRTL") != gStrings.end() && + gStrings["isRTL"] == "yes") + gtk_widget_set_default_direction(GTK_TEXT_DIR_RTL); + TryInitGnome(); return true; } From 9b4b7693679c73d7e8eb3d2e7d283ccaff989585 Mon Sep 17 00:00:00 2001 From: Bo Yang Date: Thu, 19 Jun 2008 14:32:52 -0400 Subject: [PATCH 21/66] Bug 439603 - scope a case statement to avoid an unusual error during cross-compiling, r=roc --- widget/src/windows/nsNativeThemeWin.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/widget/src/windows/nsNativeThemeWin.cpp b/widget/src/windows/nsNativeThemeWin.cpp index cad94d157597..45a36dbadb18 100644 --- a/widget/src/windows/nsNativeThemeWin.cpp +++ b/widget/src/windows/nsNativeThemeWin.cpp @@ -1597,8 +1597,10 @@ nsNativeThemeWin::GetWidgetPadding(nsIDeviceContext* aContext, case NS_THEME_MENUITEMTEXT: // There seem to be exactly 4 pixels from the edge // of the gutter to the text: 2px margin (CSS) + 2px padding (here) - SIZE size(GetGutterSize(theme, NULL)); - left = size.cx + 2; + { + SIZE size(GetGutterSize(theme, NULL)); + left = size.cx + 2; + } break; case NS_THEME_MENUSEPARATOR: { From 7444e92825da396018370a595d5407e6dcd29f41 Mon Sep 17 00:00:00 2001 From: Brendan Eich Date: Thu, 19 Jun 2008 12:51:57 -0700 Subject: [PATCH 22/66] Fix old assignment expression rval mutation via getter design, optimize setprop;pop and similar cliches (312354, r=igor). --- js/src/jsinterp.cpp | 54 +++++++++++++++++++++++++++++++++------------ js/src/jsopcode.tbl | 1 - 2 files changed, 40 insertions(+), 15 deletions(-) diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 310937d89d7a..3c58cabee4b7 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -3328,6 +3328,36 @@ interrupt: # define ASSERT_VALID_PROPERTY_CACHE_HIT(pcoff,obj,pobj,entry) ((void) 0) #endif +/* + * Skip the JSOP_POP typically found after a JSOP_SET* opcode, where oplen is + * the constant length of the SET opcode sequence, and spdec is the constant + * by which to decrease the stack pointer to pop all of the SET op's operands. + * + * NB: unlike macros that could conceivably be replaced by functions (ignoring + * goto error), where a call should not have to be braced in order to expand + * correctly (e.g., in if (cond) FOO(); else BAR()), these three macros lack + * JS_{BEGIN,END}_MACRO brackets. They are also indented so as to align with + * nearby opcode code. + */ +#define SKIP_POP_AFTER_SET(oplen,spdec) \ + if (regs.pc[oplen] == JSOP_POP) { \ + regs.sp -= spdec; \ + regs.pc += oplen + JSOP_POP_LENGTH; \ + op = (JSOp) *regs.pc; \ + DO_OP(); \ + } + +#define END_SET_CASE(OP) \ + SKIP_POP_AFTER_SET(OP##_LENGTH, 1); \ + END_CASE(OP) + +#define END_SET_CASE_STORE_RVAL(OP,spdec) \ + SKIP_POP_AFTER_SET(OP##_LENGTH, spdec); \ + rval = FETCH_OPND(-1); \ + regs.sp -= (spdec) - 1; \ + STORE_OPND(-1, rval); \ + END_CASE(OP) + BEGIN_CASE(JSOP_SETCONST) LOAD_ATOM(0); obj = fp->varobj; @@ -3339,8 +3369,7 @@ interrupt: NULL)) { goto error; } - STORE_OPND(-1, rval); - END_CASE(JSOP_SETCONST) + END_SET_CASE(JSOP_SETCONST); #if JS_HAS_DESTRUCTURING BEGIN_CASE(JSOP_ENUMCONSTELEM) @@ -4024,6 +4053,8 @@ interrupt: rval = *vp; if (JS_LIKELY(CAN_DO_FAST_INC_DEC(rval))) { *vp = rval + incr; + JS_ASSERT(JSOP_INCARG_LENGTH == js_CodeSpec[op].length); + SKIP_POP_AFTER_SET(JSOP_INCARG_LENGTH, 0); PUSH_OPND(rval + incr2); } else { PUSH_OPND(rval); @@ -4521,10 +4552,7 @@ interrupt: goto error; } } while (0); - - regs.sp--; - STORE_OPND(-1, rval); - END_CASE(JSOP_SETPROP) + END_SET_CASE_STORE_RVAL(JSOP_SETPROP, 2); BEGIN_CASE(JSOP_GETELEM) /* Open-coded ELEMENT_OP optimized for strings and dense arrays. */ @@ -4614,9 +4642,7 @@ interrupt: if (!OBJ_SET_PROPERTY(cx, obj, id, &rval)) goto error; end_setelem: - regs.sp -= 2; - STORE_OPND(-1, rval); - END_CASE(JSOP_SETELEM) + END_SET_CASE_STORE_RVAL(JSOP_SETELEM, 3) BEGIN_CASE(JSOP_ENUMELEM) /* Funky: the value to set is under the [obj, id] pair. */ @@ -5447,7 +5473,7 @@ interrupt: vp = &fp->argv[slot]; GC_POKE(cx, *vp); *vp = FETCH_OPND(-1); - END_CASE(JSOP_SETARG) + END_SET_CASE(JSOP_SETARG) BEGIN_CASE(JSOP_GETVAR) BEGIN_CASE(JSOP_CALLVAR) @@ -5466,7 +5492,7 @@ interrupt: vp = &fp->vars[slot]; GC_POKE(cx, *vp); *vp = FETCH_OPND(-1); - END_CASE(JSOP_SETVAR) + END_SET_CASE(JSOP_SETVAR) BEGIN_CASE(JSOP_GETGVAR) BEGIN_CASE(JSOP_CALLGVAR) @@ -5503,14 +5529,13 @@ interrupt: id = ATOM_TO_JSID(atom); if (!OBJ_SET_PROPERTY(cx, obj, id, &rval)) goto error; - STORE_OPND(-1, rval); } else { slot = JSVAL_TO_INT(lval); JS_LOCK_OBJ(cx, obj); LOCKED_OBJ_WRITE_BARRIER(cx, obj, slot, rval); JS_UNLOCK_OBJ(cx, obj); } - END_CASE(JSOP_SETGVAR) + END_SET_CASE(JSOP_SETGVAR) BEGIN_CASE(JSOP_DEFCONST) BEGIN_CASE(JSOP_DEFVAR) @@ -6386,6 +6411,7 @@ interrupt: FETCH_ELEMENT_ID(obj, -2, id); if (!OBJ_SET_PROPERTY(cx, obj, id, &rval)) goto error; + rval = FETCH_OPND(-1); regs.sp -= 2; STORE_OPND(-1, rval); END_CASE(JSOP_SETXMLNAME) @@ -6631,7 +6657,7 @@ interrupt: vp = &fp->spbase[slot]; GC_POKE(cx, *vp); *vp = FETCH_OPND(-1); - END_CASE(JSOP_SETLOCAL) + END_SET_CASE(JSOP_SETLOCAL) BEGIN_CASE(JSOP_ENDITER) /* diff --git a/js/src/jsopcode.tbl b/js/src/jsopcode.tbl index 8aa08fe0269f..7806e08e018f 100644 --- a/js/src/jsopcode.tbl +++ b/js/src/jsopcode.tbl @@ -528,4 +528,3 @@ OPDEF(JSOP_LENGTH, 229, "length", NULL, 1, 1, 1, 18, JOF_BYTE|J */ OPDEF(JSOP_NEWARRAY, 230,"newarray", NULL, 4, -1, 1, 19, JOF_UINT24) OPDEF(JSOP_HOLE, 231,"hole", NULL, 1, 0, 1, 0, JOF_BYTE) - From 22cad4220c038c957f9c07b123b5a12097f1d97b Mon Sep 17 00:00:00 2001 From: Mats Palmgren Date: Thu, 19 Jun 2008 23:39:46 +0200 Subject: [PATCH 23/66] URI.path one character short after redirect involving fragment. b=438288 r+sr=cbiesinger --- netwerk/base/src/nsStandardURL.cpp | 1 + netwerk/test/unit/test_standardurl.js | 61 +++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/netwerk/base/src/nsStandardURL.cpp b/netwerk/base/src/nsStandardURL.cpp index 9499cb3bad5b..cd9d7bb24f0d 100644 --- a/netwerk/base/src/nsStandardURL.cpp +++ b/netwerk/base/src/nsStandardURL.cpp @@ -2207,6 +2207,7 @@ nsStandardURL::SetRef(const nsACString &input) if (mRef.mLen < 0) { mSpec.Append('#'); + ++mPath.mLen; // Include the # in the path. mRef.mPos = mSpec.Length(); mRef.mLen = 0; } diff --git a/netwerk/test/unit/test_standardurl.js b/netwerk/test/unit/test_standardurl.js index 36fcce688b7a..5d0ae21f06c4 100644 --- a/netwerk/test/unit/test_standardurl.js +++ b/netwerk/test/unit/test_standardurl.js @@ -103,8 +103,69 @@ function test_setQuery() } +function test_setRef() +{ + var tests = + [ + ["http://example.com", "", "http://example.com/"], + ["http://example.com:80", "", "http://example.com:80/"], + ["http://example.com:80/", "", "http://example.com:80/"], + ["http://example.com/", "", "http://example.com/"], + ["http://example.com/a", "", "http://example.com/a"], + ["http://example.com:80/a", "", "http://example.com:80/a"], + + ["http://example.com", "x", "http://example.com/#x"], + ["http://example.com:80", "x", "http://example.com:80/#x"], + ["http://example.com:80/", "x", "http://example.com:80/#x"], + ["http://example.com/", "x", "http://example.com/#x"], + ["http://example.com/a", "x", "http://example.com/a#x"], + ["http://example.com:80/a", "x", "http://example.com:80/a#x"], + + ["http://example.com", "xx", "http://example.com/#xx"], + ["http://example.com:80", "xx", "http://example.com:80/#xx"], + ["http://example.com:80/", "xx", "http://example.com:80/#xx"], + ["http://example.com/", "xx", "http://example.com/#xx"], + ["http://example.com/a", "xx", "http://example.com/a#xx"], + ["http://example.com:80/a", "xx", "http://example.com:80/a#xx"], + + ["http://example.com", "xxxxxxxxxxxxxx", "http://example.com/#xxxxxxxxxxxxxx"], + ["http://example.com:80", "xxxxxxxxxxxxxx", "http://example.com:80/#xxxxxxxxxxxxxx"], + ["http://example.com:80/", "xxxxxxxxxxxxxx", "http://example.com:80/#xxxxxxxxxxxxxx"], + ["http://example.com/", "xxxxxxxxxxxxxx", "http://example.com/#xxxxxxxxxxxxxx"], + ["http://example.com/a", "xxxxxxxxxxxxxx", "http://example.com/a#xxxxxxxxxxxxxx"], + ["http://example.com:80/a", "xxxxxxxxxxxxxx", "http://example.com:80/a#xxxxxxxxxxxxxx"], + ]; + + for each (var [before, ref, result] in tests) + { + /* Test1: starting with empty ref */ + var a = stringToURL(before); + a.ref = ref; + var b = stringToURL(result); + + do_check_eq(a.spec, b.spec); + do_check_eq(ref, b.ref); + symmetricEquality(true, a, b); + + /* Test2: starting with non-empty */ + a.ref = "yyyy"; + var c = stringToURL(before); + c.ref = "yyyy"; + symmetricEquality(true, a, c); + + /* Test3: reset the ref */ + a.ref = ""; + symmetricEquality(true, a, stringToURL(before)); + + /* Test4: verify again after reset */ + a.ref = ref; + symmetricEquality(true, a, b); + } +} + function run_test() { test_setEmptyPath(); test_setQuery(); + test_setRef(); } From dbec8fafc513ce5e038ebd580ab220a5ae7ca71c Mon Sep 17 00:00:00 2001 From: Mats Palmgren Date: Fri, 20 Jun 2008 02:45:05 +0200 Subject: [PATCH 24/66] Make the test work also with desktop theme where background color for text widgets is not white. b=435048 r=karlt --- layout/reftests/forms/input-text-size-2-ref.html | 4 +++- layout/reftests/forms/input-text-size-2.html | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/layout/reftests/forms/input-text-size-2-ref.html b/layout/reftests/forms/input-text-size-2-ref.html index 3a97cb162eb2..94512260b75b 100644 --- a/layout/reftests/forms/input-text-size-2-ref.html +++ b/layout/reftests/forms/input-text-size-2-ref.html @@ -1,3 +1,5 @@ - + + + diff --git a/layout/reftests/forms/input-text-size-2.html b/layout/reftests/forms/input-text-size-2.html index 2d725e93e88b..7353238f76d8 100644 --- a/layout/reftests/forms/input-text-size-2.html +++ b/layout/reftests/forms/input-text-size-2.html @@ -1,3 +1,5 @@ - + + + From f59c177254e8703e2af5d434f5ab4ad7ccbfbefd Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Thu, 19 Jun 2008 18:44:10 -0700 Subject: [PATCH 25/66] Bug 424399: Remove unused directory "js/src/fdlibm". r+a=shaver --- js/src/SpiderMonkey.rsp | 1 - js/src/build.mk | 1 - js/src/fdlibm/Makefile.in | 127 --- js/src/fdlibm/Makefile.ref | 192 ----- js/src/fdlibm/e_acos.c | 147 ---- js/src/fdlibm/e_acosh.c | 105 --- js/src/fdlibm/e_asin.c | 156 ---- js/src/fdlibm/e_atan2.c | 165 ---- js/src/fdlibm/e_atanh.c | 110 --- js/src/fdlibm/e_cosh.c | 133 --- js/src/fdlibm/e_exp.c | 202 ----- js/src/fdlibm/e_fmod.c | 184 ----- js/src/fdlibm/e_gamma.c | 71 -- js/src/fdlibm/e_gamma_r.c | 70 -- js/src/fdlibm/e_hypot.c | 173 ---- js/src/fdlibm/e_j0.c | 524 ------------ js/src/fdlibm/e_j1.c | 523 ------------ js/src/fdlibm/e_jn.c | 315 ------- js/src/fdlibm/e_lgamma.c | 71 -- js/src/fdlibm/e_lgamma_r.c | 347 -------- js/src/fdlibm/e_log.c | 184 ----- js/src/fdlibm/e_log10.c | 134 --- js/src/fdlibm/e_pow.c | 386 --------- js/src/fdlibm/e_rem_pio2.c | 222 ----- js/src/fdlibm/e_remainder.c | 120 --- js/src/fdlibm/e_scalb.c | 89 -- js/src/fdlibm/e_sinh.c | 122 --- js/src/fdlibm/e_sqrt.c | 497 ----------- js/src/fdlibm/fdlibm.h | 273 ------- js/src/fdlibm/fdlibm.mak | 1453 --------------------------------- js/src/fdlibm/fdlibm.mdp | Bin 42143 -> 0 bytes js/src/fdlibm/k_cos.c | 135 --- js/src/fdlibm/k_rem_pio2.c | 354 -------- js/src/fdlibm/k_sin.c | 114 --- js/src/fdlibm/k_standard.c | 785 ------------------ js/src/fdlibm/k_tan.c | 170 ---- js/src/fdlibm/s_asinh.c | 101 --- js/src/fdlibm/s_atan.c | 175 ---- js/src/fdlibm/s_cbrt.c | 133 --- js/src/fdlibm/s_ceil.c | 120 --- js/src/fdlibm/s_copysign.c | 72 -- js/src/fdlibm/s_cos.c | 118 --- js/src/fdlibm/s_erf.c | 356 -------- js/src/fdlibm/s_expm1.c | 267 ------ js/src/fdlibm/s_fabs.c | 70 -- js/src/fdlibm/s_finite.c | 71 -- js/src/fdlibm/s_floor.c | 121 --- js/src/fdlibm/s_frexp.c | 99 --- js/src/fdlibm/s_ilogb.c | 85 -- js/src/fdlibm/s_isnan.c | 74 -- js/src/fdlibm/s_ldexp.c | 66 -- js/src/fdlibm/s_lib_version.c | 73 -- js/src/fdlibm/s_log1p.c | 211 ----- js/src/fdlibm/s_logb.c | 79 -- js/src/fdlibm/s_matherr.c | 64 -- js/src/fdlibm/s_modf.c | 132 --- js/src/fdlibm/s_nextafter.c | 124 --- js/src/fdlibm/s_rint.c | 131 --- js/src/fdlibm/s_scalbn.c | 107 --- js/src/fdlibm/s_signgam.c | 40 - js/src/fdlibm/s_significand.c | 68 -- js/src/fdlibm/s_sin.c | 118 --- js/src/fdlibm/s_tan.c | 112 --- js/src/fdlibm/s_tanh.c | 122 --- js/src/fdlibm/w_acos.c | 78 -- js/src/fdlibm/w_acosh.c | 78 -- js/src/fdlibm/w_asin.c | 80 -- js/src/fdlibm/w_atan2.c | 79 -- js/src/fdlibm/w_atanh.c | 81 -- js/src/fdlibm/w_cosh.c | 77 -- js/src/fdlibm/w_exp.c | 88 -- js/src/fdlibm/w_fmod.c | 78 -- js/src/fdlibm/w_gamma.c | 85 -- js/src/fdlibm/w_gamma_r.c | 81 -- js/src/fdlibm/w_hypot.c | 78 -- js/src/fdlibm/w_j0.c | 105 --- js/src/fdlibm/w_j1.c | 106 --- js/src/fdlibm/w_jn.c | 128 --- js/src/fdlibm/w_lgamma.c | 85 -- js/src/fdlibm/w_lgamma_r.c | 81 -- js/src/fdlibm/w_log.c | 78 -- js/src/fdlibm/w_log10.c | 81 -- js/src/fdlibm/w_pow.c | 99 --- js/src/fdlibm/w_remainder.c | 77 -- js/src/fdlibm/w_scalb.c | 95 --- js/src/fdlibm/w_sinh.c | 77 -- js/src/fdlibm/w_sqrt.c | 77 -- js/src/jslibmath.h | 180 ---- js/src/jsmath.cpp | 4 +- toolkit/toolkit-makefiles.sh | 1 - 90 files changed, 1 insertion(+), 14120 deletions(-) delete mode 100644 js/src/fdlibm/Makefile.in delete mode 100644 js/src/fdlibm/Makefile.ref delete mode 100644 js/src/fdlibm/e_acos.c delete mode 100644 js/src/fdlibm/e_acosh.c delete mode 100644 js/src/fdlibm/e_asin.c delete mode 100644 js/src/fdlibm/e_atan2.c delete mode 100644 js/src/fdlibm/e_atanh.c delete mode 100644 js/src/fdlibm/e_cosh.c delete mode 100644 js/src/fdlibm/e_exp.c delete mode 100644 js/src/fdlibm/e_fmod.c delete mode 100644 js/src/fdlibm/e_gamma.c delete mode 100644 js/src/fdlibm/e_gamma_r.c delete mode 100644 js/src/fdlibm/e_hypot.c delete mode 100644 js/src/fdlibm/e_j0.c delete mode 100644 js/src/fdlibm/e_j1.c delete mode 100644 js/src/fdlibm/e_jn.c delete mode 100644 js/src/fdlibm/e_lgamma.c delete mode 100644 js/src/fdlibm/e_lgamma_r.c delete mode 100644 js/src/fdlibm/e_log.c delete mode 100644 js/src/fdlibm/e_log10.c delete mode 100644 js/src/fdlibm/e_pow.c delete mode 100644 js/src/fdlibm/e_rem_pio2.c delete mode 100644 js/src/fdlibm/e_remainder.c delete mode 100644 js/src/fdlibm/e_scalb.c delete mode 100644 js/src/fdlibm/e_sinh.c delete mode 100644 js/src/fdlibm/e_sqrt.c delete mode 100644 js/src/fdlibm/fdlibm.h delete mode 100644 js/src/fdlibm/fdlibm.mak delete mode 100644 js/src/fdlibm/fdlibm.mdp delete mode 100644 js/src/fdlibm/k_cos.c delete mode 100644 js/src/fdlibm/k_rem_pio2.c delete mode 100644 js/src/fdlibm/k_sin.c delete mode 100644 js/src/fdlibm/k_standard.c delete mode 100644 js/src/fdlibm/k_tan.c delete mode 100644 js/src/fdlibm/s_asinh.c delete mode 100644 js/src/fdlibm/s_atan.c delete mode 100644 js/src/fdlibm/s_cbrt.c delete mode 100644 js/src/fdlibm/s_ceil.c delete mode 100644 js/src/fdlibm/s_copysign.c delete mode 100644 js/src/fdlibm/s_cos.c delete mode 100644 js/src/fdlibm/s_erf.c delete mode 100644 js/src/fdlibm/s_expm1.c delete mode 100644 js/src/fdlibm/s_fabs.c delete mode 100644 js/src/fdlibm/s_finite.c delete mode 100644 js/src/fdlibm/s_floor.c delete mode 100644 js/src/fdlibm/s_frexp.c delete mode 100644 js/src/fdlibm/s_ilogb.c delete mode 100644 js/src/fdlibm/s_isnan.c delete mode 100644 js/src/fdlibm/s_ldexp.c delete mode 100644 js/src/fdlibm/s_lib_version.c delete mode 100644 js/src/fdlibm/s_log1p.c delete mode 100644 js/src/fdlibm/s_logb.c delete mode 100644 js/src/fdlibm/s_matherr.c delete mode 100644 js/src/fdlibm/s_modf.c delete mode 100644 js/src/fdlibm/s_nextafter.c delete mode 100644 js/src/fdlibm/s_rint.c delete mode 100644 js/src/fdlibm/s_scalbn.c delete mode 100644 js/src/fdlibm/s_signgam.c delete mode 100644 js/src/fdlibm/s_significand.c delete mode 100644 js/src/fdlibm/s_sin.c delete mode 100644 js/src/fdlibm/s_tan.c delete mode 100644 js/src/fdlibm/s_tanh.c delete mode 100644 js/src/fdlibm/w_acos.c delete mode 100644 js/src/fdlibm/w_acosh.c delete mode 100644 js/src/fdlibm/w_asin.c delete mode 100644 js/src/fdlibm/w_atan2.c delete mode 100644 js/src/fdlibm/w_atanh.c delete mode 100644 js/src/fdlibm/w_cosh.c delete mode 100644 js/src/fdlibm/w_exp.c delete mode 100644 js/src/fdlibm/w_fmod.c delete mode 100644 js/src/fdlibm/w_gamma.c delete mode 100644 js/src/fdlibm/w_gamma_r.c delete mode 100644 js/src/fdlibm/w_hypot.c delete mode 100644 js/src/fdlibm/w_j0.c delete mode 100644 js/src/fdlibm/w_j1.c delete mode 100644 js/src/fdlibm/w_jn.c delete mode 100644 js/src/fdlibm/w_lgamma.c delete mode 100644 js/src/fdlibm/w_lgamma_r.c delete mode 100644 js/src/fdlibm/w_log.c delete mode 100644 js/src/fdlibm/w_log10.c delete mode 100644 js/src/fdlibm/w_pow.c delete mode 100644 js/src/fdlibm/w_remainder.c delete mode 100644 js/src/fdlibm/w_scalb.c delete mode 100644 js/src/fdlibm/w_sinh.c delete mode 100644 js/src/fdlibm/w_sqrt.c diff --git a/js/src/SpiderMonkey.rsp b/js/src/SpiderMonkey.rsp index 8025c6cd6271..fc162d967de5 100644 --- a/js/src/SpiderMonkey.rsp +++ b/js/src/SpiderMonkey.rsp @@ -1,6 +1,5 @@ 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/* diff --git a/js/src/build.mk b/js/src/build.mk index 693c3413aecf..eac24716885b 100644 --- a/js/src/build.mk +++ b/js/src/build.mk @@ -38,6 +38,5 @@ TIERS += js tier_js_dirs += \ - js/src/fdlibm \ js/src \ $(NULL) diff --git a/js/src/fdlibm/Makefile.in b/js/src/fdlibm/Makefile.in deleted file mode 100644 index fdec7b7e8e6c..000000000000 --- a/js/src/fdlibm/Makefile.in +++ /dev/null @@ -1,127 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# 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, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either of the GNU General Public License Version 2 or later (the "GPL"), -# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -DEPTH = ../../.. -topsrcdir = @top_srcdir@ -srcdir = @srcdir@ -VPATH = @srcdir@ - -include $(DEPTH)/config/autoconf.mk - -MODULE = js -LIBRARY_NAME = fdm - -CSRCS = \ - e_acos.c \ - e_asin.c \ - e_atan2.c \ - e_exp.c \ - e_fmod.c \ - e_log.c \ - e_pow.c \ - e_rem_pio2.c \ - s_scalbn.c \ - e_sqrt.c \ - k_cos.c \ - k_sin.c \ - k_rem_pio2.c \ - k_tan.c \ - s_atan.c \ - s_ceil.c \ - s_copysign.c \ - s_cos.c \ - s_fabs.c \ - s_finite.c \ - s_floor.c \ - s_isnan.c \ - s_lib_version.c \ - s_sin.c \ - s_tan.c \ - w_acos.c \ - w_asin.c \ - w_atan2.c \ - w_exp.c \ - w_fmod.c \ - w_log.c \ - w_pow.c \ - w_sqrt.c \ - $(NULL) - -EXPORTS = fdlibm.h - -# we need to force a static lib for the linking that js/src/Makefile.in wants -# to do, and we don't really need a shared library ever, so: -FORCE_STATIC_LIB = 1 -FORCE_USE_PIC = 1 - -include $(topsrcdir)/config/rules.mk - -# -# Default IEEE libm -# -CFLAGS += -D_IEEE_LIBM - -ifeq ($(OS_ARCH),Linux) -LDFLAGS += -ldl -endif - -ifeq ($(OS_ARCH),OSF1) -LDFLAGS += -lc_r -endif - -ifeq ($(OS_ARCH),SunOS) -LDFLAGS += -lposix4 -ldl -lnsl -lsocket -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 -endif - diff --git a/js/src/fdlibm/Makefile.ref b/js/src/fdlibm/Makefile.ref deleted file mode 100644 index de378025c708..000000000000 --- a/js/src/fdlibm/Makefile.ref +++ /dev/null @@ -1,192 +0,0 @@ -# -*- Mode: makefile -*- -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# 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, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Sun Microsystems, Inc. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either of the GNU General Public License Version 2 or later (the "GPL"), -# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -# -# @(#)Makefile 1.4 95/01/18 -# -# ==================================================== -# Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. -# -# Developed at SunSoft, a Sun Microsystems, Inc. business. -# Permission to use, copy, modify, and distribute this -# software is freely granted, provided that this notice -# is preserved. -# ==================================================== -# -# - -# -# There are two options in making libm at fdlibm compile time: -# _IEEE_LIBM --- IEEE libm; smaller, and somewhat faster -# _MULTI_LIBM --- Support multi-standard at runtime by -# imposing wrapper functions defined in -# fdlibm.h: -# _IEEE_MODE -- IEEE -# _XOPEN_MODE -- X/OPEN -# _POSIX_MODE -- POSIX/ANSI -# _SVID3_MODE -- SVID -# -# Here is how to set up CFLAGS to create the desired libm at -# compile time: -# -# CFLAGS = -D_IEEE_LIBM ... IEEE libm (recommended) -# CFLAGS = -D_SVID3_MODE ... Multi-standard supported -# libm with SVID as the -# default standard -# CFLAGS = -D_XOPEN_MODE ... Multi-standard supported -# libm with XOPEN as the -# default standard -# CFLAGS = -D_POSIX_MODE ... Multi-standard supported -# libm with POSIX as the -# default standard -# CFLAGS = ... Multi-standard supported -# libm with IEEE as the -# default standard -# -# NOTE: if scalb's second arguement is an int, then one must -# define _SCALB_INT in CFLAGS. The default prototype of scalb -# is double scalb(double, double) -# - -DEPTH = .. - -include $(DEPTH)/config.mk - -# -# Default IEEE libm -# -CFLAGS += -DXP_UNIX $(OPTIMIZER) $(OS_CFLAGS) $(DEFINES) $(INCLUDES) \ - -DJSFILE $(XCFLAGS) -D_IEEE_LIBM - -# Need for jstypes.h and friends -INCLUDES += -I.. -INCLUDES += -I../$(OBJDIR) - -#CC = cc - -INCFILES = fdlibm.h -.INIT: $(INCFILES) -.KEEP_STATE: -FDLIBM_CFILES = \ - k_standard.c k_rem_pio2.c \ - k_cos.c k_sin.c k_tan.c \ - e_acos.c e_acosh.c e_asin.c e_atan2.c \ - e_atanh.c e_cosh.c e_exp.c e_fmod.c \ - e_gamma.c e_gamma_r.c e_hypot.c e_j0.c \ - e_j1.c e_jn.c e_lgamma.c e_lgamma_r.c \ - e_log.c e_log10.c e_pow.c e_rem_pio2.c e_remainder.c \ - e_scalb.c e_sinh.c e_sqrt.c \ - w_acos.c w_acosh.c w_asin.c w_atan2.c \ - w_atanh.c w_cosh.c w_exp.c w_fmod.c \ - w_gamma.c w_gamma_r.c w_hypot.c w_j0.c \ - w_j1.c w_jn.c w_lgamma.c w_lgamma_r.c \ - w_log.c w_log10.c w_pow.c w_remainder.c \ - w_scalb.c w_sinh.c w_sqrt.c \ - s_asinh.c s_atan.c s_cbrt.c s_ceil.c s_copysign.c \ - s_cos.c s_erf.c s_expm1.c s_fabs.c s_finite.c s_floor.c \ - s_frexp.c s_ilogb.c s_isnan.c s_ldexp.c s_lib_version.c \ - s_log1p.c s_logb.c s_matherr.c s_modf.c s_nextafter.c \ - s_rint.c s_scalbn.c s_signgam.c s_significand.c s_sin.c \ - s_tan.c s_tanh.c - -ifdef USE_MSVC -FDLIBM_OBJS = $(addprefix $(OBJDIR)/, $(FDLIBM_CFILES:.c=.obj)) -else -FDLIBM_OBJS = $(addprefix $(OBJDIR)/, $(FDLIBM_CFILES:.c=.o)) -endif - -ifdef USE_MSVC -LIBRARY = $(OBJDIR)/fdlibm.lib -else -LIBRARY = $(OBJDIR)/libfdm.a -endif - -define MAKE_OBJDIR -if test ! -d $(@D); then rm -rf $(@D); mkdir -p $(@D); fi -endef - -all: $(LIBRARY) - -export: - -$(OBJDIR)/%: %.c - @$(MAKE_OBJDIR) - $(CC) -o $@ $(CFLAGS) $*.c $(LDFLAGS) - -$(OBJDIR)/%.o: %.c - @$(MAKE_OBJDIR) - $(CC) -o $@ -c $(CFLAGS) $*.c - -$(OBJDIR)/%.o: %.s - @$(MAKE_OBJDIR) - $(AS) -o $@ $(ASFLAGS) $*.s - -# windows only -$(OBJDIR)/%.obj: %.c - @$(MAKE_OBJDIR) - $(CC) -Fo$(OBJDIR)/ -c $(CFLAGS) $*.c - -ifeq ($(OS_ARCH),OS2) -$(LIBRARY): $(FDLIBM_OBJS) - $(AR) $@ $? $(AR_OS2_SUFFIX) - $(RANLIB) $@ -else -ifdef USE_MSVC -$(LIBRARY): $(FDLIBM_OBJS) - lib.exe /out:"$@" $? -else -$(LIBRARY): $(FDLIBM_OBJS) - $(AR) rv $@ $? - $(RANLIB) $@ -endif -endif - -libfdm.a : $(FDLIBM_OBJS) - $(AR) cru $(OBJDIR)/libfdm.a $(FDLIBM_OBJS) - $(RANLIB) $(OBJDIR)/libfdm.a - -clean: - rm -rf $(FDLIBM_OBJS) - -clobber: - rm -rf $(FDLIBM_OBJS) $(LIBRARY) $(DEPENDENCIES) - -SUFFIXES: .i -%.i: %.c - $(CC) -C -E $(CFLAGS) $< > $*.i diff --git a/js/src/fdlibm/e_acos.c b/js/src/fdlibm/e_acos.c deleted file mode 100644 index a07c1eebc776..000000000000 --- a/js/src/fdlibm/e_acos.c +++ /dev/null @@ -1,147 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_acos.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* __ieee754_acos(x) - * Method : - * acos(x) = pi/2 - asin(x) - * acos(-x) = pi/2 + asin(x) - * For |x|<=0.5 - * acos(x) = pi/2 - (x + x*x^2*R(x^2)) (see asin.c) - * For x>0.5 - * acos(x) = pi/2 - (pi/2 - 2asin(sqrt((1-x)/2))) - * = 2asin(sqrt((1-x)/2)) - * = 2s + 2s*z*R(z) ...z=(1-x)/2, s=sqrt(z) - * = 2f + (2c + 2s*z*R(z)) - * where f=hi part of s, and c = (z-f*f)/(s+f) is the correction term - * for f so that f+c ~ sqrt(z). - * For x<-0.5 - * acos(x) = pi - 2asin(sqrt((1-|x|)/2)) - * = pi - 0.5*(s+s*z*R(z)), where z=(1-|x|)/2,s=sqrt(z) - * - * Special cases: - * if x is NaN, return x itself; - * if |x|>1, return NaN with invalid signal. - * - * Function needed: sqrt - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif -one= 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ -pi = 3.14159265358979311600e+00, /* 0x400921FB, 0x54442D18 */ -pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */ -pio2_lo = 6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */ -pS0 = 1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */ -pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */ -pS2 = 2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */ -pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */ -pS4 = 7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */ -pS5 = 3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */ -qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */ -qS2 = 2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */ -qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */ -qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */ - -#ifdef __STDC__ - double __ieee754_acos(double x) -#else - double __ieee754_acos(x) - double x; -#endif -{ - fd_twoints u; - double df; - double z,p,q,r,w,s,c; - int hx,ix; - u.d = x; - hx = __HI(u); - ix = hx&0x7fffffff; - if(ix>=0x3ff00000) { /* |x| >= 1 */ - if(((ix-0x3ff00000)|__LO(u))==0) { /* |x|==1 */ - if(hx>0) return 0.0; /* acos(1) = 0 */ - else return pi+2.0*pio2_lo; /* acos(-1)= pi */ - } - return (x-x)/(x-x); /* acos(|x|>1) is NaN */ - } - if(ix<0x3fe00000) { /* |x| < 0.5 */ - if(ix<=0x3c600000) return pio2_hi+pio2_lo;/*if|x|<2**-57*/ - z = x*x; - p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5))))); - q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4))); - r = p/q; - return pio2_hi - (x - (pio2_lo-x*r)); - } else if (hx<0) { /* x < -0.5 */ - z = (one+x)*0.5; - p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5))))); - q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4))); - s = fd_sqrt(z); - r = p/q; - w = r*s-pio2_lo; - return pi - 2.0*(s+w); - } else { /* x > 0.5 */ - z = (one-x)*0.5; - s = fd_sqrt(z); - u.d = s; - __LO(u) = 0; - df = u.d; - c = (z-df*df)/(s+df); - p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5))))); - q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4))); - r = p/q; - w = r*s+c; - return 2.0*(df+w); - } -} diff --git a/js/src/fdlibm/e_acosh.c b/js/src/fdlibm/e_acosh.c deleted file mode 100644 index 725cceefb42d..000000000000 --- a/js/src/fdlibm/e_acosh.c +++ /dev/null @@ -1,105 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_acosh.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - * - */ - -/* __ieee754_acosh(x) - * Method : - * Based on - * acosh(x) = log [ x + sqrt(x*x-1) ] - * we have - * acosh(x) := log(x)+ln2, if x is large; else - * acosh(x) := log(2x-1/(sqrt(x*x-1)+x)) if x>2; else - * acosh(x) := log1p(t+sqrt(2.0*t+t*t)); where t=x-1. - * - * Special cases: - * acosh(x) is NaN with signal if x<1. - * acosh(NaN) is NaN without signal. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif -one = 1.0, -ln2 = 6.93147180559945286227e-01; /* 0x3FE62E42, 0xFEFA39EF */ - -#ifdef __STDC__ - double __ieee754_acosh(double x) -#else - double __ieee754_acosh(x) - double x; -#endif -{ - fd_twoints u; - double t; - int hx; - u.d = x; - hx = __HI(u); - if(hx<0x3ff00000) { /* x < 1 */ - return (x-x)/(x-x); - } else if(hx >=0x41b00000) { /* x > 2**28 */ - if(hx >=0x7ff00000) { /* x is inf of NaN */ - return x+x; - } else - return __ieee754_log(x)+ln2; /* acosh(huge)=log(2x) */ - } else if(((hx-0x3ff00000)|__LO(u))==0) { - return 0.0; /* acosh(1) = 0 */ - } else if (hx > 0x40000000) { /* 2**28 > x > 2 */ - t=x*x; - return __ieee754_log(2.0*x-one/(x+fd_sqrt(t-one))); - } else { /* 10.98 - * asin(x) = pi/2 - 2*(s+s*z*R(z)) - * = pio2_hi - (2*(s+s*z*R(z)) - pio2_lo) - * For x<=0.98, let pio4_hi = pio2_hi/2, then - * f = hi part of s; - * c = sqrt(z) - f = (z-f*f)/(s+f) ...f+c=sqrt(z) - * and - * asin(x) = pi/2 - 2*(s+s*z*R(z)) - * = pio4_hi+(pio4-2s)-(2s*z*R(z)-pio2_lo) - * = pio4_hi+(pio4-2f)-(2s*z*R(z)-(pio2_lo+2c)) - * - * Special cases: - * if x is NaN, return x itself; - * if |x|>1, return NaN with invalid signal. - * - */ - - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif -one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ -really_big = 1.000e+300, -pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */ -pio2_lo = 6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */ -pio4_hi = 7.85398163397448278999e-01, /* 0x3FE921FB, 0x54442D18 */ - /* coefficient for R(x^2) */ -pS0 = 1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */ -pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */ -pS2 = 2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */ -pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */ -pS4 = 7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */ -pS5 = 3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */ -qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */ -qS2 = 2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */ -qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */ -qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */ - -#ifdef __STDC__ - double __ieee754_asin(double x) -#else - double __ieee754_asin(x) - double x; -#endif -{ - fd_twoints u; - double w,t,p,q,c,r,s; - int hx,ix; - u.d = x; - hx = __HI(u); - x = u.d; - ix = hx&0x7fffffff; - if(ix>= 0x3ff00000) { /* |x|>= 1 */ - if(((ix-0x3ff00000)|__LO(u))==0) - /* asin(1)=+-pi/2 with inexact */ - return x*pio2_hi+x*pio2_lo; - return (x-x)/(x-x); /* asin(|x|>1) is NaN */ - } else if (ix<0x3fe00000) { /* |x|<0.5 */ - if(ix<0x3e400000) { /* if |x| < 2**-27 */ - if(really_big+x>one) return x;/* return x with inexact if x!=0*/ - } else - t = x*x; - p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5))))); - q = one+t*(qS1+t*(qS2+t*(qS3+t*qS4))); - w = p/q; - return x+x*w; - } - /* 1> |x|>= 0.5 */ - w = one-fd_fabs(x); - t = w*0.5; - p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5))))); - q = one+t*(qS1+t*(qS2+t*(qS3+t*qS4))); - s = fd_sqrt(t); - if(ix>=0x3FEF3333) { /* if |x| > 0.975 */ - w = p/q; - t = pio2_hi-(2.0*(s+s*w)-pio2_lo); - } else { - u.d = s; - __LO(u) = 0; - w = u.d; - c = (t-w*w)/(s+w); - r = p/q; - p = 2.0*s*r-(pio2_lo-2.0*c); - q = pio4_hi-2.0*w; - t = pio4_hi-(p-q); - } - if(hx>0) return t; else return -t; -} diff --git a/js/src/fdlibm/e_atan2.c b/js/src/fdlibm/e_atan2.c deleted file mode 100644 index 9c9a2c01f337..000000000000 --- a/js/src/fdlibm/e_atan2.c +++ /dev/null @@ -1,165 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_atan2.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - * - */ - -/* __ieee754_atan2(y,x) - * Method : - * 1. Reduce y to positive by atan2(y,x)=-atan2(-y,x). - * 2. Reduce x to positive by (if x and y are unexceptional): - * ARG (x+iy) = arctan(y/x) ... if x > 0, - * ARG (x+iy) = pi - arctan[y/(-x)] ... if x < 0, - * - * Special cases: - * - * ATAN2((anything), NaN ) is NaN; - * ATAN2(NAN , (anything) ) is NaN; - * ATAN2(+-0, +(anything but NaN)) is +-0 ; - * ATAN2(+-0, -(anything but NaN)) is +-pi ; - * ATAN2(+-(anything but 0 and NaN), 0) is +-pi/2; - * ATAN2(+-(anything but INF and NaN), +INF) is +-0 ; - * ATAN2(+-(anything but INF and NaN), -INF) is +-pi; - * ATAN2(+-INF,+INF ) is +-pi/4 ; - * ATAN2(+-INF,-INF ) is +-3pi/4; - * ATAN2(+-INF, (anything but,0,NaN, and INF)) is +-pi/2; - * - * Constants: - * The hexadecimal values are the intended ones for the following - * constants. The decimal values may be used, provided that the - * compiler will convert from decimal to binary accurately enough - * to produce the hexadecimal values shown. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif -tiny = 1.0e-300, -zero = 0.0, -pi_o_4 = 7.8539816339744827900E-01, /* 0x3FE921FB, 0x54442D18 */ -pi_o_2 = 1.5707963267948965580E+00, /* 0x3FF921FB, 0x54442D18 */ -pi = 3.1415926535897931160E+00, /* 0x400921FB, 0x54442D18 */ -pi_lo = 1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */ - -#ifdef __STDC__ - double __ieee754_atan2(double y, double x) -#else - double __ieee754_atan2(y,x) - double y,x; -#endif -{ - fd_twoints ux, uy, uz; - double z; - int k,m,hx,hy,ix,iy; - unsigned lx,ly; - - ux.d = x; uy.d = y; - hx = __HI(ux); ix = hx&0x7fffffff; - lx = __LO(ux); - hy = __HI(uy); iy = hy&0x7fffffff; - ly = __LO(uy); - if(((ix|((lx|-(int)lx)>>31))>0x7ff00000)|| - ((iy|((ly|-(int)ly)>>31))>0x7ff00000)) /* x or y is NaN */ - return x+y; - if(((hx-0x3ff00000)|lx)==0) return fd_atan(y); /* x=1.0 */ - m = ((hy>>31)&1)|((hx>>30)&2); /* 2*sign(x)+sign(y) */ - - /* when y = 0 */ - if((iy|ly)==0) { - switch(m) { - case 0: - case 1: return y; /* atan(+-0,+anything)=+-0 */ - case 2: return pi+tiny;/* atan(+0,-anything) = pi */ - case 3: return -pi-tiny;/* atan(-0,-anything) =-pi */ - } - } - /* when x = 0 */ - if((ix|lx)==0) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny; - - /* when x is INF */ - if(ix==0x7ff00000) { - if(iy==0x7ff00000) { - switch(m) { - case 0: return pi_o_4+tiny;/* atan(+INF,+INF) */ - case 1: return -pi_o_4-tiny;/* atan(-INF,+INF) */ - case 2: return 3.0*pi_o_4+tiny;/*atan(+INF,-INF)*/ - case 3: return -3.0*pi_o_4-tiny;/*atan(-INF,-INF)*/ - } - } else { - switch(m) { - case 0: return zero ; /* atan(+...,+INF) */ - case 1: return -zero ; /* atan(-...,+INF) */ - case 2: return pi+tiny ; /* atan(+...,-INF) */ - case 3: return -pi-tiny ; /* atan(-...,-INF) */ - } - } - } - /* when y is INF */ - if(iy==0x7ff00000) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny; - - /* compute y/x */ - k = (iy-ix)>>20; - if(k > 60) z=pi_o_2+0.5*pi_lo; /* |y/x| > 2**60 */ - else if(hx<0&&k<-60) z=0.0; /* |y|/x < -2**60 */ - else z=fd_atan(fd_fabs(y/x)); /* safe to do y/x */ - switch (m) { - case 0: return z ; /* atan(+,+) */ - case 1: uz.d = z; - __HI(uz) ^= 0x80000000; - z = uz.d; - return z ; /* atan(-,+) */ - case 2: return pi-(z-pi_lo);/* atan(+,-) */ - default: /* case 3 */ - return (z-pi_lo)-pi;/* atan(-,-) */ - } -} diff --git a/js/src/fdlibm/e_atanh.c b/js/src/fdlibm/e_atanh.c deleted file mode 100644 index dc4a90c8e035..000000000000 --- a/js/src/fdlibm/e_atanh.c +++ /dev/null @@ -1,110 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_atanh.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - * - */ - -/* __ieee754_atanh(x) - * Method : - * 1.Reduced x to positive by atanh(-x) = -atanh(x) - * 2.For x>=0.5 - * 1 2x x - * atanh(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------) - * 2 1 - x 1 - x - * - * For x<0.5 - * atanh(x) = 0.5*log1p(2x+2x*x/(1-x)) - * - * Special cases: - * atanh(x) is NaN if |x| > 1 with signal; - * atanh(NaN) is that NaN with no signal; - * atanh(+-1) is +-INF with signal. - * - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double one = 1.0, really_big = 1e300; -#else -static double one = 1.0, really_big = 1e300; -#endif - -static double zero = 0.0; - -#ifdef __STDC__ - double __ieee754_atanh(double x) -#else - double __ieee754_atanh(x) - double x; -#endif -{ - double t; - int hx,ix; - unsigned lx; - fd_twoints u; - u.d = x; - hx = __HI(u); /* high word */ - lx = __LO(u); /* low word */ - ix = hx&0x7fffffff; - if ((ix|((lx|(-(int)lx))>>31))>0x3ff00000) /* |x|>1 */ - return (x-x)/(x-x); - if(ix==0x3ff00000) - return x/zero; - if(ix<0x3e300000&&(really_big+x)>zero) return x; /* x<2**-28 */ - u.d = x; - __HI(u) = ix; /* x <- |x| */ - x = u.d; - if(ix<0x3fe00000) { /* x < 0.5 */ - t = x+x; - t = 0.5*fd_log1p(t+t*x/(one-x)); - } else - t = 0.5*fd_log1p((x+x)/(one-x)); - if(hx>=0) return t; else return -t; -} diff --git a/js/src/fdlibm/e_cosh.c b/js/src/fdlibm/e_cosh.c deleted file mode 100644 index 4f8d4f7697da..000000000000 --- a/js/src/fdlibm/e_cosh.c +++ /dev/null @@ -1,133 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_cosh.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* __ieee754_cosh(x) - * Method : - * mathematically cosh(x) if defined to be (exp(x)+exp(-x))/2 - * 1. Replace x by |x| (cosh(x) = cosh(-x)). - * 2. - * [ exp(x) - 1 ]^2 - * 0 <= x <= ln2/2 : cosh(x) := 1 + ------------------- - * 2*exp(x) - * - * exp(x) + 1/exp(x) - * ln2/2 <= x <= 22 : cosh(x) := ------------------- - * 2 - * 22 <= x <= lnovft : cosh(x) := exp(x)/2 - * lnovft <= x <= ln2ovft: cosh(x) := exp(x/2)/2 * exp(x/2) - * ln2ovft < x : cosh(x) := huge*huge (overflow) - * - * Special cases: - * cosh(x) is |x| if x is +INF, -INF, or NaN. - * only cosh(0)=1 is exact for finite x. - */ - -#include "fdlibm.h" - -#ifdef _WIN32 -#define huge myhuge -#endif - -#ifdef __STDC__ -static const double one = 1.0, half=0.5, really_big = 1.0e300; -#else -static double one = 1.0, half=0.5, really_big = 1.0e300; -#endif - -#ifdef __STDC__ - double __ieee754_cosh(double x) -#else - double __ieee754_cosh(x) - double x; -#endif -{ - fd_twoints u; - double t,w; - int ix; - unsigned lx; - - /* High word of |x|. */ - u.d = x; - ix = __HI(u); - ix &= 0x7fffffff; - - /* x is INF or NaN */ - if(ix>=0x7ff00000) return x*x; - - /* |x| in [0,0.5*ln2], return 1+expm1(|x|)^2/(2*exp(|x|)) */ - if(ix<0x3fd62e43) { - t = fd_expm1(fd_fabs(x)); - w = one+t; - if (ix<0x3c800000) return w; /* cosh(tiny) = 1 */ - return one+(t*t)/(w+w); - } - - /* |x| in [0.5*ln2,22], return (exp(|x|)+1/exp(|x|)/2; */ - if (ix < 0x40360000) { - t = __ieee754_exp(fd_fabs(x)); - return half*t+half/t; - } - - /* |x| in [22, log(maxdouble)] return half*exp(|x|) */ - if (ix < 0x40862E42) return half*__ieee754_exp(fd_fabs(x)); - - /* |x| in [log(maxdouble), overflowthresold] */ - lx = *( (((*(unsigned*)&one)>>29)) + (unsigned*)&x); - if (ix<0x408633CE || - (ix==0x408633ce)&&(lx<=(unsigned)0x8fb9f87d)) { - w = __ieee754_exp(half*fd_fabs(x)); - t = half*w; - return t*w; - } - - /* |x| > overflowthresold, cosh(x) overflow */ - return really_big*really_big; -} diff --git a/js/src/fdlibm/e_exp.c b/js/src/fdlibm/e_exp.c deleted file mode 100644 index ad9cec12419f..000000000000 --- a/js/src/fdlibm/e_exp.c +++ /dev/null @@ -1,202 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_exp.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* __ieee754_exp(x) - * Returns the exponential of x. - * - * Method - * 1. Argument reduction: - * Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658. - * Given x, find r and integer k such that - * - * x = k*ln2 + r, |r| <= 0.5*ln2. - * - * Here r will be represented as r = hi-lo for better - * accuracy. - * - * 2. Approximation of exp(r) by a special rational function on - * the interval [0,0.34658]: - * Write - * R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ... - * We use a special Reme algorithm on [0,0.34658] to generate - * a polynomial of degree 5 to approximate R. The maximum error - * of this polynomial approximation is bounded by 2**-59. In - * other words, - * R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5 - * (where z=r*r, and the values of P1 to P5 are listed below) - * and - * | 5 | -59 - * | 2.0+P1*z+...+P5*z - R(z) | <= 2 - * | | - * The computation of exp(r) thus becomes - * 2*r - * exp(r) = 1 + ------- - * R - r - * r*R1(r) - * = 1 + r + ----------- (for better accuracy) - * 2 - R1(r) - * where - * 2 4 10 - * R1(r) = r - (P1*r + P2*r + ... + P5*r ). - * - * 3. Scale back to obtain exp(x): - * From step 1, we have - * exp(x) = 2^k * exp(r) - * - * Special cases: - * exp(INF) is INF, exp(NaN) is NaN; - * exp(-INF) is 0, and - * for finite argument, only exp(0)=1 is exact. - * - * Accuracy: - * according to an error analysis, the error is always less than - * 1 ulp (unit in the last place). - * - * Misc. info. - * For IEEE double - * if x > 7.09782712893383973096e+02 then exp(x) overflow - * if x < -7.45133219101941108420e+02 then exp(x) underflow - * - * Constants: - * The hexadecimal values are the intended ones for the following - * constants. The decimal values may be used, provided that the - * compiler will convert from decimal to binary accurately enough - * to produce the hexadecimal values shown. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif -one = 1.0, -halF[2] = {0.5,-0.5,}, -really_big = 1.0e+300, -twom1000= 9.33263618503218878990e-302, /* 2**-1000=0x01700000,0*/ -o_threshold= 7.09782712893383973096e+02, /* 0x40862E42, 0xFEFA39EF */ -u_threshold= -7.45133219101941108420e+02, /* 0xc0874910, 0xD52D3051 */ -ln2HI[2] ={ 6.93147180369123816490e-01, /* 0x3fe62e42, 0xfee00000 */ - -6.93147180369123816490e-01,},/* 0xbfe62e42, 0xfee00000 */ -ln2LO[2] ={ 1.90821492927058770002e-10, /* 0x3dea39ef, 0x35793c76 */ - -1.90821492927058770002e-10,},/* 0xbdea39ef, 0x35793c76 */ -invln2 = 1.44269504088896338700e+00, /* 0x3ff71547, 0x652b82fe */ -P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */ -P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */ -P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */ -P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */ -P5 = 4.13813679705723846039e-08; /* 0x3E663769, 0x72BEA4D0 */ - - -#ifdef __STDC__ - double __ieee754_exp(double x) /* default IEEE double exp */ -#else - double __ieee754_exp(x) /* default IEEE double exp */ - double x; -#endif -{ - fd_twoints u; - double y,hi,lo,c,t; - int k, xsb; - unsigned hx; - - u.d = x; - hx = __HI(u); /* high word of x */ - xsb = (hx>>31)&1; /* sign bit of x */ - hx &= 0x7fffffff; /* high word of |x| */ - - /* filter out non-finite argument */ - if(hx >= 0x40862E42) { /* if |x|>=709.78... */ - if(hx>=0x7ff00000) { - u.d = x; - if(((hx&0xfffff)|__LO(u))!=0) - return x+x; /* NaN */ - else return (xsb==0)? x:0.0; /* exp(+-inf)={inf,0} */ - } - if(x > o_threshold) return really_big*really_big; /* overflow */ - if(x < u_threshold) return twom1000*twom1000; /* underflow */ - } - - /* argument reduction */ - if(hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */ - if(hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */ - hi = x-ln2HI[xsb]; lo=ln2LO[xsb]; k = 1-xsb-xsb; - } else { - k = (int)(invln2*x+halF[xsb]); - t = k; - hi = x - t*ln2HI[0]; /* t*ln2HI is exact here */ - lo = t*ln2LO[0]; - } - x = hi - lo; - } - else if(hx < 0x3e300000) { /* when |x|<2**-28 */ - if(really_big+x>one) return one+x;/* trigger inexact */ - } - else k = 0; - - /* x is now in primary range */ - t = x*x; - c = x - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))); - if(k==0) return one-((x*c)/(c-2.0)-x); - else y = one-((lo-(x*c)/(2.0-c))-hi); - if(k >= -1021) { - u.d = y; - __HI(u) += (k<<20); /* add k to y's exponent */ - y = u.d; - return y; - } else { - u.d = y; - __HI(u) += ((k+1000)<<20);/* add k to y's exponent */ - y = u.d; - return y*twom1000; - } -} diff --git a/js/src/fdlibm/e_fmod.c b/js/src/fdlibm/e_fmod.c deleted file mode 100644 index 7b5ce780f380..000000000000 --- a/js/src/fdlibm/e_fmod.c +++ /dev/null @@ -1,184 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_fmod.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * __ieee754_fmod(x,y) - * Return x mod y in exact arithmetic - * Method: shift and subtract - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double one = 1.0, Zero[] = {0.0, -0.0,}; -#else -static double one = 1.0, Zero[] = {0.0, -0.0,}; -#endif - -#ifdef __STDC__ - double __ieee754_fmod(double x, double y) -#else - double __ieee754_fmod(x,y) - double x,y ; -#endif -{ - fd_twoints ux, uy; - int n,hx,hy,hz,ix,iy,sx,i; - unsigned lx,ly,lz; - - ux.d = x; uy.d = y; - hx = __HI(ux); /* high word of x */ - lx = __LO(ux); /* low word of x */ - hy = __HI(uy); /* high word of y */ - ly = __LO(uy); /* low word of y */ - sx = hx&0x80000000; /* sign of x */ - hx ^=sx; /* |x| */ - hy &= 0x7fffffff; /* |y| */ - - /* purge off exception values */ - if((hy|ly)==0||(hx>=0x7ff00000)|| /* y=0,or x not finite */ - ((hy|((ly|-(int)ly)>>31))>0x7ff00000)) /* or y is NaN */ - return (x*y)/(x*y); - if(hx<=hy) { - if((hx>31]; /* |x|=|y| return x*0*/ - } - - /* determine ix = ilogb(x) */ - if(hx<0x00100000) { /* subnormal x */ - if(hx==0) { - for (ix = -1043, i=lx; i>0; i<<=1) ix -=1; - } else { - for (ix = -1022,i=(hx<<11); i>0; i<<=1) ix -=1; - } - } else ix = (hx>>20)-1023; - - /* determine iy = ilogb(y) */ - if(hy<0x00100000) { /* subnormal y */ - if(hy==0) { - for (iy = -1043, i=ly; i>0; i<<=1) iy -=1; - } else { - for (iy = -1022,i=(hy<<11); i>0; i<<=1) iy -=1; - } - } else iy = (hy>>20)-1023; - - /* set up {hx,lx}, {hy,ly} and align y to x */ - if(ix >= -1022) - hx = 0x00100000|(0x000fffff&hx); - else { /* subnormal x, shift x to normal */ - n = -1022-ix; - if(n<=31) { - hx = (hx<>(32-n)); - lx <<= n; - } else { - hx = lx<<(n-32); - lx = 0; - } - } - if(iy >= -1022) - hy = 0x00100000|(0x000fffff&hy); - else { /* subnormal y, shift y to normal */ - n = -1022-iy; - if(n<=31) { - hy = (hy<>(32-n)); - ly <<= n; - } else { - hy = ly<<(n-32); - ly = 0; - } - } - - /* fix point fmod */ - n = ix - iy; - while(n--) { - hz=hx-hy;lz=lx-ly; if(lx>31); lx = lx+lx;} - else { - if((hz|lz)==0) /* return sign(x)*0 */ - return Zero[(unsigned)sx>>31]; - hx = hz+hz+(lz>>31); lx = lz+lz; - } - } - hz=hx-hy;lz=lx-ly; if(lx=0) {hx=hz;lx=lz;} - - /* convert back to floating value and restore the sign */ - if((hx|lx)==0) /* return sign(x)*0 */ - return Zero[(unsigned)sx>>31]; - while(hx<0x00100000) { /* normalize x */ - hx = hx+hx+(lx>>31); lx = lx+lx; - iy -= 1; - } - if(iy>= -1022) { /* normalize output */ - hx = ((hx-0x00100000)|((iy+1023)<<20)); - ux.d = x; - __HI(ux) = hx|sx; - __LO(ux) = lx; - x = ux.d; - } else { /* subnormal output */ - n = -1022 - iy; - if(n<=20) { - lx = (lx>>n)|((unsigned)hx<<(32-n)); - hx >>= n; - } else if (n<=31) { - lx = (hx<<(32-n))|(lx>>n); hx = sx; - } else { - lx = hx>>(n-32); hx = sx; - } - ux.d = x; - __HI(ux) = hx|sx; - __LO(ux) = lx; - x = ux.d; - x *= one; /* create necessary signal */ - } - return x; /* exact output */ -} diff --git a/js/src/fdlibm/e_gamma.c b/js/src/fdlibm/e_gamma.c deleted file mode 100644 index a34faa32cf69..000000000000 --- a/js/src/fdlibm/e_gamma.c +++ /dev/null @@ -1,71 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_gamma.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - * - */ - -/* __ieee754_gamma(x) - * Return the logarithm of the Gamma function of x. - * - * Method: call __ieee754_gamma_r - */ - -#include "fdlibm.h" - -extern int signgam; - -#ifdef __STDC__ - double __ieee754_gamma(double x) -#else - double __ieee754_gamma(x) - double x; -#endif -{ - return __ieee754_gamma_r(x,&signgam); -} diff --git a/js/src/fdlibm/e_gamma_r.c b/js/src/fdlibm/e_gamma_r.c deleted file mode 100644 index f10e32e361ee..000000000000 --- a/js/src/fdlibm/e_gamma_r.c +++ /dev/null @@ -1,70 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_gamma_r.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - * - */ - -/* __ieee754_gamma_r(x, signgamp) - * Reentrant version of the logarithm of the Gamma function - * with user provide pointer for the sign of Gamma(x). - * - * Method: See __ieee754_lgamma_r - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - double __ieee754_gamma_r(double x, int *signgamp) -#else - double __ieee754_gamma_r(x,signgamp) - double x; int *signgamp; -#endif -{ - return __ieee754_lgamma_r(x,signgamp); -} diff --git a/js/src/fdlibm/e_hypot.c b/js/src/fdlibm/e_hypot.c deleted file mode 100644 index 3900230878ef..000000000000 --- a/js/src/fdlibm/e_hypot.c +++ /dev/null @@ -1,173 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_hypot.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* __ieee754_hypot(x,y) - * - * Method : - * If (assume round-to-nearest) z=x*x+y*y - * has error less than sqrt(2)/2 ulp, than - * sqrt(z) has error less than 1 ulp (exercise). - * - * So, compute sqrt(x*x+y*y) with some care as - * follows to get the error below 1 ulp: - * - * Assume x>y>0; - * (if possible, set rounding to round-to-nearest) - * 1. if x > 2y use - * x1*x1+(y*y+(x2*(x+x1))) for x*x+y*y - * where x1 = x with lower 32 bits cleared, x2 = x-x1; else - * 2. if x <= 2y use - * t1*y1+((x-y)*(x-y)+(t1*y2+t2*y)) - * where t1 = 2x with lower 32 bits cleared, t2 = 2x-t1, - * y1= y with lower 32 bits chopped, y2 = y-y1. - * - * NOTE: scaling may be necessary if some argument is too - * large or too tiny - * - * Special cases: - * hypot(x,y) is INF if x or y is +INF or -INF; else - * hypot(x,y) is NAN if x or y is NAN. - * - * Accuracy: - * hypot(x,y) returns sqrt(x^2+y^2) with error less - * than 1 ulps (units in the last place) - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - double __ieee754_hypot(double x, double y) -#else - double __ieee754_hypot(x,y) - double x, y; -#endif -{ - fd_twoints ux, uy; - double a=x,b=y,t1,t2,y1,y2,w; - int j,k,ha,hb; - - ux.d = x; uy.d = y; - ha = __HI(ux)&0x7fffffff; /* high word of x */ - hb = __HI(uy)&0x7fffffff; /* high word of y */ - if(hb > ha) {a=y;b=x;j=ha; ha=hb;hb=j;} else {a=x;b=y;} - ux.d = a; uy.d = b; - __HI(ux) = ha; /* a <- |a| */ - __HI(uy) = hb; /* b <- |b| */ - a = ux.d; b = uy.d; - if((ha-hb)>0x3c00000) {return a+b;} /* x/y > 2**60 */ - k=0; - if(ha > 0x5f300000) { /* a>2**500 */ - if(ha >= 0x7ff00000) { /* Inf or NaN */ - w = a+b; /* for sNaN */ - ux.d = a; uy.d = b; - if(((ha&0xfffff)|__LO(ux))==0) w = a; - if(((hb^0x7ff00000)|__LO(uy))==0) w = b; - return w; - } - /* scale a and b by 2**-600 */ - ha -= 0x25800000; hb -= 0x25800000; k += 600; - ux.d = a; uy.d = b; - __HI(ux) = ha; - __HI(uy) = hb; - a = ux.d; b = uy.d; - } - if(hb < 0x20b00000) { /* b < 2**-500 */ - if(hb <= 0x000fffff) { /* subnormal b or 0 */ - uy.d = b; - if((hb|(__LO(uy)))==0) return a; - t1=0; - ux.d = t1; - __HI(ux) = 0x7fd00000; /* t1=2^1022 */ - t1 = ux.d; - b *= t1; - a *= t1; - k -= 1022; - } else { /* scale a and b by 2^600 */ - ha += 0x25800000; /* a *= 2^600 */ - hb += 0x25800000; /* b *= 2^600 */ - k -= 600; - ux.d = a; uy.d = b; - __HI(ux) = ha; - __HI(uy) = hb; - a = ux.d; b = uy.d; - } - } - /* medium size a and b */ - w = a-b; - if (w>b) { - t1 = 0; - ux.d = t1; - __HI(ux) = ha; - t1 = ux.d; - t2 = a-t1; - w = fd_sqrt(t1*t1-(b*(-b)-t2*(a+t1))); - } else { - a = a+a; - y1 = 0; - ux.d = y1; - __HI(ux) = hb; - y1 = ux.d; - y2 = b - y1; - t1 = 0; - ux.d = t1; - __HI(ux) = ha+0x00100000; - t1 = ux.d; - t2 = a - t1; - w = fd_sqrt(t1*y1-(w*(-w)-(t1*y2+t2*b))); - } - if(k!=0) { - t1 = 1.0; - ux.d = t1; - __HI(ux) += (k<<20); - t1 = ux.d; - return t1*w; - } else return w; -} diff --git a/js/src/fdlibm/e_j0.c b/js/src/fdlibm/e_j0.c deleted file mode 100644 index 078e096415cb..000000000000 --- a/js/src/fdlibm/e_j0.c +++ /dev/null @@ -1,524 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_j0.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* __ieee754_j0(x), __ieee754_y0(x) - * Bessel function of the first and second kinds of order zero. - * Method -- j0(x): - * 1. For tiny x, we use j0(x) = 1 - x^2/4 + x^4/64 - ... - * 2. Reduce x to |x| since j0(x)=j0(-x), and - * for x in (0,2) - * j0(x) = 1-z/4+ z^2*R0/S0, where z = x*x; - * (precision: |j0-1+z/4-z^2R0/S0 |<2**-63.67 ) - * for x in (2,inf) - * j0(x) = sqrt(2/(pi*x))*(p0(x)*cos(x0)-q0(x)*sin(x0)) - * where x0 = x-pi/4. It is better to compute sin(x0),cos(x0) - * as follow: - * cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4) - * = 1/sqrt(2) * (cos(x) + sin(x)) - * sin(x0) = sin(x)cos(pi/4)-cos(x)sin(pi/4) - * = 1/sqrt(2) * (sin(x) - cos(x)) - * (To avoid cancellation, use - * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) - * to compute the worse one.) - * - * 3 Special cases - * j0(nan)= nan - * j0(0) = 1 - * j0(inf) = 0 - * - * Method -- y0(x): - * 1. For x<2. - * Since - * y0(x) = 2/pi*(j0(x)*(ln(x/2)+Euler) + x^2/4 - ...) - * therefore y0(x)-2/pi*j0(x)*ln(x) is an even function. - * We use the following function to approximate y0, - * y0(x) = U(z)/V(z) + (2/pi)*(j0(x)*ln(x)), z= x^2 - * where - * U(z) = u00 + u01*z + ... + u06*z^6 - * V(z) = 1 + v01*z + ... + v04*z^4 - * with absolute approximation error bounded by 2**-72. - * Note: For tiny x, U/V = u0 and j0(x)~1, hence - * y0(tiny) = u0 + (2/pi)*ln(tiny), (choose tiny<2**-27) - * 2. For x>=2. - * y0(x) = sqrt(2/(pi*x))*(p0(x)*cos(x0)+q0(x)*sin(x0)) - * where x0 = x-pi/4. It is better to compute sin(x0),cos(x0) - * by the method mentioned above. - * 3. Special cases: y0(0)=-inf, y0(x<0)=NaN, y0(inf)=0. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static double pzero(double), qzero(double); -#else -static double pzero(), qzero(); -#endif - -#ifdef __STDC__ -static const double -#else -static double -#endif -really_big = 1e300, -one = 1.0, -invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */ -tpi = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ - /* R0/S0 on [0, 2.00] */ -R02 = 1.56249999999999947958e-02, /* 0x3F8FFFFF, 0xFFFFFFFD */ -R03 = -1.89979294238854721751e-04, /* 0xBF28E6A5, 0xB61AC6E9 */ -R04 = 1.82954049532700665670e-06, /* 0x3EBEB1D1, 0x0C503919 */ -R05 = -4.61832688532103189199e-09, /* 0xBE33D5E7, 0x73D63FCE */ -S01 = 1.56191029464890010492e-02, /* 0x3F8FFCE8, 0x82C8C2A4 */ -S02 = 1.16926784663337450260e-04, /* 0x3F1EA6D2, 0xDD57DBF4 */ -S03 = 5.13546550207318111446e-07, /* 0x3EA13B54, 0xCE84D5A9 */ -S04 = 1.16614003333790000205e-09; /* 0x3E1408BC, 0xF4745D8F */ - -static double zero = 0.0; - -#ifdef __STDC__ - double __ieee754_j0(double x) -#else - double __ieee754_j0(x) - double x; -#endif -{ - fd_twoints un; - double z, s,c,ss,cc,r,u,v; - int hx,ix; - - un.d = x; - hx = __HI(un); - ix = hx&0x7fffffff; - if(ix>=0x7ff00000) return one/(x*x); - x = fd_fabs(x); - if(ix >= 0x40000000) { /* |x| >= 2.0 */ - s = fd_sin(x); - c = fd_cos(x); - ss = s-c; - cc = s+c; - if(ix<0x7fe00000) { /* make sure x+x not overflow */ - z = -fd_cos(x+x); - if ((s*c)0x48000000) z = (invsqrtpi*cc)/fd_sqrt(x); - else { - u = pzero(x); v = qzero(x); - z = invsqrtpi*(u*cc-v*ss)/fd_sqrt(x); - } - return z; - } - if(ix<0x3f200000) { /* |x| < 2**-13 */ - if(really_big+x>one) { /* raise inexact if x != 0 */ - if(ix<0x3e400000) return one; /* |x|<2**-27 */ - else return one - 0.25*x*x; - } - } - z = x*x; - r = z*(R02+z*(R03+z*(R04+z*R05))); - s = one+z*(S01+z*(S02+z*(S03+z*S04))); - if(ix < 0x3FF00000) { /* |x| < 1.00 */ - return one + z*(-0.25+(r/s)); - } else { - u = 0.5*x; - return((one+u)*(one-u)+z*(r/s)); - } -} - -#ifdef __STDC__ -static const double -#else -static double -#endif -u00 = -7.38042951086872317523e-02, /* 0xBFB2E4D6, 0x99CBD01F */ -u01 = 1.76666452509181115538e-01, /* 0x3FC69D01, 0x9DE9E3FC */ -u02 = -1.38185671945596898896e-02, /* 0xBF8C4CE8, 0xB16CFA97 */ -u03 = 3.47453432093683650238e-04, /* 0x3F36C54D, 0x20B29B6B */ -u04 = -3.81407053724364161125e-06, /* 0xBECFFEA7, 0x73D25CAD */ -u05 = 1.95590137035022920206e-08, /* 0x3E550057, 0x3B4EABD4 */ -u06 = -3.98205194132103398453e-11, /* 0xBDC5E43D, 0x693FB3C8 */ -v01 = 1.27304834834123699328e-02, /* 0x3F8A1270, 0x91C9C71A */ -v02 = 7.60068627350353253702e-05, /* 0x3F13ECBB, 0xF578C6C1 */ -v03 = 2.59150851840457805467e-07, /* 0x3E91642D, 0x7FF202FD */ -v04 = 4.41110311332675467403e-10; /* 0x3DFE5018, 0x3BD6D9EF */ - -#ifdef __STDC__ - double __ieee754_y0(double x) -#else - double __ieee754_y0(x) - double x; -#endif -{ - fd_twoints un; - double z, s,c,ss,cc,u,v; - int hx,ix,lx; - - un.d = x; - hx = __HI(un); - ix = 0x7fffffff&hx; - lx = __LO(un); - /* Y0(NaN) is NaN, y0(-inf) is Nan, y0(inf) is 0 */ - if(ix>=0x7ff00000) return one/(x+x*x); - if((ix|lx)==0) return -one/zero; - if(hx<0) return zero/zero; - if(ix >= 0x40000000) { /* |x| >= 2.0 */ - /* y0(x) = sqrt(2/(pi*x))*(p0(x)*sin(x0)+q0(x)*cos(x0)) - * where x0 = x-pi/4 - * Better formula: - * cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4) - * = 1/sqrt(2) * (sin(x) + cos(x)) - * sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4) - * = 1/sqrt(2) * (sin(x) - cos(x)) - * To avoid cancellation, use - * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) - * to compute the worse one. - */ - s = fd_sin(x); - c = fd_cos(x); - ss = s-c; - cc = s+c; - /* - * j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x) - * y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x) - */ - if(ix<0x7fe00000) { /* make sure x+x not overflow */ - z = -fd_cos(x+x); - if ((s*c)0x48000000) z = (invsqrtpi*ss)/fd_sqrt(x); - else { - u = pzero(x); v = qzero(x); - z = invsqrtpi*(u*ss+v*cc)/fd_sqrt(x); - } - return z; - } - if(ix<=0x3e400000) { /* x < 2**-27 */ - return(u00 + tpi*__ieee754_log(x)); - } - z = x*x; - u = u00+z*(u01+z*(u02+z*(u03+z*(u04+z*(u05+z*u06))))); - v = one+z*(v01+z*(v02+z*(v03+z*v04))); - return(u/v + tpi*(__ieee754_j0(x)*__ieee754_log(x))); -} - -/* The asymptotic expansions of pzero is - * 1 - 9/128 s^2 + 11025/98304 s^4 - ..., where s = 1/x. - * For x >= 2, We approximate pzero by - * pzero(x) = 1 + (R/S) - * where R = pR0 + pR1*s^2 + pR2*s^4 + ... + pR5*s^10 - * S = 1 + pS0*s^2 + ... + pS4*s^10 - * and - * | pzero(x)-1-R/S | <= 2 ** ( -60.26) - */ -#ifdef __STDC__ -static const double pR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ -#else -static double pR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ -#endif - 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ - -7.03124999999900357484e-02, /* 0xBFB1FFFF, 0xFFFFFD32 */ - -8.08167041275349795626e+00, /* 0xC02029D0, 0xB44FA779 */ - -2.57063105679704847262e+02, /* 0xC0701102, 0x7B19E863 */ - -2.48521641009428822144e+03, /* 0xC0A36A6E, 0xCD4DCAFC */ - -5.25304380490729545272e+03, /* 0xC0B4850B, 0x36CC643D */ -}; -#ifdef __STDC__ -static const double pS8[5] = { -#else -static double pS8[5] = { -#endif - 1.16534364619668181717e+02, /* 0x405D2233, 0x07A96751 */ - 3.83374475364121826715e+03, /* 0x40ADF37D, 0x50596938 */ - 4.05978572648472545552e+04, /* 0x40E3D2BB, 0x6EB6B05F */ - 1.16752972564375915681e+05, /* 0x40FC810F, 0x8F9FA9BD */ - 4.76277284146730962675e+04, /* 0x40E74177, 0x4F2C49DC */ -}; - -#ifdef __STDC__ -static const double pR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ -#else -static double pR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ -#endif - -1.14125464691894502584e-11, /* 0xBDA918B1, 0x47E495CC */ - -7.03124940873599280078e-02, /* 0xBFB1FFFF, 0xE69AFBC6 */ - -4.15961064470587782438e+00, /* 0xC010A370, 0xF90C6BBF */ - -6.76747652265167261021e+01, /* 0xC050EB2F, 0x5A7D1783 */ - -3.31231299649172967747e+02, /* 0xC074B3B3, 0x6742CC63 */ - -3.46433388365604912451e+02, /* 0xC075A6EF, 0x28A38BD7 */ -}; -#ifdef __STDC__ -static const double pS5[5] = { -#else -static double pS5[5] = { -#endif - 6.07539382692300335975e+01, /* 0x404E6081, 0x0C98C5DE */ - 1.05125230595704579173e+03, /* 0x40906D02, 0x5C7E2864 */ - 5.97897094333855784498e+03, /* 0x40B75AF8, 0x8FBE1D60 */ - 9.62544514357774460223e+03, /* 0x40C2CCB8, 0xFA76FA38 */ - 2.40605815922939109441e+03, /* 0x40A2CC1D, 0xC70BE864 */ -}; - -#ifdef __STDC__ -static const double pR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ -#else -static double pR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ -#endif - -2.54704601771951915620e-09, /* 0xBE25E103, 0x6FE1AA86 */ - -7.03119616381481654654e-02, /* 0xBFB1FFF6, 0xF7C0E24B */ - -2.40903221549529611423e+00, /* 0xC00345B2, 0xAEA48074 */ - -2.19659774734883086467e+01, /* 0xC035F74A, 0x4CB94E14 */ - -5.80791704701737572236e+01, /* 0xC04D0A22, 0x420A1A45 */ - -3.14479470594888503854e+01, /* 0xC03F72AC, 0xA892D80F */ -}; -#ifdef __STDC__ -static const double pS3[5] = { -#else -static double pS3[5] = { -#endif - 3.58560338055209726349e+01, /* 0x4041ED92, 0x84077DD3 */ - 3.61513983050303863820e+02, /* 0x40769839, 0x464A7C0E */ - 1.19360783792111533330e+03, /* 0x4092A66E, 0x6D1061D6 */ - 1.12799679856907414432e+03, /* 0x40919FFC, 0xB8C39B7E */ - 1.73580930813335754692e+02, /* 0x4065B296, 0xFC379081 */ -}; - -#ifdef __STDC__ -static const double pR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ -#else -static double pR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ -#endif - -8.87534333032526411254e-08, /* 0xBE77D316, 0xE927026D */ - -7.03030995483624743247e-02, /* 0xBFB1FF62, 0x495E1E42 */ - -1.45073846780952986357e+00, /* 0xBFF73639, 0x8A24A843 */ - -7.63569613823527770791e+00, /* 0xC01E8AF3, 0xEDAFA7F3 */ - -1.11931668860356747786e+01, /* 0xC02662E6, 0xC5246303 */ - -3.23364579351335335033e+00, /* 0xC009DE81, 0xAF8FE70F */ -}; -#ifdef __STDC__ -static const double pS2[5] = { -#else -static double pS2[5] = { -#endif - 2.22202997532088808441e+01, /* 0x40363865, 0x908B5959 */ - 1.36206794218215208048e+02, /* 0x4061069E, 0x0EE8878F */ - 2.70470278658083486789e+02, /* 0x4070E786, 0x42EA079B */ - 1.53875394208320329881e+02, /* 0x40633C03, 0x3AB6FAFF */ - 1.46576176948256193810e+01, /* 0x402D50B3, 0x44391809 */ -}; - -#ifdef __STDC__ - static double pzero(double x) -#else - static double pzero(x) - double x; -#endif -{ -#ifdef __STDC__ - const double *p,*q; -#else - double *p,*q; -#endif - fd_twoints u; - double z,r,s; - int ix; - u.d = x; - ix = 0x7fffffff&__HI(u); - if(ix>=0x40200000) {p = pR8; q= pS8;} - else if(ix>=0x40122E8B){p = pR5; q= pS5;} - else if(ix>=0x4006DB6D){p = pR3; q= pS3;} - else if(ix>=0x40000000){p = pR2; q= pS2;} - z = one/(x*x); - r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5])))); - s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4])))); - return one+ r/s; -} - - -/* For x >= 8, the asymptotic expansions of qzero is - * -1/8 s + 75/1024 s^3 - ..., where s = 1/x. - * We approximate pzero by - * qzero(x) = s*(-1.25 + (R/S)) - * where R = qR0 + qR1*s^2 + qR2*s^4 + ... + qR5*s^10 - * S = 1 + qS0*s^2 + ... + qS5*s^12 - * and - * | qzero(x)/s +1.25-R/S | <= 2 ** ( -61.22) - */ -#ifdef __STDC__ -static const double qR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ -#else -static double qR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ -#endif - 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ - 7.32421874999935051953e-02, /* 0x3FB2BFFF, 0xFFFFFE2C */ - 1.17682064682252693899e+01, /* 0x40278952, 0x5BB334D6 */ - 5.57673380256401856059e+02, /* 0x40816D63, 0x15301825 */ - 8.85919720756468632317e+03, /* 0x40C14D99, 0x3E18F46D */ - 3.70146267776887834771e+04, /* 0x40E212D4, 0x0E901566 */ -}; -#ifdef __STDC__ -static const double qS8[6] = { -#else -static double qS8[6] = { -#endif - 1.63776026895689824414e+02, /* 0x406478D5, 0x365B39BC */ - 8.09834494656449805916e+03, /* 0x40BFA258, 0x4E6B0563 */ - 1.42538291419120476348e+05, /* 0x41016652, 0x54D38C3F */ - 8.03309257119514397345e+05, /* 0x412883DA, 0x83A52B43 */ - 8.40501579819060512818e+05, /* 0x4129A66B, 0x28DE0B3D */ - -3.43899293537866615225e+05, /* 0xC114FD6D, 0x2C9530C5 */ -}; - -#ifdef __STDC__ -static const double qR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ -#else -static double qR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ -#endif - 1.84085963594515531381e-11, /* 0x3DB43D8F, 0x29CC8CD9 */ - 7.32421766612684765896e-02, /* 0x3FB2BFFF, 0xD172B04C */ - 5.83563508962056953777e+00, /* 0x401757B0, 0xB9953DD3 */ - 1.35111577286449829671e+02, /* 0x4060E392, 0x0A8788E9 */ - 1.02724376596164097464e+03, /* 0x40900CF9, 0x9DC8C481 */ - 1.98997785864605384631e+03, /* 0x409F17E9, 0x53C6E3A6 */ -}; -#ifdef __STDC__ -static const double qS5[6] = { -#else -static double qS5[6] = { -#endif - 8.27766102236537761883e+01, /* 0x4054B1B3, 0xFB5E1543 */ - 2.07781416421392987104e+03, /* 0x40A03BA0, 0xDA21C0CE */ - 1.88472887785718085070e+04, /* 0x40D267D2, 0x7B591E6D */ - 5.67511122894947329769e+04, /* 0x40EBB5E3, 0x97E02372 */ - 3.59767538425114471465e+04, /* 0x40E19118, 0x1F7A54A0 */ - -5.35434275601944773371e+03, /* 0xC0B4EA57, 0xBEDBC609 */ -}; - -#ifdef __STDC__ -static const double qR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ -#else -static double qR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ -#endif - 4.37741014089738620906e-09, /* 0x3E32CD03, 0x6ADECB82 */ - 7.32411180042911447163e-02, /* 0x3FB2BFEE, 0x0E8D0842 */ - 3.34423137516170720929e+00, /* 0x400AC0FC, 0x61149CF5 */ - 4.26218440745412650017e+01, /* 0x40454F98, 0x962DAEDD */ - 1.70808091340565596283e+02, /* 0x406559DB, 0xE25EFD1F */ - 1.66733948696651168575e+02, /* 0x4064D77C, 0x81FA21E0 */ -}; -#ifdef __STDC__ -static const double qS3[6] = { -#else -static double qS3[6] = { -#endif - 4.87588729724587182091e+01, /* 0x40486122, 0xBFE343A6 */ - 7.09689221056606015736e+02, /* 0x40862D83, 0x86544EB3 */ - 3.70414822620111362994e+03, /* 0x40ACF04B, 0xE44DFC63 */ - 6.46042516752568917582e+03, /* 0x40B93C6C, 0xD7C76A28 */ - 2.51633368920368957333e+03, /* 0x40A3A8AA, 0xD94FB1C0 */ - -1.49247451836156386662e+02, /* 0xC062A7EB, 0x201CF40F */ -}; - -#ifdef __STDC__ -static const double qR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ -#else -static double qR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ -#endif - 1.50444444886983272379e-07, /* 0x3E84313B, 0x54F76BDB */ - 7.32234265963079278272e-02, /* 0x3FB2BEC5, 0x3E883E34 */ - 1.99819174093815998816e+00, /* 0x3FFFF897, 0xE727779C */ - 1.44956029347885735348e+01, /* 0x402CFDBF, 0xAAF96FE5 */ - 3.16662317504781540833e+01, /* 0x403FAA8E, 0x29FBDC4A */ - 1.62527075710929267416e+01, /* 0x403040B1, 0x71814BB4 */ -}; -#ifdef __STDC__ -static const double qS2[6] = { -#else -static double qS2[6] = { -#endif - 3.03655848355219184498e+01, /* 0x403E5D96, 0xF7C07AED */ - 2.69348118608049844624e+02, /* 0x4070D591, 0xE4D14B40 */ - 8.44783757595320139444e+02, /* 0x408A6645, 0x22B3BF22 */ - 8.82935845112488550512e+02, /* 0x408B977C, 0x9C5CC214 */ - 2.12666388511798828631e+02, /* 0x406A9553, 0x0E001365 */ - -5.31095493882666946917e+00, /* 0xC0153E6A, 0xF8B32931 */ -}; - -#ifdef __STDC__ - static double qzero(double x) -#else - static double qzero(x) - double x; -#endif -{ -#ifdef __STDC__ - const double *p,*q; -#else - double *p,*q; -#endif - fd_twoints u; - double s,r,z; - int ix; - u.d = x; - ix = 0x7fffffff&__HI(u); - if(ix>=0x40200000) {p = qR8; q= qS8;} - else if(ix>=0x40122E8B){p = qR5; q= qS5;} - else if(ix>=0x4006DB6D){p = qR3; q= qS3;} - else if(ix>=0x40000000){p = qR2; q= qS2;} - z = one/(x*x); - r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5])))); - s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5]))))); - return (-.125 + r/s)/x; -} diff --git a/js/src/fdlibm/e_j1.c b/js/src/fdlibm/e_j1.c deleted file mode 100644 index 8982ac86a383..000000000000 --- a/js/src/fdlibm/e_j1.c +++ /dev/null @@ -1,523 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_j1.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* __ieee754_j1(x), __ieee754_y1(x) - * Bessel function of the first and second kinds of order zero. - * Method -- j1(x): - * 1. For tiny x, we use j1(x) = x/2 - x^3/16 + x^5/384 - ... - * 2. Reduce x to |x| since j1(x)=-j1(-x), and - * for x in (0,2) - * j1(x) = x/2 + x*z*R0/S0, where z = x*x; - * (precision: |j1/x - 1/2 - R0/S0 |<2**-61.51 ) - * for x in (2,inf) - * j1(x) = sqrt(2/(pi*x))*(p1(x)*cos(x1)-q1(x)*sin(x1)) - * y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x1)+q1(x)*cos(x1)) - * where x1 = x-3*pi/4. It is better to compute sin(x1),cos(x1) - * as follow: - * cos(x1) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4) - * = 1/sqrt(2) * (sin(x) - cos(x)) - * sin(x1) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4) - * = -1/sqrt(2) * (sin(x) + cos(x)) - * (To avoid cancellation, use - * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) - * to compute the worse one.) - * - * 3 Special cases - * j1(nan)= nan - * j1(0) = 0 - * j1(inf) = 0 - * - * Method -- y1(x): - * 1. screen out x<=0 cases: y1(0)=-inf, y1(x<0)=NaN - * 2. For x<2. - * Since - * y1(x) = 2/pi*(j1(x)*(ln(x/2)+Euler)-1/x-x/2+5/64*x^3-...) - * therefore y1(x)-2/pi*j1(x)*ln(x)-1/x is an odd function. - * We use the following function to approximate y1, - * y1(x) = x*U(z)/V(z) + (2/pi)*(j1(x)*ln(x)-1/x), z= x^2 - * where for x in [0,2] (abs err less than 2**-65.89) - * U(z) = U0[0] + U0[1]*z + ... + U0[4]*z^4 - * V(z) = 1 + v0[0]*z + ... + v0[4]*z^5 - * Note: For tiny x, 1/x dominate y1 and hence - * y1(tiny) = -2/pi/tiny, (choose tiny<2**-54) - * 3. For x>=2. - * y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x1)+q1(x)*cos(x1)) - * where x1 = x-3*pi/4. It is better to compute sin(x1),cos(x1) - * by method mentioned above. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static double pone(double), qone(double); -#else -static double pone(), qone(); -#endif - -#ifdef __STDC__ -static const double -#else -static double -#endif -really_big = 1e300, -one = 1.0, -invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */ -tpi = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ - /* R0/S0 on [0,2] */ -r00 = -6.25000000000000000000e-02, /* 0xBFB00000, 0x00000000 */ -r01 = 1.40705666955189706048e-03, /* 0x3F570D9F, 0x98472C61 */ -r02 = -1.59955631084035597520e-05, /* 0xBEF0C5C6, 0xBA169668 */ -r03 = 4.96727999609584448412e-08, /* 0x3E6AAAFA, 0x46CA0BD9 */ -s01 = 1.91537599538363460805e-02, /* 0x3F939D0B, 0x12637E53 */ -s02 = 1.85946785588630915560e-04, /* 0x3F285F56, 0xB9CDF664 */ -s03 = 1.17718464042623683263e-06, /* 0x3EB3BFF8, 0x333F8498 */ -s04 = 5.04636257076217042715e-09, /* 0x3E35AC88, 0xC97DFF2C */ -s05 = 1.23542274426137913908e-11; /* 0x3DAB2ACF, 0xCFB97ED8 */ - -static double zero = 0.0; - -#ifdef __STDC__ - double __ieee754_j1(double x) -#else - double __ieee754_j1(x) - double x; -#endif -{ - fd_twoints un; - double z, s,c,ss,cc,r,u,v,y; - int hx,ix; - - un.d = x; - hx = __HI(un); - ix = hx&0x7fffffff; - if(ix>=0x7ff00000) return one/x; - y = fd_fabs(x); - if(ix >= 0x40000000) { /* |x| >= 2.0 */ - s = fd_sin(y); - c = fd_cos(y); - ss = -s-c; - cc = s-c; - if(ix<0x7fe00000) { /* make sure y+y not overflow */ - z = fd_cos(y+y); - if ((s*c)>zero) cc = z/ss; - else ss = z/cc; - } - /* - * j1(x) = 1/sqrt(pi) * (P(1,x)*cc - Q(1,x)*ss) / sqrt(x) - * y1(x) = 1/sqrt(pi) * (P(1,x)*ss + Q(1,x)*cc) / sqrt(x) - */ - if(ix>0x48000000) z = (invsqrtpi*cc)/fd_sqrt(y); - else { - u = pone(y); v = qone(y); - z = invsqrtpi*(u*cc-v*ss)/fd_sqrt(y); - } - if(hx<0) return -z; - else return z; - } - if(ix<0x3e400000) { /* |x|<2**-27 */ - if(really_big+x>one) return 0.5*x;/* inexact if x!=0 necessary */ - } - z = x*x; - r = z*(r00+z*(r01+z*(r02+z*r03))); - s = one+z*(s01+z*(s02+z*(s03+z*(s04+z*s05)))); - r *= x; - return(x*0.5+r/s); -} - -#ifdef __STDC__ -static const double U0[5] = { -#else -static double U0[5] = { -#endif - -1.96057090646238940668e-01, /* 0xBFC91866, 0x143CBC8A */ - 5.04438716639811282616e-02, /* 0x3FA9D3C7, 0x76292CD1 */ - -1.91256895875763547298e-03, /* 0xBF5F55E5, 0x4844F50F */ - 2.35252600561610495928e-05, /* 0x3EF8AB03, 0x8FA6B88E */ - -9.19099158039878874504e-08, /* 0xBE78AC00, 0x569105B8 */ -}; -#ifdef __STDC__ -static const double V0[5] = { -#else -static double V0[5] = { -#endif - 1.99167318236649903973e-02, /* 0x3F94650D, 0x3F4DA9F0 */ - 2.02552581025135171496e-04, /* 0x3F2A8C89, 0x6C257764 */ - 1.35608801097516229404e-06, /* 0x3EB6C05A, 0x894E8CA6 */ - 6.22741452364621501295e-09, /* 0x3E3ABF1D, 0x5BA69A86 */ - 1.66559246207992079114e-11, /* 0x3DB25039, 0xDACA772A */ -}; - -#ifdef __STDC__ - double __ieee754_y1(double x) -#else - double __ieee754_y1(x) - double x; -#endif -{ - fd_twoints un; - double z, s,c,ss,cc,u,v; - int hx,ix,lx; - - un.d = x; - hx = __HI(un); - ix = 0x7fffffff&hx; - lx = __LO(un); - /* if Y1(NaN) is NaN, Y1(-inf) is NaN, Y1(inf) is 0 */ - if(ix>=0x7ff00000) return one/(x+x*x); - if((ix|lx)==0) return -one/zero; - if(hx<0) return zero/zero; - if(ix >= 0x40000000) { /* |x| >= 2.0 */ - s = fd_sin(x); - c = fd_cos(x); - ss = -s-c; - cc = s-c; - if(ix<0x7fe00000) { /* make sure x+x not overflow */ - z = fd_cos(x+x); - if ((s*c)>zero) cc = z/ss; - else ss = z/cc; - } - /* y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x0)+q1(x)*cos(x0)) - * where x0 = x-3pi/4 - * Better formula: - * cos(x0) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4) - * = 1/sqrt(2) * (sin(x) - cos(x)) - * sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4) - * = -1/sqrt(2) * (cos(x) + sin(x)) - * To avoid cancellation, use - * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) - * to compute the worse one. - */ - if(ix>0x48000000) z = (invsqrtpi*ss)/fd_sqrt(x); - else { - u = pone(x); v = qone(x); - z = invsqrtpi*(u*ss+v*cc)/fd_sqrt(x); - } - return z; - } - if(ix<=0x3c900000) { /* x < 2**-54 */ - return(-tpi/x); - } - z = x*x; - u = U0[0]+z*(U0[1]+z*(U0[2]+z*(U0[3]+z*U0[4]))); - v = one+z*(V0[0]+z*(V0[1]+z*(V0[2]+z*(V0[3]+z*V0[4])))); - return(x*(u/v) + tpi*(__ieee754_j1(x)*__ieee754_log(x)-one/x)); -} - -/* For x >= 8, the asymptotic expansions of pone is - * 1 + 15/128 s^2 - 4725/2^15 s^4 - ..., where s = 1/x. - * We approximate pone by - * pone(x) = 1 + (R/S) - * where R = pr0 + pr1*s^2 + pr2*s^4 + ... + pr5*s^10 - * S = 1 + ps0*s^2 + ... + ps4*s^10 - * and - * | pone(x)-1-R/S | <= 2 ** ( -60.06) - */ - -#ifdef __STDC__ -static const double pr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ -#else -static double pr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ -#endif - 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ - 1.17187499999988647970e-01, /* 0x3FBDFFFF, 0xFFFFFCCE */ - 1.32394806593073575129e+01, /* 0x402A7A9D, 0x357F7FCE */ - 4.12051854307378562225e+02, /* 0x4079C0D4, 0x652EA590 */ - 3.87474538913960532227e+03, /* 0x40AE457D, 0xA3A532CC */ - 7.91447954031891731574e+03, /* 0x40BEEA7A, 0xC32782DD */ -}; -#ifdef __STDC__ -static const double ps8[5] = { -#else -static double ps8[5] = { -#endif - 1.14207370375678408436e+02, /* 0x405C8D45, 0x8E656CAC */ - 3.65093083420853463394e+03, /* 0x40AC85DC, 0x964D274F */ - 3.69562060269033463555e+04, /* 0x40E20B86, 0x97C5BB7F */ - 9.76027935934950801311e+04, /* 0x40F7D42C, 0xB28F17BB */ - 3.08042720627888811578e+04, /* 0x40DE1511, 0x697A0B2D */ -}; - -#ifdef __STDC__ -static const double pr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ -#else -static double pr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ -#endif - 1.31990519556243522749e-11, /* 0x3DAD0667, 0xDAE1CA7D */ - 1.17187493190614097638e-01, /* 0x3FBDFFFF, 0xE2C10043 */ - 6.80275127868432871736e+00, /* 0x401B3604, 0x6E6315E3 */ - 1.08308182990189109773e+02, /* 0x405B13B9, 0x452602ED */ - 5.17636139533199752805e+02, /* 0x40802D16, 0xD052D649 */ - 5.28715201363337541807e+02, /* 0x408085B8, 0xBB7E0CB7 */ -}; -#ifdef __STDC__ -static const double ps5[5] = { -#else -static double ps5[5] = { -#endif - 5.92805987221131331921e+01, /* 0x404DA3EA, 0xA8AF633D */ - 9.91401418733614377743e+02, /* 0x408EFB36, 0x1B066701 */ - 5.35326695291487976647e+03, /* 0x40B4E944, 0x5706B6FB */ - 7.84469031749551231769e+03, /* 0x40BEA4B0, 0xB8A5BB15 */ - 1.50404688810361062679e+03, /* 0x40978030, 0x036F5E51 */ -}; - -#ifdef __STDC__ -static const double pr3[6] = { -#else -static double pr3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ -#endif - 3.02503916137373618024e-09, /* 0x3E29FC21, 0xA7AD9EDD */ - 1.17186865567253592491e-01, /* 0x3FBDFFF5, 0x5B21D17B */ - 3.93297750033315640650e+00, /* 0x400F76BC, 0xE85EAD8A */ - 3.51194035591636932736e+01, /* 0x40418F48, 0x9DA6D129 */ - 9.10550110750781271918e+01, /* 0x4056C385, 0x4D2C1837 */ - 4.85590685197364919645e+01, /* 0x4048478F, 0x8EA83EE5 */ -}; -#ifdef __STDC__ -static const double ps3[5] = { -#else -static double ps3[5] = { -#endif - 3.47913095001251519989e+01, /* 0x40416549, 0xA134069C */ - 3.36762458747825746741e+02, /* 0x40750C33, 0x07F1A75F */ - 1.04687139975775130551e+03, /* 0x40905B7C, 0x5037D523 */ - 8.90811346398256432622e+02, /* 0x408BD67D, 0xA32E31E9 */ - 1.03787932439639277504e+02, /* 0x4059F26D, 0x7C2EED53 */ -}; - -#ifdef __STDC__ -static const double pr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ -#else -static double pr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ -#endif - 1.07710830106873743082e-07, /* 0x3E7CE9D4, 0xF65544F4 */ - 1.17176219462683348094e-01, /* 0x3FBDFF42, 0xBE760D83 */ - 2.36851496667608785174e+00, /* 0x4002F2B7, 0xF98FAEC0 */ - 1.22426109148261232917e+01, /* 0x40287C37, 0x7F71A964 */ - 1.76939711271687727390e+01, /* 0x4031B1A8, 0x177F8EE2 */ - 5.07352312588818499250e+00, /* 0x40144B49, 0xA574C1FE */ -}; -#ifdef __STDC__ -static const double ps2[5] = { -#else -static double ps2[5] = { -#endif - 2.14364859363821409488e+01, /* 0x40356FBD, 0x8AD5ECDC */ - 1.25290227168402751090e+02, /* 0x405F5293, 0x14F92CD5 */ - 2.32276469057162813669e+02, /* 0x406D08D8, 0xD5A2DBD9 */ - 1.17679373287147100768e+02, /* 0x405D6B7A, 0xDA1884A9 */ - 8.36463893371618283368e+00, /* 0x4020BAB1, 0xF44E5192 */ -}; - -#ifdef __STDC__ - static double pone(double x) -#else - static double pone(x) - double x; -#endif -{ -#ifdef __STDC__ - const double *p,*q; -#else - double *p,*q; -#endif - fd_twoints un; - double z,r,s; - int ix; - un.d = x; - ix = 0x7fffffff&__HI(un); - if(ix>=0x40200000) {p = pr8; q= ps8;} - else if(ix>=0x40122E8B){p = pr5; q= ps5;} - else if(ix>=0x4006DB6D){p = pr3; q= ps3;} - else if(ix>=0x40000000){p = pr2; q= ps2;} - z = one/(x*x); - r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5])))); - s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4])))); - return one+ r/s; -} - - -/* For x >= 8, the asymptotic expansions of qone is - * 3/8 s - 105/1024 s^3 - ..., where s = 1/x. - * We approximate pone by - * qone(x) = s*(0.375 + (R/S)) - * where R = qr1*s^2 + qr2*s^4 + ... + qr5*s^10 - * S = 1 + qs1*s^2 + ... + qs6*s^12 - * and - * | qone(x)/s -0.375-R/S | <= 2 ** ( -61.13) - */ - -#ifdef __STDC__ -static const double qr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ -#else -static double qr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ -#endif - 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ - -1.02539062499992714161e-01, /* 0xBFBA3FFF, 0xFFFFFDF3 */ - -1.62717534544589987888e+01, /* 0xC0304591, 0xA26779F7 */ - -7.59601722513950107896e+02, /* 0xC087BCD0, 0x53E4B576 */ - -1.18498066702429587167e+04, /* 0xC0C724E7, 0x40F87415 */ - -4.84385124285750353010e+04, /* 0xC0E7A6D0, 0x65D09C6A */ -}; -#ifdef __STDC__ -static const double qs8[6] = { -#else -static double qs8[6] = { -#endif - 1.61395369700722909556e+02, /* 0x40642CA6, 0xDE5BCDE5 */ - 7.82538599923348465381e+03, /* 0x40BE9162, 0xD0D88419 */ - 1.33875336287249578163e+05, /* 0x4100579A, 0xB0B75E98 */ - 7.19657723683240939863e+05, /* 0x4125F653, 0x72869C19 */ - 6.66601232617776375264e+05, /* 0x412457D2, 0x7719AD5C */ - -2.94490264303834643215e+05, /* 0xC111F969, 0x0EA5AA18 */ -}; - -#ifdef __STDC__ -static const double qr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ -#else -static double qr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ -#endif - -2.08979931141764104297e-11, /* 0xBDB6FA43, 0x1AA1A098 */ - -1.02539050241375426231e-01, /* 0xBFBA3FFF, 0xCB597FEF */ - -8.05644828123936029840e+00, /* 0xC0201CE6, 0xCA03AD4B */ - -1.83669607474888380239e+02, /* 0xC066F56D, 0x6CA7B9B0 */ - -1.37319376065508163265e+03, /* 0xC09574C6, 0x6931734F */ - -2.61244440453215656817e+03, /* 0xC0A468E3, 0x88FDA79D */ -}; -#ifdef __STDC__ -static const double qs5[6] = { -#else -static double qs5[6] = { -#endif - 8.12765501384335777857e+01, /* 0x405451B2, 0xFF5A11B2 */ - 1.99179873460485964642e+03, /* 0x409F1F31, 0xE77BF839 */ - 1.74684851924908907677e+04, /* 0x40D10F1F, 0x0D64CE29 */ - 4.98514270910352279316e+04, /* 0x40E8576D, 0xAABAD197 */ - 2.79480751638918118260e+04, /* 0x40DB4B04, 0xCF7C364B */ - -4.71918354795128470869e+03, /* 0xC0B26F2E, 0xFCFFA004 */ -}; - -#ifdef __STDC__ -static const double qr3[6] = { -#else -static double qr3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ -#endif - -5.07831226461766561369e-09, /* 0xBE35CFA9, 0xD38FC84F */ - -1.02537829820837089745e-01, /* 0xBFBA3FEB, 0x51AEED54 */ - -4.61011581139473403113e+00, /* 0xC01270C2, 0x3302D9FF */ - -5.78472216562783643212e+01, /* 0xC04CEC71, 0xC25D16DA */ - -2.28244540737631695038e+02, /* 0xC06C87D3, 0x4718D55F */ - -2.19210128478909325622e+02, /* 0xC06B66B9, 0x5F5C1BF6 */ -}; -#ifdef __STDC__ -static const double qs3[6] = { -#else -static double qs3[6] = { -#endif - 4.76651550323729509273e+01, /* 0x4047D523, 0xCCD367E4 */ - 6.73865112676699709482e+02, /* 0x40850EEB, 0xC031EE3E */ - 3.38015286679526343505e+03, /* 0x40AA684E, 0x448E7C9A */ - 5.54772909720722782367e+03, /* 0x40B5ABBA, 0xA61D54A6 */ - 1.90311919338810798763e+03, /* 0x409DBC7A, 0x0DD4DF4B */ - -1.35201191444307340817e+02, /* 0xC060E670, 0x290A311F */ -}; - -#ifdef __STDC__ -static const double qr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ -#else -static double qr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ -#endif - -1.78381727510958865572e-07, /* 0xBE87F126, 0x44C626D2 */ - -1.02517042607985553460e-01, /* 0xBFBA3E8E, 0x9148B010 */ - -2.75220568278187460720e+00, /* 0xC0060484, 0x69BB4EDA */ - -1.96636162643703720221e+01, /* 0xC033A9E2, 0xC168907F */ - -4.23253133372830490089e+01, /* 0xC04529A3, 0xDE104AAA */ - -2.13719211703704061733e+01, /* 0xC0355F36, 0x39CF6E52 */ -}; -#ifdef __STDC__ -static const double qs2[6] = { -#else -static double qs2[6] = { -#endif - 2.95333629060523854548e+01, /* 0x403D888A, 0x78AE64FF */ - 2.52981549982190529136e+02, /* 0x406F9F68, 0xDB821CBA */ - 7.57502834868645436472e+02, /* 0x4087AC05, 0xCE49A0F7 */ - 7.39393205320467245656e+02, /* 0x40871B25, 0x48D4C029 */ - 1.55949003336666123687e+02, /* 0x40637E5E, 0x3C3ED8D4 */ - -4.95949898822628210127e+00, /* 0xC013D686, 0xE71BE86B */ -}; - -#ifdef __STDC__ - static double qone(double x) -#else - static double qone(x) - double x; -#endif -{ -#ifdef __STDC__ - const double *p,*q; -#else - double *p,*q; -#endif - fd_twoints un; - double s,r,z; - int ix; - un.d = x; - ix = 0x7fffffff&__HI(un); - if(ix>=0x40200000) {p = qr8; q= qs8;} - else if(ix>=0x40122E8B){p = qr5; q= qs5;} - else if(ix>=0x4006DB6D){p = qr3; q= qs3;} - else if(ix>=0x40000000){p = qr2; q= qs2;} - z = one/(x*x); - r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5])))); - s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5]))))); - return (.375 + r/s)/x; -} diff --git a/js/src/fdlibm/e_jn.c b/js/src/fdlibm/e_jn.c deleted file mode 100644 index 2b61b44399df..000000000000 --- a/js/src/fdlibm/e_jn.c +++ /dev/null @@ -1,315 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_jn.c 1.4 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * __ieee754_jn(n, x), __ieee754_yn(n, x) - * floating point Bessel's function of the 1st and 2nd kind - * of order n - * - * Special cases: - * y0(0)=y1(0)=yn(n,0) = -inf with division by zero signal; - * y0(-ve)=y1(-ve)=yn(n,-ve) are NaN with invalid signal. - * Note 2. About jn(n,x), yn(n,x) - * For n=0, j0(x) is called, - * for n=1, j1(x) is called, - * for nx, a continued fraction approximation to - * j(n,x)/j(n-1,x) is evaluated and then backward - * recursion is used starting from a supposed value - * for j(n,x). The resulting value of j(0,x) is - * compared with the actual value to correct the - * supposed value of j(n,x). - * - * yn(n,x) is similar in all respects, except - * that forward recursion is used for all - * values of n>1. - * - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif -invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */ -two = 2.00000000000000000000e+00, /* 0x40000000, 0x00000000 */ -one = 1.00000000000000000000e+00; /* 0x3FF00000, 0x00000000 */ - -static double zero = 0.00000000000000000000e+00; - -#ifdef __STDC__ - double __ieee754_jn(int n, double x) -#else - double __ieee754_jn(n,x) - int n; double x; -#endif -{ - fd_twoints u; - int i,hx,ix,lx, sgn; - double a, b, temp, di; - double z, w; - - /* J(-n,x) = (-1)^n * J(n, x), J(n, -x) = (-1)^n * J(n, x) - * Thus, J(-n,x) = J(n,-x) - */ - u.d = x; - hx = __HI(u); - ix = 0x7fffffff&hx; - lx = __LO(u); - /* if J(n,NaN) is NaN */ - if((ix|((unsigned)(lx|-lx))>>31)>0x7ff00000) return x+x; - if(n<0){ - n = -n; - x = -x; - hx ^= 0x80000000; - } - if(n==0) return(__ieee754_j0(x)); - if(n==1) return(__ieee754_j1(x)); - sgn = (n&1)&(hx>>31); /* even n -- 0, odd n -- sign(x) */ - x = fd_fabs(x); - if((ix|lx)==0||ix>=0x7ff00000) /* if x is 0 or inf */ - b = zero; - else if((double)n<=x) { - /* Safe to use J(n+1,x)=2n/x *J(n,x)-J(n-1,x) */ - if(ix>=0x52D00000) { /* x > 2**302 */ - /* (x >> n**2) - * Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi) - * Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi) - * Let s=sin(x), c=cos(x), - * xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then - * - * n sin(xn)*sqt2 cos(xn)*sqt2 - * ---------------------------------- - * 0 s-c c+s - * 1 -s-c -c+s - * 2 -s+c -c-s - * 3 s+c c-s - */ - switch(n&3) { - case 0: temp = fd_cos(x)+fd_sin(x); break; - case 1: temp = -fd_cos(x)+fd_sin(x); break; - case 2: temp = -fd_cos(x)-fd_sin(x); break; - case 3: temp = fd_cos(x)-fd_sin(x); break; - } - b = invsqrtpi*temp/fd_sqrt(x); - } else { - a = __ieee754_j0(x); - b = __ieee754_j1(x); - for(i=1;i33) /* underflow */ - b = zero; - else { - temp = x*0.5; b = temp; - for (a=one,i=2;i<=n;i++) { - a *= (double)i; /* a = n! */ - b *= temp; /* b = (x/2)^n */ - } - b = b/a; - } - } else { - /* use backward recurrence */ - /* x x^2 x^2 - * J(n,x)/J(n-1,x) = ---- ------ ------ ..... - * 2n - 2(n+1) - 2(n+2) - * - * 1 1 1 - * (for large x) = ---- ------ ------ ..... - * 2n 2(n+1) 2(n+2) - * -- - ------ - ------ - - * x x x - * - * Let w = 2n/x and h=2/x, then the above quotient - * is equal to the continued fraction: - * 1 - * = ----------------------- - * 1 - * w - ----------------- - * 1 - * w+h - --------- - * w+2h - ... - * - * To determine how many terms needed, let - * Q(0) = w, Q(1) = w(w+h) - 1, - * Q(k) = (w+k*h)*Q(k-1) - Q(k-2), - * When Q(k) > 1e4 good for single - * When Q(k) > 1e9 good for double - * When Q(k) > 1e17 good for quadruple - */ - /* determine k */ - double t,v; - double q0,q1,h,tmp; int k,m; - w = (n+n)/(double)x; h = 2.0/(double)x; - q0 = w; z = w+h; q1 = w*z - 1.0; k=1; - while(q1<1.0e9) { - k += 1; z += h; - tmp = z*q1 - q0; - q0 = q1; - q1 = tmp; - } - m = n+n; - for(t=zero, i = 2*(n+k); i>=m; i -= 2) t = one/(i/x-t); - a = t; - b = one; - /* estimate log((2/x)^n*n!) = n*log(2/x)+n*ln(n) - * Hence, if n*(log(2n/x)) > ... - * single 8.8722839355e+01 - * double 7.09782712893383973096e+02 - * long double 1.1356523406294143949491931077970765006170e+04 - * then recurrent value may overflow and the result is - * likely underflow to zero - */ - tmp = n; - v = two/x; - tmp = tmp*__ieee754_log(fd_fabs(v*tmp)); - if(tmp<7.09782712893383973096e+02) { - for(i=n-1,di=(double)(i+i);i>0;i--){ - temp = b; - b *= di; - b = b/x - a; - a = temp; - di -= two; - } - } else { - for(i=n-1,di=(double)(i+i);i>0;i--){ - temp = b; - b *= di; - b = b/x - a; - a = temp; - di -= two; - /* scale b to avoid spurious overflow */ - if(b>1e100) { - a /= b; - t /= b; - b = one; - } - } - } - b = (t*__ieee754_j0(x)/b); - } - } - if(sgn==1) return -b; else return b; -} - -#ifdef __STDC__ - double __ieee754_yn(int n, double x) -#else - double __ieee754_yn(n,x) - int n; double x; -#endif -{ - fd_twoints u; - int i,hx,ix,lx; - int sign; - double a, b, temp; - - u.d = x; - hx = __HI(u); - ix = 0x7fffffff&hx; - lx = __LO(u); - /* if Y(n,NaN) is NaN */ - if((ix|((unsigned)(lx|-lx))>>31)>0x7ff00000) return x+x; - if((ix|lx)==0) return -one/zero; - if(hx<0) return zero/zero; - sign = 1; - if(n<0){ - n = -n; - sign = 1 - ((n&1)<<1); - } - if(n==0) return(__ieee754_y0(x)); - if(n==1) return(sign*__ieee754_y1(x)); - if(ix==0x7ff00000) return zero; - if(ix>=0x52D00000) { /* x > 2**302 */ - /* (x >> n**2) - * Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi) - * Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi) - * Let s=sin(x), c=cos(x), - * xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then - * - * n sin(xn)*sqt2 cos(xn)*sqt2 - * ---------------------------------- - * 0 s-c c+s - * 1 -s-c -c+s - * 2 -s+c -c-s - * 3 s+c c-s - */ - switch(n&3) { - case 0: temp = fd_sin(x)-fd_cos(x); break; - case 1: temp = -fd_sin(x)-fd_cos(x); break; - case 2: temp = -fd_sin(x)+fd_cos(x); break; - case 3: temp = fd_sin(x)+fd_cos(x); break; - } - b = invsqrtpi*temp/fd_sqrt(x); - } else { - a = __ieee754_y0(x); - b = __ieee754_y1(x); - /* quit if b is -inf */ - u.d = b; - for(i=1;i0) return b; else return -b; -} diff --git a/js/src/fdlibm/e_lgamma.c b/js/src/fdlibm/e_lgamma.c deleted file mode 100644 index beb3bd932191..000000000000 --- a/js/src/fdlibm/e_lgamma.c +++ /dev/null @@ -1,71 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_lgamma.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - * - */ - -/* __ieee754_lgamma(x) - * Return the logarithm of the Gamma function of x. - * - * Method: call __ieee754_lgamma_r - */ - -#include "fdlibm.h" - -extern int signgam; - -#ifdef __STDC__ - double __ieee754_lgamma(double x) -#else - double __ieee754_lgamma(x) - double x; -#endif -{ - return __ieee754_lgamma_r(x,&signgam); -} diff --git a/js/src/fdlibm/e_lgamma_r.c b/js/src/fdlibm/e_lgamma_r.c deleted file mode 100644 index df92e7a26c9d..000000000000 --- a/js/src/fdlibm/e_lgamma_r.c +++ /dev/null @@ -1,347 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_lgamma_r.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - * - */ - -/* __ieee754_lgamma_r(x, signgamp) - * Reentrant version of the logarithm of the Gamma function - * with user provide pointer for the sign of Gamma(x). - * - * Method: - * 1. Argument Reduction for 0 < x <= 8 - * Since gamma(1+s)=s*gamma(s), for x in [0,8], we may - * reduce x to a number in [1.5,2.5] by - * lgamma(1+s) = log(s) + lgamma(s) - * for example, - * lgamma(7.3) = log(6.3) + lgamma(6.3) - * = log(6.3*5.3) + lgamma(5.3) - * = log(6.3*5.3*4.3*3.3*2.3) + lgamma(2.3) - * 2. Polynomial approximation of lgamma around its - * minimun ymin=1.461632144968362245 to maintain monotonicity. - * On [ymin-0.23, ymin+0.27] (i.e., [1.23164,1.73163]), use - * Let z = x-ymin; - * lgamma(x) = -1.214862905358496078218 + z^2*poly(z) - * where - * poly(z) is a 14 degree polynomial. - * 2. Rational approximation in the primary interval [2,3] - * We use the following approximation: - * s = x-2.0; - * lgamma(x) = 0.5*s + s*P(s)/Q(s) - * with accuracy - * |P/Q - (lgamma(x)-0.5s)| < 2**-61.71 - * Our algorithms are based on the following observation - * - * zeta(2)-1 2 zeta(3)-1 3 - * lgamma(2+s) = s*(1-Euler) + --------- * s - --------- * s + ... - * 2 3 - * - * where Euler = 0.5771... is the Euler constant, which is very - * close to 0.5. - * - * 3. For x>=8, we have - * lgamma(x)~(x-0.5)log(x)-x+0.5*log(2pi)+1/(12x)-1/(360x**3)+.... - * (better formula: - * lgamma(x)~(x-0.5)*(log(x)-1)-.5*(log(2pi)-1) + ...) - * Let z = 1/x, then we approximation - * f(z) = lgamma(x) - (x-0.5)(log(x)-1) - * by - * 3 5 11 - * w = w0 + w1*z + w2*z + w3*z + ... + w6*z - * where - * |w - f(z)| < 2**-58.74 - * - * 4. For negative x, since (G is gamma function) - * -x*G(-x)*G(x) = pi/sin(pi*x), - * we have - * G(x) = pi/(sin(pi*x)*(-x)*G(-x)) - * since G(-x) is positive, sign(G(x)) = sign(sin(pi*x)) for x<0 - * Hence, for x<0, signgam = sign(sin(pi*x)) and - * lgamma(x) = log(|Gamma(x)|) - * = log(pi/(|x*sin(pi*x)|)) - lgamma(-x); - * Note: one should avoid compute pi*(-x) directly in the - * computation of sin(pi*(-x)). - * - * 5. Special Cases - * lgamma(2+s) ~ s*(1-Euler) for tiny s - * lgamma(1)=lgamma(2)=0 - * lgamma(x) ~ -log(x) for tiny x - * lgamma(0) = lgamma(inf) = inf - * lgamma(-integer) = +-inf - * - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif -two52= 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ -half= 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */ -one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ -pi = 3.14159265358979311600e+00, /* 0x400921FB, 0x54442D18 */ -a0 = 7.72156649015328655494e-02, /* 0x3FB3C467, 0xE37DB0C8 */ -a1 = 3.22467033424113591611e-01, /* 0x3FD4A34C, 0xC4A60FAD */ -a2 = 6.73523010531292681824e-02, /* 0x3FB13E00, 0x1A5562A7 */ -a3 = 2.05808084325167332806e-02, /* 0x3F951322, 0xAC92547B */ -a4 = 7.38555086081402883957e-03, /* 0x3F7E404F, 0xB68FEFE8 */ -a5 = 2.89051383673415629091e-03, /* 0x3F67ADD8, 0xCCB7926B */ -a6 = 1.19270763183362067845e-03, /* 0x3F538A94, 0x116F3F5D */ -a7 = 5.10069792153511336608e-04, /* 0x3F40B6C6, 0x89B99C00 */ -a8 = 2.20862790713908385557e-04, /* 0x3F2CF2EC, 0xED10E54D */ -a9 = 1.08011567247583939954e-04, /* 0x3F1C5088, 0x987DFB07 */ -a10 = 2.52144565451257326939e-05, /* 0x3EFA7074, 0x428CFA52 */ -a11 = 4.48640949618915160150e-05, /* 0x3F07858E, 0x90A45837 */ -tc = 1.46163214496836224576e+00, /* 0x3FF762D8, 0x6356BE3F */ -tf = -1.21486290535849611461e-01, /* 0xBFBF19B9, 0xBCC38A42 */ -/* tt = -(tail of tf) */ -tt = -3.63867699703950536541e-18, /* 0xBC50C7CA, 0xA48A971F */ -t0 = 4.83836122723810047042e-01, /* 0x3FDEF72B, 0xC8EE38A2 */ -t1 = -1.47587722994593911752e-01, /* 0xBFC2E427, 0x8DC6C509 */ -t2 = 6.46249402391333854778e-02, /* 0x3FB08B42, 0x94D5419B */ -t3 = -3.27885410759859649565e-02, /* 0xBFA0C9A8, 0xDF35B713 */ -t4 = 1.79706750811820387126e-02, /* 0x3F9266E7, 0x970AF9EC */ -t5 = -1.03142241298341437450e-02, /* 0xBF851F9F, 0xBA91EC6A */ -t6 = 6.10053870246291332635e-03, /* 0x3F78FCE0, 0xE370E344 */ -t7 = -3.68452016781138256760e-03, /* 0xBF6E2EFF, 0xB3E914D7 */ -t8 = 2.25964780900612472250e-03, /* 0x3F6282D3, 0x2E15C915 */ -t9 = -1.40346469989232843813e-03, /* 0xBF56FE8E, 0xBF2D1AF1 */ -t10 = 8.81081882437654011382e-04, /* 0x3F4CDF0C, 0xEF61A8E9 */ -t11 = -5.38595305356740546715e-04, /* 0xBF41A610, 0x9C73E0EC */ -t12 = 3.15632070903625950361e-04, /* 0x3F34AF6D, 0x6C0EBBF7 */ -t13 = -3.12754168375120860518e-04, /* 0xBF347F24, 0xECC38C38 */ -t14 = 3.35529192635519073543e-04, /* 0x3F35FD3E, 0xE8C2D3F4 */ -u0 = -7.72156649015328655494e-02, /* 0xBFB3C467, 0xE37DB0C8 */ -u1 = 6.32827064025093366517e-01, /* 0x3FE4401E, 0x8B005DFF */ -u2 = 1.45492250137234768737e+00, /* 0x3FF7475C, 0xD119BD6F */ -u3 = 9.77717527963372745603e-01, /* 0x3FEF4976, 0x44EA8450 */ -u4 = 2.28963728064692451092e-01, /* 0x3FCD4EAE, 0xF6010924 */ -u5 = 1.33810918536787660377e-02, /* 0x3F8B678B, 0xBF2BAB09 */ -v1 = 2.45597793713041134822e+00, /* 0x4003A5D7, 0xC2BD619C */ -v2 = 2.12848976379893395361e+00, /* 0x40010725, 0xA42B18F5 */ -v3 = 7.69285150456672783825e-01, /* 0x3FE89DFB, 0xE45050AF */ -v4 = 1.04222645593369134254e-01, /* 0x3FBAAE55, 0xD6537C88 */ -v5 = 3.21709242282423911810e-03, /* 0x3F6A5ABB, 0x57D0CF61 */ -s0 = -7.72156649015328655494e-02, /* 0xBFB3C467, 0xE37DB0C8 */ -s1 = 2.14982415960608852501e-01, /* 0x3FCB848B, 0x36E20878 */ -s2 = 3.25778796408930981787e-01, /* 0x3FD4D98F, 0x4F139F59 */ -s3 = 1.46350472652464452805e-01, /* 0x3FC2BB9C, 0xBEE5F2F7 */ -s4 = 2.66422703033638609560e-02, /* 0x3F9B481C, 0x7E939961 */ -s5 = 1.84028451407337715652e-03, /* 0x3F5E26B6, 0x7368F239 */ -s6 = 3.19475326584100867617e-05, /* 0x3F00BFEC, 0xDD17E945 */ -r1 = 1.39200533467621045958e+00, /* 0x3FF645A7, 0x62C4AB74 */ -r2 = 7.21935547567138069525e-01, /* 0x3FE71A18, 0x93D3DCDC */ -r3 = 1.71933865632803078993e-01, /* 0x3FC601ED, 0xCCFBDF27 */ -r4 = 1.86459191715652901344e-02, /* 0x3F9317EA, 0x742ED475 */ -r5 = 7.77942496381893596434e-04, /* 0x3F497DDA, 0xCA41A95B */ -r6 = 7.32668430744625636189e-06, /* 0x3EDEBAF7, 0xA5B38140 */ -w0 = 4.18938533204672725052e-01, /* 0x3FDACFE3, 0x90C97D69 */ -w1 = 8.33333333333329678849e-02, /* 0x3FB55555, 0x5555553B */ -w2 = -2.77777777728775536470e-03, /* 0xBF66C16C, 0x16B02E5C */ -w3 = 7.93650558643019558500e-04, /* 0x3F4A019F, 0x98CF38B6 */ -w4 = -5.95187557450339963135e-04, /* 0xBF4380CB, 0x8C0FE741 */ -w5 = 8.36339918996282139126e-04, /* 0x3F4B67BA, 0x4CDAD5D1 */ -w6 = -1.63092934096575273989e-03; /* 0xBF5AB89D, 0x0B9E43E4 */ - -static double zero= 0.00000000000000000000e+00; - -#ifdef __STDC__ - static double sin_pi(double x) -#else - static double sin_pi(x) - double x; -#endif -{ - fd_twoints u; - double y,z; - int n,ix; - - u.d = x; - ix = 0x7fffffff&__HI(u); - - if(ix<0x3fd00000) return __kernel_sin(pi*x,zero,0); - y = -x; /* x is assume negative */ - - /* - * argument reduction, make sure inexact flag not raised if input - * is an integer - */ - z = fd_floor(y); - if(z!=y) { /* inexact anyway */ - y *= 0.5; - y = 2.0*(y - fd_floor(y)); /* y = |x| mod 2.0 */ - n = (int) (y*4.0); - } else { - if(ix>=0x43400000) { - y = zero; n = 0; /* y must be even */ - } else { - if(ix<0x43300000) z = y+two52; /* exact */ - u.d = z; - n = __LO(u)&1; /* lower word of z */ - y = n; - n<<= 2; - } - } - switch (n) { - case 0: y = __kernel_sin(pi*y,zero,0); break; - case 1: - case 2: y = __kernel_cos(pi*(0.5-y),zero); break; - case 3: - case 4: y = __kernel_sin(pi*(one-y),zero,0); break; - case 5: - case 6: y = -__kernel_cos(pi*(y-1.5),zero); break; - default: y = __kernel_sin(pi*(y-2.0),zero,0); break; - } - return -y; -} - - -#ifdef __STDC__ - double __ieee754_lgamma_r(double x, int *signgamp) -#else - double __ieee754_lgamma_r(x,signgamp) - double x; int *signgamp; -#endif -{ - fd_twoints u; - double t,y,z,nadj,p,p1,p2,p3,q,r,w; - int i,hx,lx,ix; - - u.d = x; - hx = __HI(u); - lx = __LO(u); - - /* purge off +-inf, NaN, +-0, and negative arguments */ - *signgamp = 1; - ix = hx&0x7fffffff; - if(ix>=0x7ff00000) return x*x; - if((ix|lx)==0) return one/zero; - if(ix<0x3b900000) { /* |x|<2**-70, return -log(|x|) */ - if(hx<0) { - *signgamp = -1; - return -__ieee754_log(-x); - } else return -__ieee754_log(x); - } - if(hx<0) { - if(ix>=0x43300000) /* |x|>=2**52, must be -integer */ - return one/zero; - t = sin_pi(x); - if(t==zero) return one/zero; /* -integer */ - nadj = __ieee754_log(pi/fd_fabs(t*x)); - if(t=0x3FE76944) {y = one-x; i= 0;} - else if(ix>=0x3FCDA661) {y= x-(tc-one); i=1;} - else {y = x; i=2;} - } else { - r = zero; - if(ix>=0x3FFBB4C3) {y=2.0-x;i=0;} /* [1.7316,2] */ - else if(ix>=0x3FF3B4C4) {y=x-tc;i=1;} /* [1.23,1.73] */ - else {y=x-one;i=2;} - } - switch(i) { - case 0: - z = y*y; - p1 = a0+z*(a2+z*(a4+z*(a6+z*(a8+z*a10)))); - p2 = z*(a1+z*(a3+z*(a5+z*(a7+z*(a9+z*a11))))); - p = y*p1+p2; - r += (p-0.5*y); break; - case 1: - z = y*y; - w = z*y; - p1 = t0+w*(t3+w*(t6+w*(t9 +w*t12))); /* parallel comp */ - p2 = t1+w*(t4+w*(t7+w*(t10+w*t13))); - p3 = t2+w*(t5+w*(t8+w*(t11+w*t14))); - p = z*p1-(tt-w*(p2+y*p3)); - r += (tf + p); break; - case 2: - p1 = y*(u0+y*(u1+y*(u2+y*(u3+y*(u4+y*u5))))); - p2 = one+y*(v1+y*(v2+y*(v3+y*(v4+y*v5)))); - r += (-0.5*y + p1/p2); - } - } - else if(ix<0x40200000) { /* x < 8.0 */ - i = (int)x; - t = zero; - y = x-(double)i; - p = y*(s0+y*(s1+y*(s2+y*(s3+y*(s4+y*(s5+y*s6)))))); - q = one+y*(r1+y*(r2+y*(r3+y*(r4+y*(r5+y*r6))))); - r = half*y+p/q; - z = one; /* lgamma(1+s) = log(s) + lgamma(s) */ - switch(i) { - case 7: z *= (y+6.0); /* FALLTHRU */ - case 6: z *= (y+5.0); /* FALLTHRU */ - case 5: z *= (y+4.0); /* FALLTHRU */ - case 4: z *= (y+3.0); /* FALLTHRU */ - case 3: z *= (y+2.0); /* FALLTHRU */ - r += __ieee754_log(z); break; - } - /* 8.0 <= x < 2**58 */ - } else if (ix < 0x43900000) { - t = __ieee754_log(x); - z = one/x; - y = z*z; - w = w0+z*(w1+y*(w2+y*(w3+y*(w4+y*(w5+y*w6))))); - r = (x-half)*(t-one)+w; - } else - /* 2**58 <= x <= inf */ - r = x*(__ieee754_log(x)-one); - if(hx<0) r = nadj - r; - return r; -} diff --git a/js/src/fdlibm/e_log.c b/js/src/fdlibm/e_log.c deleted file mode 100644 index 8645d6efdccf..000000000000 --- a/js/src/fdlibm/e_log.c +++ /dev/null @@ -1,184 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_log.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* __ieee754_log(x) - * Return the logrithm of x - * - * Method : - * 1. Argument Reduction: find k and f such that - * x = 2^k * (1+f), - * where sqrt(2)/2 < 1+f < sqrt(2) . - * - * 2. Approximation of log(1+f). - * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s) - * = 2s + 2/3 s**3 + 2/5 s**5 + ....., - * = 2s + s*R - * We use a special Reme algorithm on [0,0.1716] to generate - * a polynomial of degree 14 to approximate R The maximum error - * of this polynomial approximation is bounded by 2**-58.45. In - * other words, - * 2 4 6 8 10 12 14 - * R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s +Lg6*s +Lg7*s - * (the values of Lg1 to Lg7 are listed in the program) - * and - * | 2 14 | -58.45 - * | Lg1*s +...+Lg7*s - R(z) | <= 2 - * | | - * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2. - * In order to guarantee error in log below 1ulp, we compute log - * by - * log(1+f) = f - s*(f - R) (if f is not too large) - * log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy) - * - * 3. Finally, log(x) = k*ln2 + log(1+f). - * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo))) - * Here ln2 is split into two floating point number: - * ln2_hi + ln2_lo, - * where n*ln2_hi is always exact for |n| < 2000. - * - * Special cases: - * log(x) is NaN with signal if x < 0 (including -INF) ; - * log(+INF) is +INF; log(0) is -INF with signal; - * log(NaN) is that NaN with no signal. - * - * Accuracy: - * according to an error analysis, the error is always less than - * 1 ulp (unit in the last place). - * - * Constants: - * The hexadecimal values are the intended ones for the following - * constants. The decimal values may be used, provided that the - * compiler will convert from decimal to binary accurately enough - * to produce the hexadecimal values shown. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif -ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */ -ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */ -two54 = 1.80143985094819840000e+16, /* 43500000 00000000 */ -Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */ -Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */ -Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */ -Lg4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */ -Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */ -Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */ -Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ - -static double zero = 0.0; - -#ifdef __STDC__ - double __ieee754_log(double x) -#else - double __ieee754_log(x) - double x; -#endif -{ - fd_twoints u; - double hfsq,f,s,z,R,w,t1,t2,dk; - int k,hx,i,j; - unsigned lx; - - u.d = x; - hx = __HI(u); /* high word of x */ - lx = __LO(u); /* low word of x */ - - k=0; - if (hx < 0x00100000) { /* x < 2**-1022 */ - if (((hx&0x7fffffff)|lx)==0) - return -two54/zero; /* log(+-0)=-inf */ - if (hx<0) return (x-x)/zero; /* log(-#) = NaN */ - k -= 54; x *= two54; /* subnormal number, scale up x */ - u.d = x; - hx = __HI(u); /* high word of x */ - } - if (hx >= 0x7ff00000) return x+x; - k += (hx>>20)-1023; - hx &= 0x000fffff; - i = (hx+0x95f64)&0x100000; - u.d = x; - __HI(u) = hx|(i^0x3ff00000); /* normalize x or x/2 */ - x = u.d; - k += (i>>20); - f = x-1.0; - if((0x000fffff&(2+hx))<3) { /* |f| < 2**-20 */ - if(f==zero) { - if(k==0) return zero; else {dk=(double)k; - return dk*ln2_hi+dk*ln2_lo;} - } - R = f*f*(0.5-0.33333333333333333*f); - if(k==0) return f-R; else {dk=(double)k; - return dk*ln2_hi-((R-dk*ln2_lo)-f);} - } - s = f/(2.0+f); - dk = (double)k; - z = s*s; - i = hx-0x6147a; - w = z*z; - j = 0x6b851-hx; - t1= w*(Lg2+w*(Lg4+w*Lg6)); - t2= z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7))); - i |= j; - R = t2+t1; - if(i>0) { - hfsq=0.5*f*f; - if(k==0) return f-(hfsq-s*(hfsq+R)); else - return dk*ln2_hi-((hfsq-(s*(hfsq+R)+dk*ln2_lo))-f); - } else { - if(k==0) return f-s*(f-R); else - return dk*ln2_hi-((s*(f-R)-dk*ln2_lo)-f); - } -} diff --git a/js/src/fdlibm/e_log10.c b/js/src/fdlibm/e_log10.c deleted file mode 100644 index 5f88f4b4cfeb..000000000000 --- a/js/src/fdlibm/e_log10.c +++ /dev/null @@ -1,134 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_log10.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* __ieee754_log10(x) - * Return the base 10 logarithm of x - * - * Method : - * Let log10_2hi = leading 40 bits of log10(2) and - * log10_2lo = log10(2) - log10_2hi, - * ivln10 = 1/log(10) rounded. - * Then - * n = ilogb(x), - * if(n<0) n = n+1; - * x = scalbn(x,-n); - * log10(x) := n*log10_2hi + (n*log10_2lo + ivln10*log(x)) - * - * Note 1: - * To guarantee log10(10**n)=n, where 10**n is normal, the rounding - * mode must set to Round-to-Nearest. - * Note 2: - * [1/log(10)] rounded to 53 bits has error .198 ulps; - * log10 is monotonic at all binary break points. - * - * Special cases: - * log10(x) is NaN with signal if x < 0; - * log10(+INF) is +INF with no signal; log10(0) is -INF with signal; - * log10(NaN) is that NaN with no signal; - * log10(10**N) = N for N=0,1,...,22. - * - * Constants: - * The hexadecimal values are the intended ones for the following constants. - * The decimal values may be used, provided that the compiler will convert - * from decimal to binary accurately enough to produce the hexadecimal values - * shown. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif -two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ -ivln10 = 4.34294481903251816668e-01, /* 0x3FDBCB7B, 0x1526E50E */ -log10_2hi = 3.01029995663611771306e-01, /* 0x3FD34413, 0x509F6000 */ -log10_2lo = 3.69423907715893078616e-13; /* 0x3D59FEF3, 0x11F12B36 */ - -static double zero = 0.0; - -#ifdef __STDC__ - double __ieee754_log10(double x) -#else - double __ieee754_log10(x) - double x; -#endif -{ - fd_twoints u; - double y,z; - int i,k,hx; - unsigned lx; - - u.d = x; - hx = __HI(u); /* high word of x */ - lx = __LO(u); /* low word of x */ - - k=0; - if (hx < 0x00100000) { /* x < 2**-1022 */ - if (((hx&0x7fffffff)|lx)==0) - return -two54/zero; /* log(+-0)=-inf */ - if (hx<0) return (x-x)/zero; /* log(-#) = NaN */ - k -= 54; x *= two54; /* subnormal number, scale up x */ - u.d = x; - hx = __HI(u); /* high word of x */ - } - if (hx >= 0x7ff00000) return x+x; - k += (hx>>20)-1023; - i = ((unsigned)k&0x80000000)>>31; - hx = (hx&0x000fffff)|((0x3ff-i)<<20); - y = (double)(k+i); - u.d = x; - __HI(u) = hx; - x = u.d; - z = y*log10_2lo + ivln10*__ieee754_log(x); - return z+y*log10_2hi; -} diff --git a/js/src/fdlibm/e_pow.c b/js/src/fdlibm/e_pow.c deleted file mode 100644 index 18c8d069507a..000000000000 --- a/js/src/fdlibm/e_pow.c +++ /dev/null @@ -1,386 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_pow.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* __ieee754_pow(x,y) return x**y - * - * n - * Method: Let x = 2 * (1+f) - * 1. Compute and return log2(x) in two pieces: - * log2(x) = w1 + w2, - * where w1 has 53-24 = 29 bit trailing zeros. - * 2. Perform y*log2(x) = n+y' by simulating muti-precision - * arithmetic, where |y'|<=0.5. - * 3. Return x**y = 2**n*exp(y'*log2) - * - * Special cases: - * 1. (anything) ** 0 is 1 - * 2. (anything) ** 1 is itself - * 3. (anything) ** NAN is NAN - * 4. NAN ** (anything except 0) is NAN - * 5. +-(|x| > 1) ** +INF is +INF - * 6. +-(|x| > 1) ** -INF is +0 - * 7. +-(|x| < 1) ** +INF is +0 - * 8. +-(|x| < 1) ** -INF is +INF - * 9. +-1 ** +-INF is NAN - * 10. +0 ** (+anything except 0, NAN) is +0 - * 11. -0 ** (+anything except 0, NAN, odd integer) is +0 - * 12. +0 ** (-anything except 0, NAN) is +INF - * 13. -0 ** (-anything except 0, NAN, odd integer) is +INF - * 14. -0 ** (odd integer) = -( +0 ** (odd integer) ) - * 15. +INF ** (+anything except 0,NAN) is +INF - * 16. +INF ** (-anything except 0,NAN) is +0 - * 17. -INF ** (anything) = -0 ** (-anything) - * 18. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer) - * 19. (-anything except 0 and inf) ** (non-integer) is NAN - * - * Accuracy: - * pow(x,y) returns x**y nearly rounded. In particular - * pow(integer,integer) - * always returns the correct integer provided it is - * representable. - * - * Constants : - * The hexadecimal values are the intended ones for the following - * constants. The decimal values may be used, provided that the - * compiler will convert from decimal to binary accurately enough - * to produce the hexadecimal values shown. - */ - -#include "fdlibm.h" - -#if defined(_MSC_VER) -/* Microsoft Compiler */ -#pragma warning( disable : 4723 ) /* disables potential divide by 0 warning */ -#endif - -#ifdef __STDC__ -static const double -#else -static double -#endif -bp[] = {1.0, 1.5,}, -dp_h[] = { 0.0, 5.84962487220764160156e-01,}, /* 0x3FE2B803, 0x40000000 */ -dp_l[] = { 0.0, 1.35003920212974897128e-08,}, /* 0x3E4CFDEB, 0x43CFD006 */ -zero = 0.0, -one = 1.0, -two = 2.0, -two53 = 9007199254740992.0, /* 0x43400000, 0x00000000 */ -really_big = 1.0e300, -tiny = 1.0e-300, - /* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */ -L1 = 5.99999999999994648725e-01, /* 0x3FE33333, 0x33333303 */ -L2 = 4.28571428578550184252e-01, /* 0x3FDB6DB6, 0xDB6FABFF */ -L3 = 3.33333329818377432918e-01, /* 0x3FD55555, 0x518F264D */ -L4 = 2.72728123808534006489e-01, /* 0x3FD17460, 0xA91D4101 */ -L5 = 2.30660745775561754067e-01, /* 0x3FCD864A, 0x93C9DB65 */ -L6 = 2.06975017800338417784e-01, /* 0x3FCA7E28, 0x4A454EEF */ -P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */ -P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */ -P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */ -P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */ -P5 = 4.13813679705723846039e-08, /* 0x3E663769, 0x72BEA4D0 */ -lg2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */ -lg2_h = 6.93147182464599609375e-01, /* 0x3FE62E43, 0x00000000 */ -lg2_l = -1.90465429995776804525e-09, /* 0xBE205C61, 0x0CA86C39 */ -ovt = 8.0085662595372944372e-0017, /* -(1024-log2(ovfl+.5ulp)) */ -cp = 9.61796693925975554329e-01, /* 0x3FEEC709, 0xDC3A03FD =2/(3ln2) */ -cp_h = 9.61796700954437255859e-01, /* 0x3FEEC709, 0xE0000000 =(float)cp */ -cp_l = -7.02846165095275826516e-09, /* 0xBE3E2FE0, 0x145B01F5 =tail of cp_h*/ -ivln2 = 1.44269504088896338700e+00, /* 0x3FF71547, 0x652B82FE =1/ln2 */ -ivln2_h = 1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2*/ -ivln2_l = 1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail*/ - -#ifdef __STDC__ - double __ieee754_pow(double x, double y) -#else - double __ieee754_pow(x,y) - double x, y; -#endif -{ - fd_twoints ux, uy, uz; - double y1,t1,p_h,t,z,ax; - double z_h,z_l,p_l; - double t2,r,s,u,v,w; - int i,j,k,yisint,n; - int hx,hy,ix,iy; - unsigned lx,ly; - - ux.d = x; uy.d = y; - hx = __HI(ux); lx = __LO(ux); - hy = __HI(uy); ly = __LO(uy); - ix = hx&0x7fffffff; iy = hy&0x7fffffff; - - /* y==zero: x**0 = 1 */ - if((iy|ly)==0) return one; - - /* +-NaN return x+y */ - if(ix > 0x7ff00000 || ((ix==0x7ff00000)&&(lx!=0)) || - iy > 0x7ff00000 || ((iy==0x7ff00000)&&(ly!=0))) - return x+y; - - /* determine if y is an odd int when x < 0 - * yisint = 0 ... y is not an integer - * yisint = 1 ... y is an odd int - * yisint = 2 ... y is an even int - */ - yisint = 0; - if(hx<0) { - if(iy>=0x43400000) yisint = 2; /* even integer y */ - else if(iy>=0x3ff00000) { - k = (iy>>20)-0x3ff; /* exponent */ - if(k>20) { - j = ly>>(52-k); - if((j<<(52-k))==(int)ly) yisint = 2-(j&1); - } else if(ly==0) { - j = iy>>(20-k); - if((j<<(20-k))==iy) yisint = 2-(j&1); - } - } - } - - /* special value of y */ - if(ly==0) { - if (iy==0x7ff00000) { /* y is +-inf */ - if(((ix-0x3ff00000)|lx)==0) -#ifdef _WIN32 -/* VC++ optimizer reduces y - y to 0 */ - return y / y; -#else - return y - y; /* inf**+-1 is NaN */ -#endif - else if (ix >= 0x3ff00000)/* (|x|>1)**+-inf = inf,0 */ - return (hy>=0)? y: zero; - else /* (|x|<1)**-,+inf = inf,0 */ - return (hy<0)?-y: zero; - } - if(iy==0x3ff00000) { /* y is +-1 */ - if(hy<0) return one/x; else return x; - } - if(hy==0x40000000) return x*x; /* y is 2 */ - if(hy==0x3fe00000) { /* y is 0.5 */ - if(hx>=0) /* x >= +0 */ - return fd_sqrt(x); - } - } - - ax = fd_fabs(x); - /* special value of x */ - if(lx==0) { - if(ix==0x7ff00000||ix==0||ix==0x3ff00000){ - z = ax; /*x is +-0,+-inf,+-1*/ - if(hy<0) z = one/z; /* z = (1/|x|) */ - if(hx<0) { - if(((ix-0x3ff00000)|yisint)==0) { - z = (z-z)/(z-z); /* (-1)**non-int is NaN */ - } else if(yisint==1) { -#ifdef HPUX - uz.d = z; - __HI(uz) ^= 1<<31; /* some HPUXes cannot negate 0.. */ - z = uz.d; -#else - z = -z; /* (x<0)**odd = -(|x|**odd) */ -#endif - } - } - return z; - } - } - - /* (x<0)**(non-int) is NaN */ - if((((hx>>31)+1)|yisint)==0) return (x-x)/(x-x); - - /* |y| is really_big */ - if(iy>0x41e00000) { /* if |y| > 2**31 */ - if(iy>0x43f00000){ /* if |y| > 2**64, must o/uflow */ - if(ix<=0x3fefffff) return (hy<0)? really_big*really_big:tiny*tiny; - if(ix>=0x3ff00000) return (hy>0)? really_big*really_big:tiny*tiny; - } - /* over/underflow if x is not close to one */ - if(ix<0x3fefffff) return (hy<0)? really_big*really_big:tiny*tiny; - if(ix>0x3ff00000) return (hy>0)? really_big*really_big:tiny*tiny; - /* now |1-x| is tiny <= 2**-20, suffice to compute - log(x) by x-x^2/2+x^3/3-x^4/4 */ - t = x-1; /* t has 20 trailing zeros */ - w = (t*t)*(0.5-t*(0.3333333333333333333333-t*0.25)); - u = ivln2_h*t; /* ivln2_h has 21 sig. bits */ - v = t*ivln2_l-w*ivln2; - t1 = u+v; - uz.d = t1; - __LO(uz) = 0; - t1 = uz.d; - t2 = v-(t1-u); - } else { - double s_h,t_h; - double s2,s_l,t_l; - n = 0; - /* take care subnormal number */ - if(ix<0x00100000) - {ax *= two53; n -= 53; uz.d = ax; ix = __HI(uz); } - n += ((ix)>>20)-0x3ff; - j = ix&0x000fffff; - /* determine interval */ - ix = j|0x3ff00000; /* normalize ix */ - if(j<=0x3988E) k=0; /* |x|>1)|0x20000000)+0x00080000+(k<<18); - t_h = uz.d; - t_l = ax - (t_h-bp[k]); - s_l = v*((u-s_h*t_h)-s_h*t_l); - /* compute log(ax) */ - s2 = s*s; - r = s2*s2*(L1+s2*(L2+s2*(L3+s2*(L4+s2*(L5+s2*L6))))); - r += s_l*(s_h+s); - s2 = s_h*s_h; - t_h = 3.0+s2+r; - uz.d = t_h; - __LO(uz) = 0; - t_h = uz.d; - t_l = r-((t_h-3.0)-s2); - /* u+v = s*(1+...) */ - u = s_h*t_h; - v = s_l*t_h+t_l*s; - /* 2/(3log2)*(s+...) */ - p_h = u+v; - uz.d = p_h; - __LO(uz) = 0; - p_h = uz.d; - p_l = v-(p_h-u); - z_h = cp_h*p_h; /* cp_h+cp_l = 2/(3*log2) */ - z_l = cp_l*p_h+p_l*cp+dp_l[k]; - /* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */ - t = (double)n; - t1 = (((z_h+z_l)+dp_h[k])+t); - uz.d = t1; - __LO(uz) = 0; - t1 = uz.d; - t2 = z_l-(((t1-t)-dp_h[k])-z_h); - } - - s = one; /* s (sign of result -ve**odd) = -1 else = 1 */ - if((((hx>>31)+1)|(yisint-1))==0) s = -one;/* (-ve)**(odd int) */ - - /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */ - y1 = y; - uy.d = y1; - __LO(uy) = 0; - y1 = uy.d; - p_l = (y-y1)*t1+y*t2; - p_h = y1*t1; - z = p_l+p_h; - uz.d = z; - j = __HI(uz); - i = __LO(uz); - - if (j>=0x40900000) { /* z >= 1024 */ - if(((j-0x40900000)|i)!=0) /* if z > 1024 */ - return s*really_big*really_big; /* overflow */ - else { - if(p_l+ovt>z-p_h) return s*really_big*really_big; /* overflow */ - } - } else if((j&0x7fffffff)>=0x4090cc00 ) { /* z <= -1075 */ - if(((j-0xc090cc00)|i)!=0) /* z < -1075 */ - return s*tiny*tiny; /* underflow */ - else { - if(p_l<=z-p_h) return s*tiny*tiny; /* underflow */ - } - } - /* - * compute 2**(p_h+p_l) - */ - i = j&0x7fffffff; - k = (i>>20)-0x3ff; - n = 0; - if(i>0x3fe00000) { /* if |z| > 0.5, set n = [z+0.5] */ - n = j+(0x00100000>>(k+1)); - k = ((n&0x7fffffff)>>20)-0x3ff; /* new k for n */ - t = zero; - uz.d = t; - __HI(uz) = (n&~(0x000fffff>>k)); - t = uz.d; - n = ((n&0x000fffff)|0x00100000)>>(20-k); - if(j<0) n = -n; - p_h -= t; - } - t = p_l+p_h; - uz.d = t; - __LO(uz) = 0; - t = uz.d; - u = t*lg2_h; - v = (p_l-(t-p_h))*lg2+t*lg2_l; - z = u+v; - w = v-(z-u); - t = z*z; - t1 = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))); - r = (z*t1)/(t1-two)-(w+z*w); - z = one-(r-z); - uz.d = z; - j = __HI(uz); - j += (n<<20); - if((j>>20)<=0) z = fd_scalbn(z,n); /* subnormal output */ - else { uz.d = z; __HI(uz) += (n<<20); z = uz.d; } - return s*z; -} diff --git a/js/src/fdlibm/e_rem_pio2.c b/js/src/fdlibm/e_rem_pio2.c deleted file mode 100644 index c9d26187510b..000000000000 --- a/js/src/fdlibm/e_rem_pio2.c +++ /dev/null @@ -1,222 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_rem_pio2.c 1.4 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - * - */ - -/* __ieee754_rem_pio2(x,y) - * - * return the remainder of x rem pi/2 in y[0]+y[1] - * use __kernel_rem_pio2() - */ - -#include "fdlibm.h" - -/* - * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi - */ -#ifdef __STDC__ -static const int two_over_pi[] = { -#else -static int two_over_pi[] = { -#endif -0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62, -0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A, -0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129, -0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41, -0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8, -0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF, -0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5, -0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08, -0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3, -0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880, -0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B, -}; - -#ifdef __STDC__ -static const int npio2_hw[] = { -#else -static int npio2_hw[] = { -#endif -0x3FF921FB, 0x400921FB, 0x4012D97C, 0x401921FB, 0x401F6A7A, 0x4022D97C, -0x4025FDBB, 0x402921FB, 0x402C463A, 0x402F6A7A, 0x4031475C, 0x4032D97C, -0x40346B9C, 0x4035FDBB, 0x40378FDB, 0x403921FB, 0x403AB41B, 0x403C463A, -0x403DD85A, 0x403F6A7A, 0x40407E4C, 0x4041475C, 0x4042106C, 0x4042D97C, -0x4043A28C, 0x40446B9C, 0x404534AC, 0x4045FDBB, 0x4046C6CB, 0x40478FDB, -0x404858EB, 0x404921FB, -}; - -/* - * invpio2: 53 bits of 2/pi - * pio2_1: first 33 bit of pi/2 - * pio2_1t: pi/2 - pio2_1 - * pio2_2: second 33 bit of pi/2 - * pio2_2t: pi/2 - (pio2_1+pio2_2) - * pio2_3: third 33 bit of pi/2 - * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3) - */ - -#ifdef __STDC__ -static const double -#else -static double -#endif -zero = 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ -half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */ -two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */ -invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ -pio2_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */ -pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */ -pio2_2 = 6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */ -pio2_2t = 2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */ -pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */ -pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */ - -#ifdef __STDC__ - int __ieee754_rem_pio2(double x, double *y) -#else - int __ieee754_rem_pio2(x,y) - double x,y[]; -#endif -{ - fd_twoints u, ux, uz; - double z = 0; - double w,t,r,fn; - double tx[3]; - int e0,i,j,nx,n,ix,hx; - - u.d = x; - hx = __HI(u); /* high word of x */ - ix = hx&0x7fffffff; - if(ix<=0x3fe921fb) /* |x| ~<= pi/4 , no need for reduction */ - {y[0] = x; y[1] = 0; return 0;} - if(ix<0x4002d97c) { /* |x| < 3pi/4, special case with n=+-1 */ - if(hx>0) { - z = x - pio2_1; - if(ix!=0x3ff921fb) { /* 33+53 bit pi is good enough */ - y[0] = z - pio2_1t; - y[1] = (z-y[0])-pio2_1t; - } else { /* near pi/2, use 33+33+53 bit pi */ - z -= pio2_2; - y[0] = z - pio2_2t; - y[1] = (z-y[0])-pio2_2t; - } - return 1; - } else { /* negative x */ - z = x + pio2_1; - if(ix!=0x3ff921fb) { /* 33+53 bit pi is good enough */ - y[0] = z + pio2_1t; - y[1] = (z-y[0])+pio2_1t; - } else { /* near pi/2, use 33+33+53 bit pi */ - z += pio2_2; - y[0] = z + pio2_2t; - y[1] = (z-y[0])+pio2_2t; - } - return -1; - } - } - if(ix<=0x413921fb) { /* |x| ~<= 2^19*(pi/2), medium size */ - t = fd_fabs(x); - n = (int) (t*invpio2+half); - fn = (double)n; - r = t-fn*pio2_1; - w = fn*pio2_1t; /* 1st round good to 85 bit */ - if(n<32&&ix!=npio2_hw[n-1]) { - y[0] = r-w; /* quick check no cancellation */ - } else { - j = ix>>20; - y[0] = r-w; - u.d = y[0]; - i = j-(((__HI(u))>>20)&0x7ff); - if(i>16) { /* 2nd iteration needed, good to 118 */ - t = r; - w = fn*pio2_2; - r = t-w; - w = fn*pio2_2t-((t-r)-w); - y[0] = r-w; - u.d = y[0]; - i = j-(((__HI(u))>>20)&0x7ff); - if(i>49) { /* 3rd iteration need, 151 bits acc */ - t = r; /* will cover all possible cases */ - w = fn*pio2_3; - r = t-w; - w = fn*pio2_3t-((t-r)-w); - y[0] = r-w; - } - } - } - y[1] = (r-y[0])-w; - if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;} - else return n; - } - /* - * all other (large) arguments - */ - if(ix>=0x7ff00000) { /* x is inf or NaN */ - y[0]=y[1]=x-x; return 0; - } - /* set z = scalbn(|x|,ilogb(x)-23) */ - ux.d = x; uz.d = z; - __LO(uz) = __LO(ux); - z = uz.d; - e0 = (ix>>20)-1046; /* e0 = ilogb(z)-23; */ - uz.d = z; - __HI(uz) = ix - (e0<<20); - z = uz.d; - for(i=0;i<2;i++) { - tx[i] = (double)((int)(z)); - z = (z-tx[i])*two24; - } - tx[2] = z; - nx = 3; - while(tx[nx-1]==zero) nx--; /* skip zero term */ - n = __kernel_rem_pio2(tx,y,e0,nx,2,two_over_pi); - if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;} - return n; -} diff --git a/js/src/fdlibm/e_remainder.c b/js/src/fdlibm/e_remainder.c deleted file mode 100644 index de40f0c2a5ec..000000000000 --- a/js/src/fdlibm/e_remainder.c +++ /dev/null @@ -1,120 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_remainder.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* __ieee754_remainder(x,p) - * Return : - * returns x REM p = x - [x/p]*p as if in infinite - * precise arithmetic, where [x/p] is the (infinite bit) - * integer nearest x/p (in half way case choose the even one). - * Method : - * Based on fmod() return x-[x/p]chopped*p exactlp. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double zero = 0.0; -#else -static double zero = 0.0; -#endif - - -#ifdef __STDC__ - double __ieee754_remainder(double x, double p) -#else - double __ieee754_remainder(x,p) - double x,p; -#endif -{ - fd_twoints u; - int hx,hp; - unsigned sx,lx,lp; - double p_half; - - u.d = x; - hx = __HI(u); /* high word of x */ - lx = __LO(u); /* low word of x */ - u.d = p; - hp = __HI(u); /* high word of p */ - lp = __LO(u); /* low word of p */ - sx = hx&0x80000000; - hp &= 0x7fffffff; - hx &= 0x7fffffff; - - /* purge off exception values */ - if((hp|lp)==0) return (x*p)/(x*p); /* p = 0 */ - if((hx>=0x7ff00000)|| /* x not finite */ - ((hp>=0x7ff00000)&& /* p is NaN */ - (((hp-0x7ff00000)|lp)!=0))) - return (x*p)/(x*p); - - - if (hp<=0x7fdfffff) x = __ieee754_fmod(x,p+p); /* now x < 2p */ - if (((hx-hp)|(lx-lp))==0) return zero*x; - x = fd_fabs(x); - p = fd_fabs(p); - if (hp<0x00200000) { - if(x+x>p) { - x-=p; - if(x+x>=p) x -= p; - } - } else { - p_half = 0.5*p; - if(x>p_half) { - x-=p; - if(x>=p_half) x -= p; - } - } - u.d = x; - __HI(u) ^= sx; - x = u.d; - return x; -} diff --git a/js/src/fdlibm/e_scalb.c b/js/src/fdlibm/e_scalb.c deleted file mode 100644 index 621704ea048b..000000000000 --- a/js/src/fdlibm/e_scalb.c +++ /dev/null @@ -1,89 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_scalb.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * __ieee754_scalb(x, fn) is provide for - * passing various standard test suite. One - * should use scalbn() instead. - */ - -#include "fdlibm.h" - -#ifdef _SCALB_INT -#ifdef __STDC__ - double __ieee754_scalb(double x, int fn) -#else - double __ieee754_scalb(x,fn) - double x; int fn; -#endif -#else -#ifdef __STDC__ - double __ieee754_scalb(double x, double fn) -#else - double __ieee754_scalb(x,fn) - double x, fn; -#endif -#endif -{ -#ifdef _SCALB_INT - return fd_scalbn(x,fn); -#else - if (fd_isnan(x)||fd_isnan(fn)) return x*fn; - if (!fd_finite(fn)) { - if(fn>0.0) return x*fn; - else return x/(-fn); - } - if (fd_rint(fn)!=fn) return (fn-fn)/(fn-fn); - if ( fn > 65000.0) return fd_scalbn(x, 65000); - if (-fn > 65000.0) return fd_scalbn(x,-65000); - return fd_scalbn(x,(int)fn); -#endif -} diff --git a/js/src/fdlibm/e_sinh.c b/js/src/fdlibm/e_sinh.c deleted file mode 100644 index 98ab9b5a32f3..000000000000 --- a/js/src/fdlibm/e_sinh.c +++ /dev/null @@ -1,122 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)e_sinh.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* __ieee754_sinh(x) - * Method : - * mathematically sinh(x) if defined to be (exp(x)-exp(-x))/2 - * 1. Replace x by |x| (sinh(-x) = -sinh(x)). - * 2. - * E + E/(E+1) - * 0 <= x <= 22 : sinh(x) := --------------, E=expm1(x) - * 2 - * - * 22 <= x <= lnovft : sinh(x) := exp(x)/2 - * lnovft <= x <= ln2ovft: sinh(x) := exp(x/2)/2 * exp(x/2) - * ln2ovft < x : sinh(x) := x*shuge (overflow) - * - * Special cases: - * sinh(x) is |x| if x is +INF, -INF, or NaN. - * only sinh(0)=0 is exact for finite x. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double one = 1.0, shuge = 1.0e307; -#else -static double one = 1.0, shuge = 1.0e307; -#endif - -#ifdef __STDC__ - double __ieee754_sinh(double x) -#else - double __ieee754_sinh(x) - double x; -#endif -{ - fd_twoints u; - double t,w,h; - int ix,jx; - unsigned lx; - - /* High word of |x|. */ - u.d = x; - jx = __HI(u); - ix = jx&0x7fffffff; - - /* x is INF or NaN */ - if(ix>=0x7ff00000) return x+x; - - h = 0.5; - if (jx<0) h = -h; - /* |x| in [0,22], return sign(x)*0.5*(E+E/(E+1))) */ - if (ix < 0x40360000) { /* |x|<22 */ - if (ix<0x3e300000) /* |x|<2**-28 */ - if(shuge+x>one) return x;/* sinh(tiny) = tiny with inexact */ - t = fd_expm1(fd_fabs(x)); - if(ix<0x3ff00000) return h*(2.0*t-t*t/(t+one)); - return h*(t+t/(t+one)); - } - - /* |x| in [22, log(maxdouble)] return 0.5*exp(|x|) */ - if (ix < 0x40862E42) return h*__ieee754_exp(fd_fabs(x)); - - /* |x| in [log(maxdouble), overflowthresold] */ - lx = *( (((*(unsigned*)&one)>>29)) + (unsigned*)&x); - if (ix<0x408633CE || (ix==0x408633ce)&&(lx<=(unsigned)0x8fb9f87d)) { - w = __ieee754_exp(0.5*fd_fabs(x)); - t = h*w; - return t*w; - } - - /* |x| > overflowthresold, sinh(x) overflow */ - return x*shuge; -} diff --git a/js/src/fdlibm/e_sqrt.c b/js/src/fdlibm/e_sqrt.c deleted file mode 100644 index 91802839b082..000000000000 --- a/js/src/fdlibm/e_sqrt.c +++ /dev/null @@ -1,497 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* @(#)e_sqrt.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* __ieee754_sqrt(x) - * Return correctly rounded sqrt. - * ------------------------------------------ - * | Use the hardware sqrt if you have one | - * ------------------------------------------ - * Method: - * Bit by bit method using integer arithmetic. (Slow, but portable) - * 1. Normalization - * Scale x to y in [1,4) with even powers of 2: - * find an integer k such that 1 <= (y=x*2^(2k)) < 4, then - * sqrt(y) = 2^k * sqrt(x) - * 2. Bit by bit computation - * Let q = sqrt(y) truncated to i bit after binary point (q = 1), - * i 0 - * i+1 2 - * s = 2*q , and y = 2 * ( y - q ). (1) - * i i i i - * - * To compute q from q , one checks whether - * i+1 i - * - * -(i+1) 2 - * (q + 2 ) <= y. (2) - * i - * -(i+1) - * If (2) is false, then q = q ; otherwise q = q + 2 . - * i+1 i i+1 i - * - * With some algebric manipulation, it is not difficult to see - * that (2) is equivalent to - * -(i+1) - * s + 2 <= y (3) - * i i - * - * The advantage of (3) is that s and y can be computed by - * i i - * the following recurrence formula: - * if (3) is false - * - * s = s , y = y ; (4) - * i+1 i i+1 i - * - * otherwise, - * -i -(i+1) - * s = s + 2 , y = y - s - 2 (5) - * i+1 i i+1 i i - * - * One may easily use induction to prove (4) and (5). - * Note. Since the left hand side of (3) contain only i+2 bits, - * it does not necessary to do a full (53-bit) comparison - * in (3). - * 3. Final rounding - * After generating the 53 bits result, we compute one more bit. - * Together with the remainder, we can decide whether the - * result is exact, bigger than 1/2ulp, or less than 1/2ulp - * (it will never equal to 1/2ulp). - * The rounding mode can be detected by checking whether - * huge + tiny is equal to huge, and whether huge - tiny is - * equal to huge for some floating point number "huge" and "tiny". - * - * Special cases: - * sqrt(+-0) = +-0 ... exact - * sqrt(inf) = inf - * sqrt(-ve) = NaN ... with invalid signal - * sqrt(NaN) = NaN ... with invalid signal for signaling NaN - * - * Other methods : see the appended file at the end of the program below. - *--------------- - */ - -#include "fdlibm.h" - -#if defined(_MSC_VER) -/* Microsoft Compiler */ -#pragma warning( disable : 4723 ) /* disables potential divide by 0 warning */ -#endif - -#ifdef __STDC__ -static const double one = 1.0, tiny=1.0e-300; -#else -static double one = 1.0, tiny=1.0e-300; -#endif - -#ifdef __STDC__ - double __ieee754_sqrt(double x) -#else - double __ieee754_sqrt(x) - double x; -#endif -{ - fd_twoints u; - double z; - int sign = (int)0x80000000; - unsigned r,t1,s1,ix1,q1; - int ix0,s0,q,m,t,i; - - u.d = x; - ix0 = __HI(u); /* high word of x */ - ix1 = __LO(u); /* low word of x */ - - /* take care of Inf and NaN */ - if((ix0&0x7ff00000)==0x7ff00000) { - return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf - sqrt(-inf)=sNaN */ - } - /* take care of zero */ - if(ix0<=0) { - if(((ix0&(~sign))|ix1)==0) return x;/* sqrt(+-0) = +-0 */ - else if(ix0<0) - return (x-x)/(x-x); /* sqrt(-ve) = sNaN */ - } - /* normalize x */ - m = (ix0>>20); - if(m==0) { /* subnormal x */ - while(ix0==0) { - m -= 21; - ix0 |= (ix1>>11); ix1 <<= 21; - } - for(i=0;(ix0&0x00100000)==0;i++) ix0<<=1; - m -= i-1; - ix0 |= (ix1>>(32-i)); - ix1 <<= i; - } - m -= 1023; /* unbias exponent */ - ix0 = (ix0&0x000fffff)|0x00100000; - if(m&1){ /* odd m, double x to make it even */ - ix0 += ix0 + ((ix1&sign)>>31); - ix1 += ix1; - } - m >>= 1; /* m = [m/2] */ - - /* generate sqrt(x) bit by bit */ - ix0 += ix0 + ((ix1&sign)>>31); - ix1 += ix1; - q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */ - r = 0x00200000; /* r = moving bit from right to left */ - - while(r!=0) { - t = s0+r; - if(t<=ix0) { - s0 = t+r; - ix0 -= t; - q += r; - } - ix0 += ix0 + ((ix1&sign)>>31); - ix1 += ix1; - r>>=1; - } - - r = sign; - while(r!=0) { - t1 = s1+r; - t = s0; - if((t>31); - ix1 += ix1; - r>>=1; - } - - /* use floating add to find out rounding direction */ - if((ix0|ix1)!=0) { - z = one-tiny; /* trigger inexact flag */ - if (z>=one) { - z = one+tiny; - if (q1==(unsigned)0xffffffff) { q1=0; q += 1;} - else if (z>one) { - if (q1==(unsigned)0xfffffffe) q+=1; - q1+=2; - } else - q1 += (q1&1); - } - } - ix0 = (q>>1)+0x3fe00000; - ix1 = q1>>1; - if ((q&1)==1) ix1 |= sign; - ix0 += (m <<20); - u.d = z; - __HI(u) = ix0; - __LO(u) = ix1; - z = u.d; - return z; -} - -/* -Other methods (use floating-point arithmetic) -------------- -(This is a copy of a drafted paper by Prof W. Kahan -and K.C. Ng, written in May, 1986) - - Two algorithms are given here to implement sqrt(x) - (IEEE double precision arithmetic) in software. - Both supply sqrt(x) correctly rounded. The first algorithm (in - Section A) uses newton iterations and involves four divisions. - The second one uses reciproot iterations to avoid division, but - requires more multiplications. Both algorithms need the ability - to chop results of arithmetic operations instead of round them, - and the INEXACT flag to indicate when an arithmetic operation - is executed exactly with no roundoff error, all part of the - standard (IEEE 754-1985). The ability to perform shift, add, - subtract and logical AND operations upon 32-bit words is needed - too, though not part of the standard. - -A. sqrt(x) by Newton Iteration - - (1) Initial approximation - - Let x0 and x1 be the leading and the trailing 32-bit words of - a floating point number x (in IEEE double format) respectively - - 1 11 52 ...widths - ------------------------------------------------------ - x: |s| e | f | - ------------------------------------------------------ - msb lsb msb lsb ...order - - - ------------------------ ------------------------ - x0: |s| e | f1 | x1: | f2 | - ------------------------ ------------------------ - - By performing shifts and subtracts on x0 and x1 (both regarded - as integers), we obtain an 8-bit approximation of sqrt(x) as - follows. - - k := (x0>>1) + 0x1ff80000; - y0 := k - T1[31&(k>>15)]. ... y ~ sqrt(x) to 8 bits - Here k is a 32-bit integer and T1[] is an integer array containing - correction terms. Now magically the floating value of y (y's - leading 32-bit word is y0, the value of its trailing word is 0) - approximates sqrt(x) to almost 8-bit. - - Value of T1: - static int T1[32]= { - 0, 1024, 3062, 5746, 9193, 13348, 18162, 23592, - 29598, 36145, 43202, 50740, 58733, 67158, 75992, 85215, - 83599, 71378, 60428, 50647, 41945, 34246, 27478, 21581, - 16499, 12183, 8588, 5674, 3403, 1742, 661, 130,}; - - (2) Iterative refinement - - Apply Heron's rule three times to y, we have y approximates - sqrt(x) to within 1 ulp (Unit in the Last Place): - - y := (y+x/y)/2 ... almost 17 sig. bits - y := (y+x/y)/2 ... almost 35 sig. bits - y := y-(y-x/y)/2 ... within 1 ulp - - - Remark 1. - Another way to improve y to within 1 ulp is: - - y := (y+x/y) ... almost 17 sig. bits to 2*sqrt(x) - y := y - 0x00100006 ... almost 18 sig. bits to sqrt(x) - - 2 - (x-y )*y - y := y + 2* ---------- ...within 1 ulp - 2 - 3y + x - - - This formula has one division fewer than the one above; however, - it requires more multiplications and additions. Also x must be - scaled in advance to avoid spurious overflow in evaluating the - expression 3y*y+x. Hence it is not recommended uless division - is slow. If division is very slow, then one should use the - reciproot algorithm given in section B. - - (3) Final adjustment - - By twiddling y's last bit it is possible to force y to be - correctly rounded according to the prevailing rounding mode - as follows. Let r and i be copies of the rounding mode and - inexact flag before entering the square root program. Also we - use the expression y+-ulp for the next representable floating - numbers (up and down) of y. Note that y+-ulp = either fixed - point y+-1, or multiply y by nextafter(1,+-inf) in chopped - mode. - - I := FALSE; ... reset INEXACT flag I - R := RZ; ... set rounding mode to round-toward-zero - z := x/y; ... chopped quotient, possibly inexact - If(not I) then { ... if the quotient is exact - if(z=y) { - I := i; ... restore inexact flag - R := r; ... restore rounded mode - return sqrt(x):=y. - } else { - z := z - ulp; ... special rounding - } - } - i := TRUE; ... sqrt(x) is inexact - If (r=RN) then z=z+ulp ... rounded-to-nearest - If (r=RP) then { ... round-toward-+inf - y = y+ulp; z=z+ulp; - } - y := y+z; ... chopped sum - y0:=y0-0x00100000; ... y := y/2 is correctly rounded. - I := i; ... restore inexact flag - R := r; ... restore rounded mode - return sqrt(x):=y. - - (4) Special cases - - Square root of +inf, +-0, or NaN is itself; - Square root of a negative number is NaN with invalid signal. - - -B. sqrt(x) by Reciproot Iteration - - (1) Initial approximation - - Let x0 and x1 be the leading and the trailing 32-bit words of - a floating point number x (in IEEE double format) respectively - (see section A). By performing shifs and subtracts on x0 and y0, - we obtain a 7.8-bit approximation of 1/sqrt(x) as follows. - - k := 0x5fe80000 - (x0>>1); - y0:= k - T2[63&(k>>14)]. ... y ~ 1/sqrt(x) to 7.8 bits - - Here k is a 32-bit integer and T2[] is an integer array - containing correction terms. Now magically the floating - value of y (y's leading 32-bit word is y0, the value of - its trailing word y1 is set to zero) approximates 1/sqrt(x) - to almost 7.8-bit. - - Value of T2: - static int T2[64]= { - 0x1500, 0x2ef8, 0x4d67, 0x6b02, 0x87be, 0xa395, 0xbe7a, 0xd866, - 0xf14a, 0x1091b,0x11fcd,0x13552,0x14999,0x15c98,0x16e34,0x17e5f, - 0x18d03,0x19a01,0x1a545,0x1ae8a,0x1b5c4,0x1bb01,0x1bfde,0x1c28d, - 0x1c2de,0x1c0db,0x1ba73,0x1b11c,0x1a4b5,0x1953d,0x18266,0x16be0, - 0x1683e,0x179d8,0x18a4d,0x19992,0x1a789,0x1b445,0x1bf61,0x1c989, - 0x1d16d,0x1d77b,0x1dddf,0x1e2ad,0x1e5bf,0x1e6e8,0x1e654,0x1e3cd, - 0x1df2a,0x1d635,0x1cb16,0x1be2c,0x1ae4e,0x19bde,0x1868e,0x16e2e, - 0x1527f,0x1334a,0x11051,0xe951, 0xbe01, 0x8e0d, 0x5924, 0x1edd,}; - - (2) Iterative refinement - - Apply Reciproot iteration three times to y and multiply the - result by x to get an approximation z that matches sqrt(x) - to about 1 ulp. To be exact, we will have - -1ulp < sqrt(x)-z<1.0625ulp. - - ... set rounding mode to Round-to-nearest - y := y*(1.5-0.5*x*y*y) ... almost 15 sig. bits to 1/sqrt(x) - y := y*((1.5-2^-30)+0.5*x*y*y)... about 29 sig. bits to 1/sqrt(x) - ... special arrangement for better accuracy - z := x*y ... 29 bits to sqrt(x), with z*y<1 - z := z + 0.5*z*(1-z*y) ... about 1 ulp to sqrt(x) - - Remark 2. The constant 1.5-2^-30 is chosen to bias the error so that - (a) the term z*y in the final iteration is always less than 1; - (b) the error in the final result is biased upward so that - -1 ulp < sqrt(x) - z < 1.0625 ulp - instead of |sqrt(x)-z|<1.03125ulp. - - (3) Final adjustment - - By twiddling y's last bit it is possible to force y to be - correctly rounded according to the prevailing rounding mode - as follows. Let r and i be copies of the rounding mode and - inexact flag before entering the square root program. Also we - use the expression y+-ulp for the next representable floating - numbers (up and down) of y. Note that y+-ulp = either fixed - point y+-1, or multiply y by nextafter(1,+-inf) in chopped - mode. - - R := RZ; ... set rounding mode to round-toward-zero - switch(r) { - case RN: ... round-to-nearest - if(x<= z*(z-ulp)...chopped) z = z - ulp; else - if(x<= z*(z+ulp)...chopped) z = z; else z = z+ulp; - break; - case RZ:case RM: ... round-to-zero or round-to--inf - R:=RP; ... reset rounding mod to round-to-+inf - if(x=(z+ulp)*(z+ulp) ...rounded up) z = z+ulp; - break; - case RP: ... round-to-+inf - if(x>(z+ulp)*(z+ulp)...chopped) z = z+2*ulp; else - if(x>z*z ...chopped) z = z+ulp; - break; - } - - Remark 3. The above comparisons can be done in fixed point. For - example, to compare x and w=z*z chopped, it suffices to compare - x1 and w1 (the trailing parts of x and w), regarding them as - two's complement integers. - - ...Is z an exact square root? - To determine whether z is an exact square root of x, let z1 be the - trailing part of z, and also let x0 and x1 be the leading and - trailing parts of x. - - If ((z1&0x03ffffff)!=0) ... not exact if trailing 26 bits of z!=0 - I := 1; ... Raise Inexact flag: z is not exact - else { - j := 1 - [(x0>>20)&1] ... j = logb(x) mod 2 - k := z1 >> 26; ... get z's 25-th and 26-th - fraction bits - I := i or (k&j) or ((k&(j+j+1))!=(x1&3)); - } - R:= r ... restore rounded mode - return sqrt(x):=z. - - If multiplication is cheaper then the foregoing red tape, the - Inexact flag can be evaluated by - - I := i; - I := (z*z!=x) or I. - - Note that z*z can overwrite I; this value must be sensed if it is - True. - - Remark 4. If z*z = x exactly, then bit 25 to bit 0 of z1 must be - zero. - - -------------------- - z1: | f2 | - -------------------- - bit 31 bit 0 - - Further more, bit 27 and 26 of z1, bit 0 and 1 of x1, and the odd - or even of logb(x) have the following relations: - - ------------------------------------------------- - bit 27,26 of z1 bit 1,0 of x1 logb(x) - ------------------------------------------------- - 00 00 odd and even - 01 01 even - 10 10 odd - 10 00 even - 11 01 even - ------------------------------------------------- - - (4) Special cases (see (4) of Section A). - - */ - diff --git a/js/src/fdlibm/fdlibm.h b/js/src/fdlibm/fdlibm.h deleted file mode 100644 index e623be56e450..000000000000 --- a/js/src/fdlibm/fdlibm.h +++ /dev/null @@ -1,273 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)fdlibm.h 1.5 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* Modified defines start here.. */ -#undef __LITTLE_ENDIAN - -#ifdef _WIN32 -#define huge myhuge -#define __LITTLE_ENDIAN -#endif - -#ifdef XP_OS2 -#define __LITTLE_ENDIAN -#endif - -#if defined(linux) && (defined(__i386__) || defined(__x86_64__) || defined(__ia64) || (defined(__mips) && defined(__MIPSEL__))) -#define __LITTLE_ENDIAN -#endif - -/* End here. The rest is the standard file. */ - -#ifdef SOLARIS /* special setup for Sun test regime */ -#if defined(i386) || defined(i486) || \ - defined(intel) || defined(x86) || defined(i86pc) -#define __LITTLE_ENDIAN -#endif -#endif - -typedef union { -#ifdef __LITTLE_ENDIAN - struct { int lo, hi; } ints; -#else - struct { int hi, lo; } ints; -#endif - double d; -} fd_twoints; - -#define __HI(x) x.ints.hi -#define __LO(x) x.ints.lo - -#undef __P -#ifdef __STDC__ -#define __P(p) p -#else -#define __P(p) () -#endif - -/* - * ANSI/POSIX - */ - -extern int signgam; - -#define MAXFLOAT ((float)3.40282346638528860e+38) - -enum fdversion {fdlibm_ieee = -1, fdlibm_svid, fdlibm_xopen, fdlibm_posix}; - -#define _LIB_VERSION_TYPE enum fdversion -#define _LIB_VERSION _fdlib_version - -/* if global variable _LIB_VERSION is not desirable, one may - * change the following to be a constant by: - * #define _LIB_VERSION_TYPE const enum version - * In that case, after one initializes the value _LIB_VERSION (see - * s_lib_version.c) during compile time, it cannot be modified - * in the middle of a program - */ -extern _LIB_VERSION_TYPE _LIB_VERSION; - -#define _IEEE_ fdlibm_ieee -#define _SVID_ fdlibm_svid -#define _XOPEN_ fdlibm_xopen -#define _POSIX_ fdlibm_posix - -struct exception { - int type; - char *name; - double arg1; - double arg2; - double retval; -}; - -#define HUGE MAXFLOAT - -/* - * set X_TLOSS = pi*2**52, which is possibly defined in - * (one may replace the following line by "#include ") - */ - -#define X_TLOSS 1.41484755040568800000e+16 - -#define DOMAIN 1 -#define SING 2 -#define OVERFLOW 3 -#define UNDERFLOW 4 -#define TLOSS 5 -#define PLOSS 6 - -/* - * ANSI/POSIX - */ - -extern double fd_acos __P((double)); -extern double fd_asin __P((double)); -extern double fd_atan __P((double)); -extern double fd_atan2 __P((double, double)); -extern double fd_cos __P((double)); -extern double fd_sin __P((double)); -extern double fd_tan __P((double)); - -extern double fd_cosh __P((double)); -extern double fd_sinh __P((double)); -extern double fd_tanh __P((double)); - -extern double fd_exp __P((double)); -extern double fd_frexp __P((double, int *)); -extern double fd_ldexp __P((double, int)); -extern double fd_log __P((double)); -extern double fd_log10 __P((double)); -extern double fd_modf __P((double, double *)); - -extern double fd_pow __P((double, 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_erf __P((double)); -extern double fd_erfc __P((double)); -extern double fd_gamma __P((double)); -extern double fd_hypot __P((double, double)); -extern int fd_isnan __P((double)); -extern int fd_finite __P((double)); -extern double fd_j0 __P((double)); -extern double fd_j1 __P((double)); -extern double fd_jn __P((int, double)); -extern double fd_lgamma __P((double)); -extern double fd_y0 __P((double)); -extern double fd_y1 __P((double)); -extern double fd_yn __P((int, double)); - -extern double fd_acosh __P((double)); -extern double fd_asinh __P((double)); -extern double fd_atanh __P((double)); -extern double fd_cbrt __P((double)); -extern double fd_logb __P((double)); -extern double fd_nextafter __P((double, double)); -extern double fd_remainder __P((double, double)); -#ifdef _SCALB_INT -extern double fd_scalb __P((double, int)); -#else -extern double fd_scalb __P((double, double)); -#endif - -extern int fd_matherr __P((struct exception *)); - -/* - * IEEE Test Vector - */ -extern double significand __P((double)); - -/* - * Functions callable from C, intended to support IEEE arithmetic. - */ -extern double fd_copysign __P((double, double)); -extern int fd_ilogb __P((double)); -extern double fd_rint __P((double)); -extern double fd_scalbn __P((double, int)); - -/* - * BSD math library entry points - */ -extern double fd_expm1 __P((double)); -extern double fd_log1p __P((double)); - -/* - * Reentrant version of gamma & lgamma; passes signgam back by reference - * as the second argument; user must allocate space for signgam. - */ -#ifdef _REENTRANT -extern double gamma_r __P((double, int *)); -extern double lgamma_r __P((double, int *)); -#endif /* _REENTRANT */ - -/* ieee style elementary functions */ -extern double __ieee754_sqrt __P((double)); -extern double __ieee754_acos __P((double)); -extern double __ieee754_acosh __P((double)); -extern double __ieee754_log __P((double)); -extern double __ieee754_atanh __P((double)); -extern double __ieee754_asin __P((double)); -extern double __ieee754_atan2 __P((double,double)); -extern double __ieee754_exp __P((double)); -extern double __ieee754_cosh __P((double)); -extern double __ieee754_fmod __P((double,double)); -extern double __ieee754_pow __P((double,double)); -extern double __ieee754_lgamma_r __P((double,int *)); -extern double __ieee754_gamma_r __P((double,int *)); -extern double __ieee754_lgamma __P((double)); -extern double __ieee754_gamma __P((double)); -extern double __ieee754_log10 __P((double)); -extern double __ieee754_sinh __P((double)); -extern double __ieee754_hypot __P((double,double)); -extern double __ieee754_j0 __P((double)); -extern double __ieee754_j1 __P((double)); -extern double __ieee754_y0 __P((double)); -extern double __ieee754_y1 __P((double)); -extern double __ieee754_jn __P((int,double)); -extern double __ieee754_yn __P((int,double)); -extern double __ieee754_remainder __P((double,double)); -extern int __ieee754_rem_pio2 __P((double,double*)); -#ifdef _SCALB_INT -extern double __ieee754_scalb __P((double,int)); -#else -extern double __ieee754_scalb __P((double,double)); -#endif - -/* fdlibm kernel function */ -extern double __kernel_standard __P((double,double,int,int*)); -extern double __kernel_sin __P((double,double,int)); -extern double __kernel_cos __P((double,double)); -extern double __kernel_tan __P((double,double,int)); -extern int __kernel_rem_pio2 __P((double*,double*,int,int,int,const int*)); diff --git a/js/src/fdlibm/fdlibm.mak b/js/src/fdlibm/fdlibm.mak deleted file mode 100644 index 6b8cfcb0db4e..000000000000 --- a/js/src/fdlibm/fdlibm.mak +++ /dev/null @@ -1,1453 +0,0 @@ -# Microsoft Developer Studio Generated NMAKE File, Format Version 4.20 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Static Library" 0x0104 - -!IF "$(CFG)" == "" -CFG=fdlibm - Win32 Debug -!MESSAGE No configuration specified. Defaulting to fdlibm - Win32 Debug. -!ENDIF - -!IF "$(CFG)" != "fdlibm - Win32 Release" && "$(CFG)" != "fdlibm - Win32 Debug" -!MESSAGE Invalid configuration "$(CFG)" specified. -!MESSAGE You can specify a configuration when running NMAKE on this makefile -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "fdlibm.mak" CFG="fdlibm - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "fdlibm - Win32 Release" (based on "Win32 (x86) Static Library") -!MESSAGE "fdlibm - Win32 Debug" (based on "Win32 (x86) Static Library") -!MESSAGE -!ERROR An invalid configuration is specified. -!ENDIF - -!IF "$(OS)" == "Windows_NT" -NULL= -!ELSE -NULL=nul -!ENDIF -################################################################################ -# Begin Project -CPP=cl.exe - -!IF "$(CFG)" == "fdlibm - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "fdlibm__" -# PROP BASE Intermediate_Dir "fdlibm__" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "fdlibm__" -# PROP Intermediate_Dir "fdlibm__" -# PROP Target_Dir "" -OUTDIR=.\fdlibm__ -INTDIR=.\fdlibm__ - -ALL : "$(OUTDIR)\fdlibm.lib" - -CLEAN : - -@erase "$(INTDIR)\e_acos.obj" - -@erase "$(INTDIR)\e_acosh.obj" - -@erase "$(INTDIR)\e_asin.obj" - -@erase "$(INTDIR)\e_atan2.obj" - -@erase "$(INTDIR)\e_atanh.obj" - -@erase "$(INTDIR)\e_cosh.obj" - -@erase "$(INTDIR)\e_exp.obj" - -@erase "$(INTDIR)\e_fmod.obj" - -@erase "$(INTDIR)\e_gamma.obj" - -@erase "$(INTDIR)\e_gamma_r.obj" - -@erase "$(INTDIR)\e_hypot.obj" - -@erase "$(INTDIR)\e_j0.obj" - -@erase "$(INTDIR)\e_j1.obj" - -@erase "$(INTDIR)\e_jn.obj" - -@erase "$(INTDIR)\e_lgamma.obj" - -@erase "$(INTDIR)\e_lgamma_r.obj" - -@erase "$(INTDIR)\e_log.obj" - -@erase "$(INTDIR)\e_log10.obj" - -@erase "$(INTDIR)\e_pow.obj" - -@erase "$(INTDIR)\e_rem_pio2.obj" - -@erase "$(INTDIR)\e_remainder.obj" - -@erase "$(INTDIR)\e_scalb.obj" - -@erase "$(INTDIR)\e_sinh.obj" - -@erase "$(INTDIR)\e_sqrt.obj" - -@erase "$(INTDIR)\k_cos.obj" - -@erase "$(INTDIR)\k_rem_pio2.obj" - -@erase "$(INTDIR)\k_sin.obj" - -@erase "$(INTDIR)\k_standard.obj" - -@erase "$(INTDIR)\k_tan.obj" - -@erase "$(INTDIR)\s_asinh.obj" - -@erase "$(INTDIR)\s_atan.obj" - -@erase "$(INTDIR)\s_cbrt.obj" - -@erase "$(INTDIR)\s_ceil.obj" - -@erase "$(INTDIR)\s_copysign.obj" - -@erase "$(INTDIR)\s_cos.obj" - -@erase "$(INTDIR)\s_erf.obj" - -@erase "$(INTDIR)\s_expm1.obj" - -@erase "$(INTDIR)\s_fabs.obj" - -@erase "$(INTDIR)\s_finite.obj" - -@erase "$(INTDIR)\s_floor.obj" - -@erase "$(INTDIR)\s_frexp.obj" - -@erase "$(INTDIR)\s_ilogb.obj" - -@erase "$(INTDIR)\s_isnan.obj" - -@erase "$(INTDIR)\s_ldexp.obj" - -@erase "$(INTDIR)\s_lib_version.obj" - -@erase "$(INTDIR)\s_log1p.obj" - -@erase "$(INTDIR)\s_logb.obj" - -@erase "$(INTDIR)\s_matherr.obj" - -@erase "$(INTDIR)\s_modf.obj" - -@erase "$(INTDIR)\s_nextafter.obj" - -@erase "$(INTDIR)\s_rint.obj" - -@erase "$(INTDIR)\s_scalbn.obj" - -@erase "$(INTDIR)\s_signgam.obj" - -@erase "$(INTDIR)\s_significand.obj" - -@erase "$(INTDIR)\s_sin.obj" - -@erase "$(INTDIR)\s_tan.obj" - -@erase "$(INTDIR)\s_tanh.obj" - -@erase "$(INTDIR)\w_acos.obj" - -@erase "$(INTDIR)\w_acosh.obj" - -@erase "$(INTDIR)\w_asin.obj" - -@erase "$(INTDIR)\w_atan2.obj" - -@erase "$(INTDIR)\w_atanh.obj" - -@erase "$(INTDIR)\w_cosh.obj" - -@erase "$(INTDIR)\w_exp.obj" - -@erase "$(INTDIR)\w_fmod.obj" - -@erase "$(INTDIR)\w_gamma.obj" - -@erase "$(INTDIR)\w_gamma_r.obj" - -@erase "$(INTDIR)\w_hypot.obj" - -@erase "$(INTDIR)\w_j0.obj" - -@erase "$(INTDIR)\w_j1.obj" - -@erase "$(INTDIR)\w_jn.obj" - -@erase "$(INTDIR)\w_lgamma.obj" - -@erase "$(INTDIR)\w_lgamma_r.obj" - -@erase "$(INTDIR)\w_log.obj" - -@erase "$(INTDIR)\w_log10.obj" - -@erase "$(INTDIR)\w_pow.obj" - -@erase "$(INTDIR)\w_remainder.obj" - -@erase "$(INTDIR)\w_scalb.obj" - -@erase "$(INTDIR)\w_sinh.obj" - -@erase "$(INTDIR)\w_sqrt.obj" - -@erase "$(OUTDIR)\fdlibm.lib" - -"$(OUTDIR)" : - if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" - -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c -# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c -CPP_PROJ=/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\ - /Fp"$(INTDIR)/fdlibm.pch" /YX /Fo"$(INTDIR)/" /c -CPP_OBJS=.\fdlibm__/ -CPP_SBRS=.\. -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o"$(OUTDIR)/fdlibm.bsc" -BSC32_SBRS= \ - -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo -LIB32_FLAGS=/nologo /out:"$(OUTDIR)/fdlibm.lib" -LIB32_OBJS= \ - "$(INTDIR)\e_acos.obj" \ - "$(INTDIR)\e_acosh.obj" \ - "$(INTDIR)\e_asin.obj" \ - "$(INTDIR)\e_atan2.obj" \ - "$(INTDIR)\e_atanh.obj" \ - "$(INTDIR)\e_cosh.obj" \ - "$(INTDIR)\e_exp.obj" \ - "$(INTDIR)\e_fmod.obj" \ - "$(INTDIR)\e_gamma.obj" \ - "$(INTDIR)\e_gamma_r.obj" \ - "$(INTDIR)\e_hypot.obj" \ - "$(INTDIR)\e_j0.obj" \ - "$(INTDIR)\e_j1.obj" \ - "$(INTDIR)\e_jn.obj" \ - "$(INTDIR)\e_lgamma.obj" \ - "$(INTDIR)\e_lgamma_r.obj" \ - "$(INTDIR)\e_log.obj" \ - "$(INTDIR)\e_log10.obj" \ - "$(INTDIR)\e_pow.obj" \ - "$(INTDIR)\e_rem_pio2.obj" \ - "$(INTDIR)\e_remainder.obj" \ - "$(INTDIR)\e_scalb.obj" \ - "$(INTDIR)\e_sinh.obj" \ - "$(INTDIR)\e_sqrt.obj" \ - "$(INTDIR)\k_cos.obj" \ - "$(INTDIR)\k_rem_pio2.obj" \ - "$(INTDIR)\k_sin.obj" \ - "$(INTDIR)\k_standard.obj" \ - "$(INTDIR)\k_tan.obj" \ - "$(INTDIR)\s_asinh.obj" \ - "$(INTDIR)\s_atan.obj" \ - "$(INTDIR)\s_cbrt.obj" \ - "$(INTDIR)\s_ceil.obj" \ - "$(INTDIR)\s_copysign.obj" \ - "$(INTDIR)\s_cos.obj" \ - "$(INTDIR)\s_erf.obj" \ - "$(INTDIR)\s_expm1.obj" \ - "$(INTDIR)\s_fabs.obj" \ - "$(INTDIR)\s_finite.obj" \ - "$(INTDIR)\s_floor.obj" \ - "$(INTDIR)\s_frexp.obj" \ - "$(INTDIR)\s_ilogb.obj" \ - "$(INTDIR)\s_isnan.obj" \ - "$(INTDIR)\s_ldexp.obj" \ - "$(INTDIR)\s_lib_version.obj" \ - "$(INTDIR)\s_log1p.obj" \ - "$(INTDIR)\s_logb.obj" \ - "$(INTDIR)\s_matherr.obj" \ - "$(INTDIR)\s_modf.obj" \ - "$(INTDIR)\s_nextafter.obj" \ - "$(INTDIR)\s_rint.obj" \ - "$(INTDIR)\s_scalbn.obj" \ - "$(INTDIR)\s_signgam.obj" \ - "$(INTDIR)\s_significand.obj" \ - "$(INTDIR)\s_sin.obj" \ - "$(INTDIR)\s_tan.obj" \ - "$(INTDIR)\s_tanh.obj" \ - "$(INTDIR)\w_acos.obj" \ - "$(INTDIR)\w_acosh.obj" \ - "$(INTDIR)\w_asin.obj" \ - "$(INTDIR)\w_atan2.obj" \ - "$(INTDIR)\w_atanh.obj" \ - "$(INTDIR)\w_cosh.obj" \ - "$(INTDIR)\w_exp.obj" \ - "$(INTDIR)\w_fmod.obj" \ - "$(INTDIR)\w_gamma.obj" \ - "$(INTDIR)\w_gamma_r.obj" \ - "$(INTDIR)\w_hypot.obj" \ - "$(INTDIR)\w_j0.obj" \ - "$(INTDIR)\w_j1.obj" \ - "$(INTDIR)\w_jn.obj" \ - "$(INTDIR)\w_lgamma.obj" \ - "$(INTDIR)\w_lgamma_r.obj" \ - "$(INTDIR)\w_log.obj" \ - "$(INTDIR)\w_log10.obj" \ - "$(INTDIR)\w_pow.obj" \ - "$(INTDIR)\w_remainder.obj" \ - "$(INTDIR)\w_scalb.obj" \ - "$(INTDIR)\w_sinh.obj" \ - "$(INTDIR)\w_sqrt.obj" - -"$(OUTDIR)\fdlibm.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS) - $(LIB32) @<< - $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS) -<< - -!ELSEIF "$(CFG)" == "fdlibm - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "fdlibm_0" -# PROP BASE Intermediate_Dir "fdlibm_0" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "fdlibm_0" -# PROP Intermediate_Dir "fdlibm_0" -# PROP Target_Dir "" -OUTDIR=.\fdlibm_0 -INTDIR=.\fdlibm_0 - -ALL : "$(OUTDIR)\fdlibm.lib" - -CLEAN : - -@erase "$(INTDIR)\e_acos.obj" - -@erase "$(INTDIR)\e_acosh.obj" - -@erase "$(INTDIR)\e_asin.obj" - -@erase "$(INTDIR)\e_atan2.obj" - -@erase "$(INTDIR)\e_atanh.obj" - -@erase "$(INTDIR)\e_cosh.obj" - -@erase "$(INTDIR)\e_exp.obj" - -@erase "$(INTDIR)\e_fmod.obj" - -@erase "$(INTDIR)\e_gamma.obj" - -@erase "$(INTDIR)\e_gamma_r.obj" - -@erase "$(INTDIR)\e_hypot.obj" - -@erase "$(INTDIR)\e_j0.obj" - -@erase "$(INTDIR)\e_j1.obj" - -@erase "$(INTDIR)\e_jn.obj" - -@erase "$(INTDIR)\e_lgamma.obj" - -@erase "$(INTDIR)\e_lgamma_r.obj" - -@erase "$(INTDIR)\e_log.obj" - -@erase "$(INTDIR)\e_log10.obj" - -@erase "$(INTDIR)\e_pow.obj" - -@erase "$(INTDIR)\e_rem_pio2.obj" - -@erase "$(INTDIR)\e_remainder.obj" - -@erase "$(INTDIR)\e_scalb.obj" - -@erase "$(INTDIR)\e_sinh.obj" - -@erase "$(INTDIR)\e_sqrt.obj" - -@erase "$(INTDIR)\k_cos.obj" - -@erase "$(INTDIR)\k_rem_pio2.obj" - -@erase "$(INTDIR)\k_sin.obj" - -@erase "$(INTDIR)\k_standard.obj" - -@erase "$(INTDIR)\k_tan.obj" - -@erase "$(INTDIR)\s_asinh.obj" - -@erase "$(INTDIR)\s_atan.obj" - -@erase "$(INTDIR)\s_cbrt.obj" - -@erase "$(INTDIR)\s_ceil.obj" - -@erase "$(INTDIR)\s_copysign.obj" - -@erase "$(INTDIR)\s_cos.obj" - -@erase "$(INTDIR)\s_erf.obj" - -@erase "$(INTDIR)\s_expm1.obj" - -@erase "$(INTDIR)\s_fabs.obj" - -@erase "$(INTDIR)\s_finite.obj" - -@erase "$(INTDIR)\s_floor.obj" - -@erase "$(INTDIR)\s_frexp.obj" - -@erase "$(INTDIR)\s_ilogb.obj" - -@erase "$(INTDIR)\s_isnan.obj" - -@erase "$(INTDIR)\s_ldexp.obj" - -@erase "$(INTDIR)\s_lib_version.obj" - -@erase "$(INTDIR)\s_log1p.obj" - -@erase "$(INTDIR)\s_logb.obj" - -@erase "$(INTDIR)\s_matherr.obj" - -@erase "$(INTDIR)\s_modf.obj" - -@erase "$(INTDIR)\s_nextafter.obj" - -@erase "$(INTDIR)\s_rint.obj" - -@erase "$(INTDIR)\s_scalbn.obj" - -@erase "$(INTDIR)\s_signgam.obj" - -@erase "$(INTDIR)\s_significand.obj" - -@erase "$(INTDIR)\s_sin.obj" - -@erase "$(INTDIR)\s_tan.obj" - -@erase "$(INTDIR)\s_tanh.obj" - -@erase "$(INTDIR)\w_acos.obj" - -@erase "$(INTDIR)\w_acosh.obj" - -@erase "$(INTDIR)\w_asin.obj" - -@erase "$(INTDIR)\w_atan2.obj" - -@erase "$(INTDIR)\w_atanh.obj" - -@erase "$(INTDIR)\w_cosh.obj" - -@erase "$(INTDIR)\w_exp.obj" - -@erase "$(INTDIR)\w_fmod.obj" - -@erase "$(INTDIR)\w_gamma.obj" - -@erase "$(INTDIR)\w_gamma_r.obj" - -@erase "$(INTDIR)\w_hypot.obj" - -@erase "$(INTDIR)\w_j0.obj" - -@erase "$(INTDIR)\w_j1.obj" - -@erase "$(INTDIR)\w_jn.obj" - -@erase "$(INTDIR)\w_lgamma.obj" - -@erase "$(INTDIR)\w_lgamma_r.obj" - -@erase "$(INTDIR)\w_log.obj" - -@erase "$(INTDIR)\w_log10.obj" - -@erase "$(INTDIR)\w_pow.obj" - -@erase "$(INTDIR)\w_remainder.obj" - -@erase "$(INTDIR)\w_scalb.obj" - -@erase "$(INTDIR)\w_sinh.obj" - -@erase "$(INTDIR)\w_sqrt.obj" - -@erase "$(OUTDIR)\fdlibm.lib" - -"$(OUTDIR)" : - if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" - -# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c -# ADD CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c -CPP_PROJ=/nologo /MLd /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS"\ - /Fp"$(INTDIR)/fdlibm.pch" /YX /Fo"$(INTDIR)/" /c -CPP_OBJS=.\fdlibm_0/ -CPP_SBRS=.\. -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o"$(OUTDIR)/fdlibm.bsc" -BSC32_SBRS= \ - -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo -LIB32_FLAGS=/nologo /out:"$(OUTDIR)/fdlibm.lib" -LIB32_OBJS= \ - "$(INTDIR)\e_acos.obj" \ - "$(INTDIR)\e_acosh.obj" \ - "$(INTDIR)\e_asin.obj" \ - "$(INTDIR)\e_atan2.obj" \ - "$(INTDIR)\e_atanh.obj" \ - "$(INTDIR)\e_cosh.obj" \ - "$(INTDIR)\e_exp.obj" \ - "$(INTDIR)\e_fmod.obj" \ - "$(INTDIR)\e_gamma.obj" \ - "$(INTDIR)\e_gamma_r.obj" \ - "$(INTDIR)\e_hypot.obj" \ - "$(INTDIR)\e_j0.obj" \ - "$(INTDIR)\e_j1.obj" \ - "$(INTDIR)\e_jn.obj" \ - "$(INTDIR)\e_lgamma.obj" \ - "$(INTDIR)\e_lgamma_r.obj" \ - "$(INTDIR)\e_log.obj" \ - "$(INTDIR)\e_log10.obj" \ - "$(INTDIR)\e_pow.obj" \ - "$(INTDIR)\e_rem_pio2.obj" \ - "$(INTDIR)\e_remainder.obj" \ - "$(INTDIR)\e_scalb.obj" \ - "$(INTDIR)\e_sinh.obj" \ - "$(INTDIR)\e_sqrt.obj" \ - "$(INTDIR)\k_cos.obj" \ - "$(INTDIR)\k_rem_pio2.obj" \ - "$(INTDIR)\k_sin.obj" \ - "$(INTDIR)\k_standard.obj" \ - "$(INTDIR)\k_tan.obj" \ - "$(INTDIR)\s_asinh.obj" \ - "$(INTDIR)\s_atan.obj" \ - "$(INTDIR)\s_cbrt.obj" \ - "$(INTDIR)\s_ceil.obj" \ - "$(INTDIR)\s_copysign.obj" \ - "$(INTDIR)\s_cos.obj" \ - "$(INTDIR)\s_erf.obj" \ - "$(INTDIR)\s_expm1.obj" \ - "$(INTDIR)\s_fabs.obj" \ - "$(INTDIR)\s_finite.obj" \ - "$(INTDIR)\s_floor.obj" \ - "$(INTDIR)\s_frexp.obj" \ - "$(INTDIR)\s_ilogb.obj" \ - "$(INTDIR)\s_isnan.obj" \ - "$(INTDIR)\s_ldexp.obj" \ - "$(INTDIR)\s_lib_version.obj" \ - "$(INTDIR)\s_log1p.obj" \ - "$(INTDIR)\s_logb.obj" \ - "$(INTDIR)\s_matherr.obj" \ - "$(INTDIR)\s_modf.obj" \ - "$(INTDIR)\s_nextafter.obj" \ - "$(INTDIR)\s_rint.obj" \ - "$(INTDIR)\s_scalbn.obj" \ - "$(INTDIR)\s_signgam.obj" \ - "$(INTDIR)\s_significand.obj" \ - "$(INTDIR)\s_sin.obj" \ - "$(INTDIR)\s_tan.obj" \ - "$(INTDIR)\s_tanh.obj" \ - "$(INTDIR)\w_acos.obj" \ - "$(INTDIR)\w_acosh.obj" \ - "$(INTDIR)\w_asin.obj" \ - "$(INTDIR)\w_atan2.obj" \ - "$(INTDIR)\w_atanh.obj" \ - "$(INTDIR)\w_cosh.obj" \ - "$(INTDIR)\w_exp.obj" \ - "$(INTDIR)\w_fmod.obj" \ - "$(INTDIR)\w_gamma.obj" \ - "$(INTDIR)\w_gamma_r.obj" \ - "$(INTDIR)\w_hypot.obj" \ - "$(INTDIR)\w_j0.obj" \ - "$(INTDIR)\w_j1.obj" \ - "$(INTDIR)\w_jn.obj" \ - "$(INTDIR)\w_lgamma.obj" \ - "$(INTDIR)\w_lgamma_r.obj" \ - "$(INTDIR)\w_log.obj" \ - "$(INTDIR)\w_log10.obj" \ - "$(INTDIR)\w_pow.obj" \ - "$(INTDIR)\w_remainder.obj" \ - "$(INTDIR)\w_scalb.obj" \ - "$(INTDIR)\w_sinh.obj" \ - "$(INTDIR)\w_sqrt.obj" - -"$(OUTDIR)\fdlibm.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS) - $(LIB32) @<< - $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS) -<< - -!ENDIF - -.c{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.c{$(CPP_SBRS)}.sbr: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_SBRS)}.sbr: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_SBRS)}.sbr: - $(CPP) $(CPP_PROJ) $< - -################################################################################ -# Begin Target - -# Name "fdlibm - Win32 Release" -# Name "fdlibm - Win32 Debug" - -!IF "$(CFG)" == "fdlibm - Win32 Release" - -!ELSEIF "$(CFG)" == "fdlibm - Win32 Debug" - -!ENDIF - -################################################################################ -# Begin Source File - -SOURCE=.\w_sqrt.c -DEP_CPP_W_SQR=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_sqrt.obj" : $(SOURCE) $(DEP_CPP_W_SQR) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_acosh.c -DEP_CPP_E_ACO=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_acosh.obj" : $(SOURCE) $(DEP_CPP_E_ACO) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_asin.c -DEP_CPP_E_ASI=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_asin.obj" : $(SOURCE) $(DEP_CPP_E_ASI) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_atan2.c -DEP_CPP_E_ATA=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_atan2.obj" : $(SOURCE) $(DEP_CPP_E_ATA) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_atanh.c -DEP_CPP_E_ATAN=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_atanh.obj" : $(SOURCE) $(DEP_CPP_E_ATAN) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_cosh.c -DEP_CPP_E_COS=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_cosh.obj" : $(SOURCE) $(DEP_CPP_E_COS) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_exp.c -DEP_CPP_E_EXP=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_exp.obj" : $(SOURCE) $(DEP_CPP_E_EXP) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_fmod.c -DEP_CPP_E_FMO=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_fmod.obj" : $(SOURCE) $(DEP_CPP_E_FMO) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_gamma.c -DEP_CPP_E_GAM=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_gamma.obj" : $(SOURCE) $(DEP_CPP_E_GAM) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_gamma_r.c -DEP_CPP_E_GAMM=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_gamma_r.obj" : $(SOURCE) $(DEP_CPP_E_GAMM) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_hypot.c -DEP_CPP_E_HYP=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_hypot.obj" : $(SOURCE) $(DEP_CPP_E_HYP) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_j0.c -DEP_CPP_E_J0_=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_j0.obj" : $(SOURCE) $(DEP_CPP_E_J0_) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_j1.c -DEP_CPP_E_J1_=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_j1.obj" : $(SOURCE) $(DEP_CPP_E_J1_) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_jn.c -DEP_CPP_E_JN_=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_jn.obj" : $(SOURCE) $(DEP_CPP_E_JN_) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_lgamma.c -DEP_CPP_E_LGA=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_lgamma.obj" : $(SOURCE) $(DEP_CPP_E_LGA) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_lgamma_r.c -DEP_CPP_E_LGAM=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_lgamma_r.obj" : $(SOURCE) $(DEP_CPP_E_LGAM) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_log.c -DEP_CPP_E_LOG=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_log.obj" : $(SOURCE) $(DEP_CPP_E_LOG) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_log10.c -DEP_CPP_E_LOG1=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_log10.obj" : $(SOURCE) $(DEP_CPP_E_LOG1) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_pow.c -DEP_CPP_E_POW=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_pow.obj" : $(SOURCE) $(DEP_CPP_E_POW) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_rem_pio2.c -DEP_CPP_E_REM=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_rem_pio2.obj" : $(SOURCE) $(DEP_CPP_E_REM) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_remainder.c -DEP_CPP_E_REMA=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_remainder.obj" : $(SOURCE) $(DEP_CPP_E_REMA) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_scalb.c -DEP_CPP_E_SCA=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_scalb.obj" : $(SOURCE) $(DEP_CPP_E_SCA) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_sinh.c -DEP_CPP_E_SIN=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_sinh.obj" : $(SOURCE) $(DEP_CPP_E_SIN) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_sqrt.c -DEP_CPP_E_SQR=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_sqrt.obj" : $(SOURCE) $(DEP_CPP_E_SQR) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\fdlibm.h - -!IF "$(CFG)" == "fdlibm - Win32 Release" - -!ELSEIF "$(CFG)" == "fdlibm - Win32 Debug" - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\k_cos.c -DEP_CPP_K_COS=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\k_cos.obj" : $(SOURCE) $(DEP_CPP_K_COS) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\k_rem_pio2.c -DEP_CPP_K_REM=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\k_rem_pio2.obj" : $(SOURCE) $(DEP_CPP_K_REM) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\k_sin.c -DEP_CPP_K_SIN=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\k_sin.obj" : $(SOURCE) $(DEP_CPP_K_SIN) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\k_standard.c -DEP_CPP_K_STA=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\k_standard.obj" : $(SOURCE) $(DEP_CPP_K_STA) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\k_tan.c -DEP_CPP_K_TAN=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\k_tan.obj" : $(SOURCE) $(DEP_CPP_K_TAN) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_asinh.c -DEP_CPP_S_ASI=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_asinh.obj" : $(SOURCE) $(DEP_CPP_S_ASI) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_atan.c -DEP_CPP_S_ATA=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_atan.obj" : $(SOURCE) $(DEP_CPP_S_ATA) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_cbrt.c -DEP_CPP_S_CBR=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_cbrt.obj" : $(SOURCE) $(DEP_CPP_S_CBR) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_ceil.c -DEP_CPP_S_CEI=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_ceil.obj" : $(SOURCE) $(DEP_CPP_S_CEI) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_copysign.c -DEP_CPP_S_COP=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_copysign.obj" : $(SOURCE) $(DEP_CPP_S_COP) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_cos.c -DEP_CPP_S_COS=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_cos.obj" : $(SOURCE) $(DEP_CPP_S_COS) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_erf.c -DEP_CPP_S_ERF=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_erf.obj" : $(SOURCE) $(DEP_CPP_S_ERF) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_expm1.c -DEP_CPP_S_EXP=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_expm1.obj" : $(SOURCE) $(DEP_CPP_S_EXP) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_fabs.c -DEP_CPP_S_FAB=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_fabs.obj" : $(SOURCE) $(DEP_CPP_S_FAB) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_finite.c -DEP_CPP_S_FIN=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_finite.obj" : $(SOURCE) $(DEP_CPP_S_FIN) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_floor.c -DEP_CPP_S_FLO=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_floor.obj" : $(SOURCE) $(DEP_CPP_S_FLO) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_frexp.c -DEP_CPP_S_FRE=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_frexp.obj" : $(SOURCE) $(DEP_CPP_S_FRE) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_ilogb.c -DEP_CPP_S_ILO=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_ilogb.obj" : $(SOURCE) $(DEP_CPP_S_ILO) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_isnan.c -DEP_CPP_S_ISN=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_isnan.obj" : $(SOURCE) $(DEP_CPP_S_ISN) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_ldexp.c -DEP_CPP_S_LDE=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_ldexp.obj" : $(SOURCE) $(DEP_CPP_S_LDE) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_lib_version.c -DEP_CPP_S_LIB=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_lib_version.obj" : $(SOURCE) $(DEP_CPP_S_LIB) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_log1p.c -DEP_CPP_S_LOG=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_log1p.obj" : $(SOURCE) $(DEP_CPP_S_LOG) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_logb.c -DEP_CPP_S_LOGB=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_logb.obj" : $(SOURCE) $(DEP_CPP_S_LOGB) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_matherr.c -DEP_CPP_S_MAT=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_matherr.obj" : $(SOURCE) $(DEP_CPP_S_MAT) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_modf.c -DEP_CPP_S_MOD=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_modf.obj" : $(SOURCE) $(DEP_CPP_S_MOD) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_nextafter.c -DEP_CPP_S_NEX=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_nextafter.obj" : $(SOURCE) $(DEP_CPP_S_NEX) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_rint.c -DEP_CPP_S_RIN=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_rint.obj" : $(SOURCE) $(DEP_CPP_S_RIN) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_scalbn.c -DEP_CPP_S_SCA=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_scalbn.obj" : $(SOURCE) $(DEP_CPP_S_SCA) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_signgam.c -DEP_CPP_S_SIG=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_signgam.obj" : $(SOURCE) $(DEP_CPP_S_SIG) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_significand.c -DEP_CPP_S_SIGN=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_significand.obj" : $(SOURCE) $(DEP_CPP_S_SIGN) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_sin.c -DEP_CPP_S_SIN=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_sin.obj" : $(SOURCE) $(DEP_CPP_S_SIN) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_tan.c -DEP_CPP_S_TAN=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_tan.obj" : $(SOURCE) $(DEP_CPP_S_TAN) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\s_tanh.c -DEP_CPP_S_TANH=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\s_tanh.obj" : $(SOURCE) $(DEP_CPP_S_TANH) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_acos.c -DEP_CPP_W_ACO=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_acos.obj" : $(SOURCE) $(DEP_CPP_W_ACO) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_acosh.c -DEP_CPP_W_ACOS=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_acosh.obj" : $(SOURCE) $(DEP_CPP_W_ACOS) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_asin.c -DEP_CPP_W_ASI=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_asin.obj" : $(SOURCE) $(DEP_CPP_W_ASI) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_atan2.c -DEP_CPP_W_ATA=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_atan2.obj" : $(SOURCE) $(DEP_CPP_W_ATA) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_atanh.c -DEP_CPP_W_ATAN=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_atanh.obj" : $(SOURCE) $(DEP_CPP_W_ATAN) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_cosh.c -DEP_CPP_W_COS=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_cosh.obj" : $(SOURCE) $(DEP_CPP_W_COS) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_exp.c -DEP_CPP_W_EXP=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_exp.obj" : $(SOURCE) $(DEP_CPP_W_EXP) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_fmod.c -DEP_CPP_W_FMO=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_fmod.obj" : $(SOURCE) $(DEP_CPP_W_FMO) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_gamma.c -DEP_CPP_W_GAM=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_gamma.obj" : $(SOURCE) $(DEP_CPP_W_GAM) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_gamma_r.c -DEP_CPP_W_GAMM=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_gamma_r.obj" : $(SOURCE) $(DEP_CPP_W_GAMM) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_hypot.c -DEP_CPP_W_HYP=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_hypot.obj" : $(SOURCE) $(DEP_CPP_W_HYP) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_j0.c -DEP_CPP_W_J0_=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_j0.obj" : $(SOURCE) $(DEP_CPP_W_J0_) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_j1.c -DEP_CPP_W_J1_=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_j1.obj" : $(SOURCE) $(DEP_CPP_W_J1_) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_jn.c -DEP_CPP_W_JN_=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_jn.obj" : $(SOURCE) $(DEP_CPP_W_JN_) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_lgamma.c -DEP_CPP_W_LGA=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_lgamma.obj" : $(SOURCE) $(DEP_CPP_W_LGA) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_lgamma_r.c -DEP_CPP_W_LGAM=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_lgamma_r.obj" : $(SOURCE) $(DEP_CPP_W_LGAM) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_log.c -DEP_CPP_W_LOG=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_log.obj" : $(SOURCE) $(DEP_CPP_W_LOG) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_log10.c -DEP_CPP_W_LOG1=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_log10.obj" : $(SOURCE) $(DEP_CPP_W_LOG1) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_pow.c -DEP_CPP_W_POW=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_pow.obj" : $(SOURCE) $(DEP_CPP_W_POW) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_remainder.c -DEP_CPP_W_REM=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_remainder.obj" : $(SOURCE) $(DEP_CPP_W_REM) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_scalb.c -DEP_CPP_W_SCA=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_scalb.obj" : $(SOURCE) $(DEP_CPP_W_SCA) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\w_sinh.c -DEP_CPP_W_SIN=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\w_sinh.obj" : $(SOURCE) $(DEP_CPP_W_SIN) "$(INTDIR)" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\e_acos.c -DEP_CPP_E_ACOS=\ - ".\fdlibm.h"\ - - -"$(INTDIR)\e_acos.obj" : $(SOURCE) $(DEP_CPP_E_ACOS) "$(INTDIR)" - - -# End Source File -# End Target -# End Project -################################################################################ diff --git a/js/src/fdlibm/fdlibm.mdp b/js/src/fdlibm/fdlibm.mdp deleted file mode 100644 index 5904c494072aa975bf949afb4b7106a01b9705e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42143 zcmeHQTXP&o6+RQovSdfLjPFUD41#cTEcp@$1QKFNmXVQc6B86DQB$MYUTLk}on>b2 zwJ07^#VZ$cEq(w$B7Sqh3spSu7xEmccredgPTyu`HRrTkRDvC=w@T}Ef2Vu8Pv1^| z-F@cj%`4~jzzBQ?;2H3rU8jNn_|LA^zz4g!^uF*5a29UBXW%4AT^v;3UMsst1LcJG z@7+^qU(!MYBe1V*0#nUKyS3JdqE-E48vi#HPVApH|3_dDK=rBq>Wog;*Aou>k+!ne7c zXn@R0J6$J|$I$asUV7<(kj_LW>a|iz?+C@MZbML7$dkCeMkI$dOH~!wKsF<+!CD%d z5u2sWh-x?(iVdd`XZ8Bsj1Z|kA&+7*n;1@uCu>CW&Z9)M+C<_>+S|%o>(q0p^5&7q znnW_#j63z#lSj>Xt*$f-ZgpFIL8Q}cr)j+gF+xUllssx-`>EF~hUZ;Um+c0f4vrJi z9g*d&l+uK3r1fr^N6f=JaeqT(R57qyQ`+l_yZyM?C)#cvWvy<#1Lu)y(o|k$Wn%9n zbSsfovz1`;BT*_fx`|72b1Dd|3Gm}z23ofIF$@Junr=so(B;*unr=6 zI5XkIXf}xGfpriO11kpBy9Nf<^*xA~fz<+JRNa*H=54Xs*gXJ#nLm z%qWlQ;yH0wY*pc?O-BN{P4EI(e-7}x3q0olb;IIQ-Z|$xWnA?E{sFS%@Tlr-JS;o! zh9kP}+>ZEiOmM)?#~afwfuHVsEeIyZKsLGeKYR#BCiVl&bW?0JX*jdI6wa(%3}>#q z8_rz65YEhpQ!9(tE?$^YKd;SSo_*(v{vBcX{PmTa_`ii-VO!1^+p?EzAn<)mWg#s= z3`)@AoFdz_>Kk0~OpkKFsw47v*@<}>SFgfRMhzN#Y{c2xsf z->d9!%}3s;SJ^3oPr=!%^mN2W-l18$dzGCs`Q)Vq>Cl{B`8cA>5uJl`X|?iQUcrvY zuAHHjQ!!ci3|N!LAt8GXuL5Ib@$pLojh9ijodY&TAuoZQYt5l4**E!-8I9433F~-> zGJttp8_o`Vhg@nyosX{#dKDoz;XG)qwa=Ytd$%I$W>M{b$>K? zCYa2GoPh5B;~_{=Vinh5a%sj#mfhS1D}#%Ru2+vdS}Z#qB92j_ve4xdaH&sd-i3>d zurwzfuygWL7NxOZ`80~PIxpgyAH@#yqr%A|?1fRJsm5R&&=NTS&%#8>S@~a2y#~f% z4+Ma1U@sQ6VgBC5?dp3N`l(9sU%~&&&nW(Fms5cGvT`Fk$o&QJ-{aq&N0gI~cRg38 zCqHth{ZZtktW1+ww+dznEvO|l2G*C*7+7CIV;|HeW}V>m++@Lydu|eEW6w=iwng&D zbCX5)z!jBTmuw$G>_UqU_uM3*Fi9BH)g_lQo||MiqGFojjZ`zm@dBQkBnV|Ui-H@# zYU6=ds*^>r`^Q{#&rRA523|w1wU_56$%Uol6+Ab|H7UOs0F(y~2H_1C6oLFup zS(>NKemHmLOue3E8+R4LH#JHD7oCfu$ zBg=Ev{&eKf`EukAsTQMyDeBNOkOXf?Z|zi09uaXo16e;?DQQ{W+Vu=1uN!|l(w~l` zPj@PYlI>NMF^X$kR>YBpgV$H5%=x78TsjZB&m5P>;Q18vz|7-WRX$AiPPf2@9nr^wCl6H{Zo{}b67EeigO1gBzgOszUq!~Wacwplu zX6v|(!#ySa1XI$Vg_n_c`8<39z6f7}Gw_Nfr2N0TKm+57ft1G~kLyKrcs5*VbuV7P zQI7}!MGK`rL8v#g5WtaV`?42 zMb*|4_gu4r34#~Nloc$OKwNxt03irYk@4mFi^b5}3yYyUl^{4xrfK(*g5V_wt}{*R zOC6%(N~Ev2;?wE4>Z%*}=+aF|5QJprDxSW$3}~-?m;t((X>ThmDqZ9B5GKt{mvl8Y!k@y3BSm=TPmsheeg!AG+A`sIc*|iY248 zrVkUdp!B$kAT^rcfn)9Oh|8Grae$GjK2RPf;1V~s9}6p|tZde_Z&n^wE?QYwdum0P z+6o@#fB7`D%PdYg*hkUf7CmU8KLmRug^R8))zMuvk18(1xCE4ISA0HQImW{)o4>;A z8KRx;GUr3hB8_@zkg3fVv(pBuIiAMZA8u)&N|bi>rz``vhTyuZ5H0VSi8OM?Ym)LyxzXs?w#1#wvF>* zx?5EbTG6e4$eA78x$sJ=_J_x{Z*SiX*O<5OY93JvZjWwa2z&cZP7%}uoxJX;*T>qhm*J-kg0K@5CQ~x$nl=y67+VMaKloi=+jsh(2WJ7Vx%n z1wSy2uS>99j=*L7f>LtTSNT?Jn#Yo^|G6lskvY;dxSx~O92=G~%Y(X;;0tZV0wZ-shJD35E#k-;tJNU0fBWNAktHWqS-cO*nq z0-A9kP?bQ1c_c(s0-7r!P}EP!JrcOoPhp+1xZxjpTr-dajs+N^APEsHfaM@LRFjYd zs)}b>NCMZzGdv`LV=t)?k%WMHfMp_C+?c8yZn;PnH)JG-TQ-uw56c4JnStW{QRHBt zN+G){y6~r3u~ribNJf%)3XXDBN|KUL?Z}Xl1de@q*lHzYbS?}pN#LroR9|PtJeAFo znIw`>>Kdjd2`SYg**>XIw!`T{Ancf~&<528Eb(ltDh<2iv$@mpozrQ_QWDRX`7d}% z0>{!@qLM&$Z0B@Za+OqknfgxCX~|X+Dd2Q!%vl!Xr&El{G%ajE4bekN6XxbcPoV3bZn7mk zGvSL7L}rZ1v2rdwRF#u9r4iXXc69#g%14=&PEmj3n;5wxF+;WnbLyr_pRpn?Pon?( zTO6dbO^khiBpAV$draHwinTYFS(}f|p5q$7@^sJZ$Dc%ImHLsm=f%{eLsjh#5QZqT zpTHHoz1YhCFmev$AF(lS-$%*SUqPucg(w&~9)Buck3*kUMicZC@P3>(M&zq~I+=a9 zoODlOJhMn)&|Up{95b*MRtKx2|HH_t*_-w}PH*4Qdhzz1x9{`<35~CYaa{03UKGARD)*5ZO?y~m`!V<7BYET;lSlrd kFsYbN!bOrR@GV$`tMF}Df@Qb{*B=)Z<)8Z)G%ybT1)S%zeE 0.3, let qx = |x|/4 with - * the last 32 bits mask off, and if x > 0.78125, let qx = 0.28125. - * Then - * cos(x+y) = (1-qx) - ((x*x/2-qx) - (r-x*y)). - * Note that 1-qx and (x*x/2-qx) is EXACT here, and the - * magnitude of the latter is at least a quarter of x*x/2, - * thus, reducing the rounding error in the subtraction. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif -one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ -C1 = 4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */ -C2 = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */ -C3 = 2.48015872894767294178e-05, /* 0x3EFA01A0, 0x19CB1590 */ -C4 = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */ -C5 = 2.08757232129817482790e-09, /* 0x3E21EE9E, 0xBDB4B1C4 */ -C6 = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */ - -#ifdef __STDC__ - double __kernel_cos(double x, double y) -#else - double __kernel_cos(x, y) - double x,y; -#endif -{ - fd_twoints u; - double qx = 0; - double a,hz,z,r; - int ix; - u.d = x; - ix = __HI(u)&0x7fffffff; /* ix = |x|'s high word*/ - if(ix<0x3e400000) { /* if x < 2**27 */ - if(((int)x)==0) return one; /* generate inexact */ - } - z = x*x; - r = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*C6))))); - if(ix < 0x3FD33333) /* if |x| < 0.3 */ - return one - (0.5*z - (z*r - x*y)); - else { - if(ix > 0x3fe90000) { /* x > 0.78125 */ - qx = 0.28125; - } else { - u.d = qx; - __HI(u) = ix-0x00200000; /* x/4 */ - __LO(u) = 0; - qx = u.d; - } - hz = 0.5*z-qx; - a = one-qx; - return a - (hz - (z*r-x*y)); - } -} diff --git a/js/src/fdlibm/k_rem_pio2.c b/js/src/fdlibm/k_rem_pio2.c deleted file mode 100644 index d261e190af4e..000000000000 --- a/js/src/fdlibm/k_rem_pio2.c +++ /dev/null @@ -1,354 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)k_rem_pio2.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * __kernel_rem_pio2(x,y,e0,nx,prec,ipio2) - * double x[],y[]; int e0,nx,prec; int ipio2[]; - * - * __kernel_rem_pio2 return the last three digits of N with - * y = x - N*pi/2 - * so that |y| < pi/2. - * - * The method is to compute the integer (mod 8) and fraction parts of - * (2/pi)*x without doing the full multiplication. In general we - * skip the part of the product that are known to be a huge integer ( - * more accurately, = 0 mod 8 ). Thus the number of operations are - * independent of the exponent of the input. - * - * (2/pi) is represented by an array of 24-bit integers in ipio2[]. - * - * Input parameters: - * x[] The input value (must be positive) is broken into nx - * pieces of 24-bit integers in double precision format. - * x[i] will be the i-th 24 bit of x. The scaled exponent - * of x[0] is given in input parameter e0 (i.e., x[0]*2^e0 - * match x's up to 24 bits. - * - * Example of breaking a double positive z into x[0]+x[1]+x[2]: - * e0 = ilogb(z)-23 - * z = scalbn(z,-e0) - * for i = 0,1,2 - * x[i] = floor(z) - * z = (z-x[i])*2**24 - * - * - * y[] ouput result in an array of double precision numbers. - * The dimension of y[] is: - * 24-bit precision 1 - * 53-bit precision 2 - * 64-bit precision 2 - * 113-bit precision 3 - * The actual value is the sum of them. Thus for 113-bit - * precison, one may have to do something like: - * - * long double t,w,r_head, r_tail; - * t = (long double)y[2] + (long double)y[1]; - * w = (long double)y[0]; - * r_head = t+w; - * r_tail = w - (r_head - t); - * - * e0 The exponent of x[0] - * - * nx dimension of x[] - * - * prec an integer indicating the precision: - * 0 24 bits (single) - * 1 53 bits (double) - * 2 64 bits (extended) - * 3 113 bits (quad) - * - * ipio2[] - * integer array, contains the (24*i)-th to (24*i+23)-th - * bit of 2/pi after binary point. The corresponding - * floating value is - * - * ipio2[i] * 2^(-24(i+1)). - * - * External function: - * double scalbn(), floor(); - * - * - * Here is the description of some local variables: - * - * jk jk+1 is the initial number of terms of ipio2[] needed - * in the computation. The recommended value is 2,3,4, - * 6 for single, double, extended,and quad. - * - * jz local integer variable indicating the number of - * terms of ipio2[] used. - * - * jx nx - 1 - * - * jv index for pointing to the suitable ipio2[] for the - * computation. In general, we want - * ( 2^e0*x[0] * ipio2[jv-1]*2^(-24jv) )/8 - * is an integer. Thus - * e0-3-24*jv >= 0 or (e0-3)/24 >= jv - * Hence jv = max(0,(e0-3)/24). - * - * jp jp+1 is the number of terms in PIo2[] needed, jp = jk. - * - * q[] double array with integral value, representing the - * 24-bits chunk of the product of x and 2/pi. - * - * q0 the corresponding exponent of q[0]. Note that the - * exponent for q[i] would be q0-24*i. - * - * PIo2[] double precision array, obtained by cutting pi/2 - * into 24 bits chunks. - * - * f[] ipio2[] in floating point - * - * iq[] integer array by breaking up q[] in 24-bits chunk. - * - * fq[] final product of x*(2/pi) in fq[0],..,fq[jk] - * - * ih integer. If >0 it indicates q[] is >= 0.5, hence - * it also indicates the *sign* of the result. - * - */ - - -/* - * Constants: - * The hexadecimal values are the intended ones for the following - * constants. The decimal values may be used, provided that the - * compiler will convert from decimal to binary accurately enough - * to produce the hexadecimal values shown. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const int init_jk[] = {2,3,4,6}; /* initial value for jk */ -#else -static int init_jk[] = {2,3,4,6}; -#endif - -#ifdef __STDC__ -static const double PIo2[] = { -#else -static double PIo2[] = { -#endif - 1.57079625129699707031e+00, /* 0x3FF921FB, 0x40000000 */ - 7.54978941586159635335e-08, /* 0x3E74442D, 0x00000000 */ - 5.39030252995776476554e-15, /* 0x3CF84698, 0x80000000 */ - 3.28200341580791294123e-22, /* 0x3B78CC51, 0x60000000 */ - 1.27065575308067607349e-29, /* 0x39F01B83, 0x80000000 */ - 1.22933308981111328932e-36, /* 0x387A2520, 0x40000000 */ - 2.73370053816464559624e-44, /* 0x36E38222, 0x80000000 */ - 2.16741683877804819444e-51, /* 0x3569F31D, 0x00000000 */ -}; - -#ifdef __STDC__ -static const double -#else -static double -#endif -zero = 0.0, -one = 1.0, -two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */ -twon24 = 5.96046447753906250000e-08; /* 0x3E700000, 0x00000000 */ - -#ifdef __STDC__ - int __kernel_rem_pio2(double *x, double *y, int e0, int nx, int prec, const int *ipio2) -#else - int __kernel_rem_pio2(x,y,e0,nx,prec,ipio2) - double x[], y[]; int e0,nx,prec; int ipio2[]; -#endif -{ - int jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih; - double z,fw,f[20],fq[20],q[20]; - - /* initialize jk*/ - jk = init_jk[prec]; - jp = jk; - - /* determine jx,jv,q0, note that 3>q0 */ - jx = nx-1; - jv = (e0-3)/24; if(jv<0) jv=0; - q0 = e0-24*(jv+1); - - /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */ - j = jv-jx; m = jx+jk; - for(i=0;i<=m;i++,j++) f[i] = (j<0)? zero : (double) ipio2[j]; - - /* compute q[0],q[1],...q[jk] */ - for (i=0;i<=jk;i++) { - for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; q[i] = fw; - } - - jz = jk; -recompute: - /* distill q[] into iq[] reversingly */ - for(i=0,j=jz,z=q[jz];j>0;i++,j--) { - fw = (double)((int)(twon24* z)); - iq[i] = (int)(z-two24*fw); - z = q[j-1]+fw; - } - - /* compute n */ - z = fd_scalbn(z,q0); /* actual value of z */ - z -= 8.0*fd_floor(z*0.125); /* trim off integer >= 8 */ - n = (int) z; - z -= (double)n; - ih = 0; - if(q0>0) { /* need iq[jz-1] to determine n */ - i = (iq[jz-1]>>(24-q0)); n += i; - iq[jz-1] -= i<<(24-q0); - ih = iq[jz-1]>>(23-q0); - } - else if(q0==0) ih = iq[jz-1]>>23; - else if(z>=0.5) ih=2; - - if(ih>0) { /* q > 0.5 */ - n += 1; carry = 0; - for(i=0;i0) { /* rare case: chance is 1 in 12 */ - switch(q0) { - case 1: - iq[jz-1] &= 0x7fffff; break; - case 2: - iq[jz-1] &= 0x3fffff; break; - } - } - if(ih==2) { - z = one - z; - if(carry!=0) z -= fd_scalbn(one,q0); - } - } - - /* check if recomputation is needed */ - if(z==zero) { - j = 0; - for (i=jz-1;i>=jk;i--) j |= iq[i]; - if(j==0) { /* need recomputation */ - for(k=1;iq[jk-k]==0;k++); /* k = no. of terms needed */ - - for(i=jz+1;i<=jz+k;i++) { /* add q[jz+1] to q[jz+k] */ - f[jx+i] = (double) ipio2[jv+i]; - for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; - q[i] = fw; - } - jz += k; - goto recompute; - } - } - - /* chop off zero terms */ - if(z==0.0) { - jz -= 1; q0 -= 24; - while(iq[jz]==0) { jz--; q0-=24;} - } else { /* break z into 24-bit if necessary */ - z = fd_scalbn(z,-q0); - if(z>=two24) { - fw = (double)((int)(twon24*z)); - iq[jz] = (int)(z-two24*fw); - jz += 1; q0 += 24; - iq[jz] = (int) fw; - } else iq[jz] = (int) z ; - } - - /* convert integer "bit" chunk to floating-point value */ - fw = fd_scalbn(one,q0); - for(i=jz;i>=0;i--) { - q[i] = fw*(double)iq[i]; fw*=twon24; - } - - /* compute PIo2[0,...,jp]*q[jz,...,0] */ - for(i=jz;i>=0;i--) { - for(fw=0.0,k=0;k<=jp&&k<=jz-i;k++) fw += PIo2[k]*q[i+k]; - fq[jz-i] = fw; - } - - /* compress fq[] into y[] */ - switch(prec) { - case 0: - fw = 0.0; - for (i=jz;i>=0;i--) fw += fq[i]; - y[0] = (ih==0)? fw: -fw; - break; - case 1: - case 2: - fw = 0.0; - for (i=jz;i>=0;i--) fw += fq[i]; - y[0] = (ih==0)? fw: -fw; - fw = fq[0]-fw; - for (i=1;i<=jz;i++) fw += fq[i]; - y[1] = (ih==0)? fw: -fw; - break; - case 3: /* painful */ - for (i=jz;i>0;i--) { - fw = fq[i-1]+fq[i]; - fq[i] += fq[i-1]-fw; - fq[i-1] = fw; - } - for (i=jz;i>1;i--) { - fw = fq[i-1]+fq[i]; - fq[i] += fq[i-1]-fw; - fq[i-1] = fw; - } - for (fw=0.0,i=jz;i>=2;i--) fw += fq[i]; - if(ih==0) { - y[0] = fq[0]; y[1] = fq[1]; y[2] = fw; - } else { - y[0] = -fq[0]; y[1] = -fq[1]; y[2] = -fw; - } - } - return n&7; -} diff --git a/js/src/fdlibm/k_sin.c b/js/src/fdlibm/k_sin.c deleted file mode 100644 index d2bdabd6da32..000000000000 --- a/js/src/fdlibm/k_sin.c +++ /dev/null @@ -1,114 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)k_sin.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* __kernel_sin( x, y, iy) - * kernel sin function on [-pi/4, pi/4], pi/4 ~ 0.7854 - * Input x is assumed to be bounded by ~pi/4 in magnitude. - * Input y is the tail of x. - * Input iy indicates whether y is 0. (if iy=0, y assume to be 0). - * - * Algorithm - * 1. Since sin(-x) = -sin(x), we need only to consider positive x. - * 2. if x < 2^-27 (hx<0x3e400000 0), return x with inexact if x!=0. - * 3. sin(x) is approximated by a polynomial of degree 13 on - * [0,pi/4] - * 3 13 - * sin(x) ~ x + S1*x + ... + S6*x - * where - * - * |sin(x) 2 4 6 8 10 12 | -58 - * |----- - (1+S1*x +S2*x +S3*x +S4*x +S5*x +S6*x )| <= 2 - * | x | - * - * 4. sin(x+y) = sin(x) + sin'(x')*y - * ~ sin(x) + (1-x*x/2)*y - * For better accuracy, let - * 3 2 2 2 2 - * r = x *(S2+x *(S3+x *(S4+x *(S5+x *S6)))) - * then 3 2 - * sin(x) = x + (S1*x + (x *(r-y/2)+y)) - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif -half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */ -S1 = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */ -S2 = 8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */ -S3 = -1.98412698298579493134e-04, /* 0xBF2A01A0, 0x19C161D5 */ -S4 = 2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */ -S5 = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */ -S6 = 1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */ - -#ifdef __STDC__ - double __kernel_sin(double x, double y, int iy) -#else - double __kernel_sin(x, y, iy) - double x,y; int iy; /* iy=0 if y is zero */ -#endif -{ - fd_twoints u; - double z,r,v; - int ix; - u.d = x; - ix = __HI(u)&0x7fffffff; /* high word of x */ - if(ix<0x3e400000) /* |x| < 2**-27 */ - {if((int)x==0) return x;} /* generate inexact */ - z = x*x; - v = z*x; - r = S2+z*(S3+z*(S4+z*(S5+z*S6))); - if(iy==0) return x+v*(S1+z*r); - else return x-((z*(half*y-v*r)-y)-v*S1); -} diff --git a/js/src/fdlibm/k_standard.c b/js/src/fdlibm/k_standard.c deleted file mode 100644 index 720109c9d6a1..000000000000 --- a/js/src/fdlibm/k_standard.c +++ /dev/null @@ -1,785 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)k_standard.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - * - */ - -#include "fdlibm.h" - -/* XXX ugly hack to get msvc to link without error. */ -#if _LIB_VERSION == _IEEE_ && !(defined(DARWIN) || defined(XP_MACOSX)) - int errno; -# define EDOM 0 -# define ERANGE 0 -#else -# include -#endif - - -#ifndef _USE_WRITE -#include /* fputs(), stderr */ -#define WRITE2(u,v) fputs(u, stderr) -#else /* !defined(_USE_WRITE) */ -#include /* write */ -#define WRITE2(u,v) write(2, u, v) -#undef fflush -#endif /* !defined(_USE_WRITE) */ - -static double zero = 0.0; /* used as const */ - -/* - * Standard conformance (non-IEEE) on exception cases. - * Mapping: - * 1 -- acos(|x|>1) - * 2 -- asin(|x|>1) - * 3 -- atan2(+-0,+-0) - * 4 -- hypot overflow - * 5 -- cosh overflow - * 6 -- exp overflow - * 7 -- exp underflow - * 8 -- y0(0) - * 9 -- y0(-ve) - * 10-- y1(0) - * 11-- y1(-ve) - * 12-- yn(0) - * 13-- yn(-ve) - * 14-- lgamma(finite) overflow - * 15-- lgamma(-integer) - * 16-- log(0) - * 17-- log(x<0) - * 18-- log10(0) - * 19-- log10(x<0) - * 20-- pow(0.0,0.0) - * 21-- pow(x,y) overflow - * 22-- pow(x,y) underflow - * 23-- pow(0,negative) - * 24-- pow(neg,non-integral) - * 25-- sinh(finite) overflow - * 26-- sqrt(negative) - * 27-- fmod(x,0) - * 28-- remainder(x,0) - * 29-- acosh(x<1) - * 30-- atanh(|x|>1) - * 31-- atanh(|x|=1) - * 32-- scalb overflow - * 33-- scalb underflow - * 34-- j0(|x|>X_TLOSS) - * 35-- y0(x>X_TLOSS) - * 36-- j1(|x|>X_TLOSS) - * 37-- y1(x>X_TLOSS) - * 38-- jn(|x|>X_TLOSS, n) - * 39-- yn(x>X_TLOSS, n) - * 40-- gamma(finite) overflow - * 41-- gamma(-integer) - * 42-- pow(NaN,0.0) - */ - - -#ifdef __STDC__ - double __kernel_standard(double x, double y, int type, int *err) -#else - double __kernel_standard(x,y,type, err) - double x,y; int type;int *err; -#endif -{ - struct exception exc; -#ifndef HUGE_VAL /* this is the only routine that uses HUGE_VAL */ -#define HUGE_VAL inf - double inf = 0.0; - fd_twoints u; - - u.d = inf; - __HI(u) = 0x7ff00000; /* set inf to infinite */ - inf = u.d; -#endif - - *err = 0; - -#ifdef _USE_WRITE - (void) fflush(stdout); -#endif - exc.arg1 = x; - exc.arg2 = y; - switch(type) { - case 1: - /* acos(|x|>1) */ - exc.type = DOMAIN; - exc.name = "acos"; - exc.retval = zero; - if (_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if(_LIB_VERSION == _SVID_) { - (void) WRITE2("acos: DOMAIN error\n", 19); - } - *err = EDOM; - } - break; - case 2: - /* asin(|x|>1) */ - exc.type = DOMAIN; - exc.name = "asin"; - exc.retval = zero; - if(_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if(_LIB_VERSION == _SVID_) { - (void) WRITE2("asin: DOMAIN error\n", 19); - } - *err = EDOM; - } - break; - case 3: - /* atan2(+-0,+-0) */ - exc.arg1 = y; - exc.arg2 = x; - exc.type = DOMAIN; - exc.name = "atan2"; - exc.retval = zero; - if(_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if(_LIB_VERSION == _SVID_) { - (void) WRITE2("atan2: DOMAIN error\n", 20); - } - *err = EDOM; - } - break; - case 4: - /* hypot(finite,finite) overflow */ - exc.type = OVERFLOW; - exc.name = "hypot"; - if (_LIB_VERSION == _SVID_) - exc.retval = HUGE; - else - exc.retval = HUGE_VAL; - if (_LIB_VERSION == _POSIX_) - *err = ERANGE; - else if (!fd_matherr(&exc)) { - *err = ERANGE; - } - break; - case 5: - /* cosh(finite) overflow */ - exc.type = OVERFLOW; - exc.name = "cosh"; - if (_LIB_VERSION == _SVID_) - exc.retval = HUGE; - else - exc.retval = HUGE_VAL; - if (_LIB_VERSION == _POSIX_) - *err = ERANGE; - else if (!fd_matherr(&exc)) { - *err = ERANGE; - } - break; - case 6: - /* exp(finite) overflow */ - exc.type = OVERFLOW; - exc.name = "exp"; - if (_LIB_VERSION == _SVID_) - exc.retval = HUGE; - else - exc.retval = HUGE_VAL; - if (_LIB_VERSION == _POSIX_) - *err = ERANGE; - else if (!fd_matherr(&exc)) { - *err = ERANGE; - } - break; - case 7: - /* exp(finite) underflow */ - exc.type = UNDERFLOW; - exc.name = "exp"; - exc.retval = zero; - if (_LIB_VERSION == _POSIX_) - *err = ERANGE; - else if (!fd_matherr(&exc)) { - *err = ERANGE; - } - break; - case 8: - /* y0(0) = -inf */ - exc.type = DOMAIN; /* should be SING for IEEE */ - exc.name = "y0"; - if (_LIB_VERSION == _SVID_) - exc.retval = -HUGE; - else - exc.retval = -HUGE_VAL; - if (_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2("y0: DOMAIN error\n", 17); - } - *err = EDOM; - } - break; - case 9: - /* y0(x<0) = NaN */ - exc.type = DOMAIN; - exc.name = "y0"; - if (_LIB_VERSION == _SVID_) - exc.retval = -HUGE; - else - exc.retval = -HUGE_VAL; - if (_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2("y0: DOMAIN error\n", 17); - } - *err = EDOM; - } - break; - case 10: - /* y1(0) = -inf */ - exc.type = DOMAIN; /* should be SING for IEEE */ - exc.name = "y1"; - if (_LIB_VERSION == _SVID_) - exc.retval = -HUGE; - else - exc.retval = -HUGE_VAL; - if (_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2("y1: DOMAIN error\n", 17); - } - *err = EDOM; - } - break; - case 11: - /* y1(x<0) = NaN */ - exc.type = DOMAIN; - exc.name = "y1"; - if (_LIB_VERSION == _SVID_) - exc.retval = -HUGE; - else - exc.retval = -HUGE_VAL; - if (_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2("y1: DOMAIN error\n", 17); - } - *err = EDOM; - } - break; - case 12: - /* yn(n,0) = -inf */ - exc.type = DOMAIN; /* should be SING for IEEE */ - exc.name = "yn"; - if (_LIB_VERSION == _SVID_) - exc.retval = -HUGE; - else - exc.retval = -HUGE_VAL; - if (_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2("yn: DOMAIN error\n", 17); - } - *err = EDOM; - } - break; - case 13: - /* yn(x<0) = NaN */ - exc.type = DOMAIN; - exc.name = "yn"; - if (_LIB_VERSION == _SVID_) - exc.retval = -HUGE; - else - exc.retval = -HUGE_VAL; - if (_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2("yn: DOMAIN error\n", 17); - } - *err = EDOM; - } - break; - case 14: - /* lgamma(finite) overflow */ - exc.type = OVERFLOW; - exc.name = "lgamma"; - if (_LIB_VERSION == _SVID_) - exc.retval = HUGE; - else - exc.retval = HUGE_VAL; - if (_LIB_VERSION == _POSIX_) - *err = ERANGE; - else if (!fd_matherr(&exc)) { - *err = ERANGE; - } - break; - case 15: - /* lgamma(-integer) or lgamma(0) */ - exc.type = SING; - exc.name = "lgamma"; - if (_LIB_VERSION == _SVID_) - exc.retval = HUGE; - else - exc.retval = HUGE_VAL; - if (_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2("lgamma: SING error\n", 19); - } - *err = EDOM; - } - break; - case 16: - /* log(0) */ - exc.type = SING; - exc.name = "log"; - if (_LIB_VERSION == _SVID_) - exc.retval = -HUGE; - else - exc.retval = -HUGE_VAL; - if (_LIB_VERSION == _POSIX_) - *err = ERANGE; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2("log: SING error\n", 16); - } - *err = EDOM; - } - break; - case 17: - /* log(x<0) */ - exc.type = DOMAIN; - exc.name = "log"; - if (_LIB_VERSION == _SVID_) - exc.retval = -HUGE; - else - exc.retval = -HUGE_VAL; - if (_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2("log: DOMAIN error\n", 18); - } - *err = EDOM; - } - break; - case 18: - /* log10(0) */ - exc.type = SING; - exc.name = "log10"; - if (_LIB_VERSION == _SVID_) - exc.retval = -HUGE; - else - exc.retval = -HUGE_VAL; - if (_LIB_VERSION == _POSIX_) - *err = ERANGE; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2("log10: SING error\n", 18); - } - *err = EDOM; - } - break; - case 19: - /* log10(x<0) */ - exc.type = DOMAIN; - exc.name = "log10"; - if (_LIB_VERSION == _SVID_) - exc.retval = -HUGE; - else - exc.retval = -HUGE_VAL; - if (_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2("log10: DOMAIN error\n", 20); - } - *err = EDOM; - } - break; - case 20: - /* pow(0.0,0.0) */ - /* error only if _LIB_VERSION == _SVID_ */ - exc.type = DOMAIN; - exc.name = "pow"; - exc.retval = zero; - if (_LIB_VERSION != _SVID_) exc.retval = 1.0; - else if (!fd_matherr(&exc)) { - (void) WRITE2("pow(0,0): DOMAIN error\n", 23); - *err = EDOM; - } - break; - case 21: - /* pow(x,y) overflow */ - exc.type = OVERFLOW; - exc.name = "pow"; - if (_LIB_VERSION == _SVID_) { - exc.retval = HUGE; - y *= 0.5; - if(xzero) ? HUGE : -HUGE); - else - exc.retval = ( (x>zero) ? HUGE_VAL : -HUGE_VAL); - if (_LIB_VERSION == _POSIX_) - *err = ERANGE; - else if (!fd_matherr(&exc)) { - *err = ERANGE; - } - break; - case 26: - /* sqrt(x<0) */ - exc.type = DOMAIN; - exc.name = "sqrt"; - if (_LIB_VERSION == _SVID_) - exc.retval = zero; - else - exc.retval = zero/zero; - if (_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2("sqrt: DOMAIN error\n", 19); - } - *err = EDOM; - } - break; - case 27: - /* fmod(x,0) */ - exc.type = DOMAIN; - exc.name = "fmod"; - if (_LIB_VERSION == _SVID_) - exc.retval = x; - else - exc.retval = zero/zero; - if (_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2("fmod: DOMAIN error\n", 20); - } - *err = EDOM; - } - break; - case 28: - /* remainder(x,0) */ - exc.type = DOMAIN; - exc.name = "remainder"; - exc.retval = zero/zero; - if (_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2("remainder: DOMAIN error\n", 24); - } - *err = EDOM; - } - break; - case 29: - /* acosh(x<1) */ - exc.type = DOMAIN; - exc.name = "acosh"; - exc.retval = zero/zero; - if (_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2("acosh: DOMAIN error\n", 20); - } - *err = EDOM; - } - break; - case 30: - /* atanh(|x|>1) */ - exc.type = DOMAIN; - exc.name = "atanh"; - exc.retval = zero/zero; - if (_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2("atanh: DOMAIN error\n", 20); - } - *err = EDOM; - } - break; - case 31: - /* atanh(|x|=1) */ - exc.type = SING; - exc.name = "atanh"; - exc.retval = x/zero; /* sign(x)*inf */ - if (_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2("atanh: SING error\n", 18); - } - *err = EDOM; - } - break; - case 32: - /* scalb overflow; SVID also returns +-HUGE_VAL */ - exc.type = OVERFLOW; - exc.name = "scalb"; - exc.retval = x > zero ? HUGE_VAL : -HUGE_VAL; - if (_LIB_VERSION == _POSIX_) - *err = ERANGE; - else if (!fd_matherr(&exc)) { - *err = ERANGE; - } - break; - case 33: - /* scalb underflow */ - exc.type = UNDERFLOW; - exc.name = "scalb"; - exc.retval = fd_copysign(zero,x); - if (_LIB_VERSION == _POSIX_) - *err = ERANGE; - else if (!fd_matherr(&exc)) { - *err = ERANGE; - } - break; - case 34: - /* j0(|x|>X_TLOSS) */ - exc.type = TLOSS; - exc.name = "j0"; - exc.retval = zero; - if (_LIB_VERSION == _POSIX_) - *err = ERANGE; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2(exc.name, 2); - (void) WRITE2(": TLOSS error\n", 14); - } - *err = ERANGE; - } - break; - case 35: - /* y0(x>X_TLOSS) */ - exc.type = TLOSS; - exc.name = "y0"; - exc.retval = zero; - if (_LIB_VERSION == _POSIX_) - *err = ERANGE; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2(exc.name, 2); - (void) WRITE2(": TLOSS error\n", 14); - } - *err = ERANGE; - } - break; - case 36: - /* j1(|x|>X_TLOSS) */ - exc.type = TLOSS; - exc.name = "j1"; - exc.retval = zero; - if (_LIB_VERSION == _POSIX_) - *err = ERANGE; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2(exc.name, 2); - (void) WRITE2(": TLOSS error\n", 14); - } - *err = ERANGE; - } - break; - case 37: - /* y1(x>X_TLOSS) */ - exc.type = TLOSS; - exc.name = "y1"; - exc.retval = zero; - if (_LIB_VERSION == _POSIX_) - *err = ERANGE; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2(exc.name, 2); - (void) WRITE2(": TLOSS error\n", 14); - } - *err = ERANGE; - } - break; - case 38: - /* jn(|x|>X_TLOSS) */ - exc.type = TLOSS; - exc.name = "jn"; - exc.retval = zero; - if (_LIB_VERSION == _POSIX_) - *err = ERANGE; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2(exc.name, 2); - (void) WRITE2(": TLOSS error\n", 14); - } - *err = ERANGE; - } - break; - case 39: - /* yn(x>X_TLOSS) */ - exc.type = TLOSS; - exc.name = "yn"; - exc.retval = zero; - if (_LIB_VERSION == _POSIX_) - *err = ERANGE; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2(exc.name, 2); - (void) WRITE2(": TLOSS error\n", 14); - } - *err = ERANGE; - } - break; - case 40: - /* gamma(finite) overflow */ - exc.type = OVERFLOW; - exc.name = "gamma"; - if (_LIB_VERSION == _SVID_) - exc.retval = HUGE; - else - exc.retval = HUGE_VAL; - if (_LIB_VERSION == _POSIX_) - *err = ERANGE; - else if (!fd_matherr(&exc)) { - *err = ERANGE; - } - break; - case 41: - /* gamma(-integer) or gamma(0) */ - exc.type = SING; - exc.name = "gamma"; - if (_LIB_VERSION == _SVID_) - exc.retval = HUGE; - else - exc.retval = HUGE_VAL; - if (_LIB_VERSION == _POSIX_) - *err = EDOM; - else if (!fd_matherr(&exc)) { - if (_LIB_VERSION == _SVID_) { - (void) WRITE2("gamma: SING error\n", 18); - } - *err = EDOM; - } - break; - case 42: - /* pow(NaN,0.0) */ - /* error only if _LIB_VERSION == _SVID_ & _XOPEN_ */ - exc.type = DOMAIN; - exc.name = "pow"; - exc.retval = x; - if (_LIB_VERSION == _IEEE_ || - _LIB_VERSION == _POSIX_) exc.retval = 1.0; - else if (!fd_matherr(&exc)) { - *err = EDOM; - } - break; - } - return exc.retval; -} diff --git a/js/src/fdlibm/k_tan.c b/js/src/fdlibm/k_tan.c deleted file mode 100644 index 1e7681b8883d..000000000000 --- a/js/src/fdlibm/k_tan.c +++ /dev/null @@ -1,170 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)k_tan.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* __kernel_tan( x, y, k ) - * kernel tan function on [-pi/4, pi/4], pi/4 ~ 0.7854 - * Input x is assumed to be bounded by ~pi/4 in magnitude. - * Input y is the tail of x. - * Input k indicates whether tan (if k=1) or - * -1/tan (if k= -1) is returned. - * - * Algorithm - * 1. Since tan(-x) = -tan(x), we need only to consider positive x. - * 2. if x < 2^-28 (hx<0x3e300000 0), return x with inexact if x!=0. - * 3. tan(x) is approximated by a odd polynomial of degree 27 on - * [0,0.67434] - * 3 27 - * tan(x) ~ x + T1*x + ... + T13*x - * where - * - * |tan(x) 2 4 26 | -59.2 - * |----- - (1+T1*x +T2*x +.... +T13*x )| <= 2 - * | x | - * - * Note: tan(x+y) = tan(x) + tan'(x)*y - * ~ tan(x) + (1+x*x)*y - * Therefore, for better accuracy in computing tan(x+y), let - * 3 2 2 2 2 - * r = x *(T2+x *(T3+x *(...+x *(T12+x *T13)))) - * then - * 3 2 - * tan(x+y) = x + (T1*x + (x *(r+y)+y)) - * - * 4. For x in [0.67434,pi/4], let y = pi/4 - x, then - * tan(x) = tan(pi/4-y) = (1-tan(y))/(1+tan(y)) - * = 1 - 2*(tan(y) - (tan(y)^2)/(1+tan(y))) - */ - -#include "fdlibm.h" -#ifdef __STDC__ -static const double -#else -static double -#endif -one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ -pio4 = 7.85398163397448278999e-01, /* 0x3FE921FB, 0x54442D18 */ -pio4lo= 3.06161699786838301793e-17, /* 0x3C81A626, 0x33145C07 */ -T[] = { - 3.33333333333334091986e-01, /* 0x3FD55555, 0x55555563 */ - 1.33333333333201242699e-01, /* 0x3FC11111, 0x1110FE7A */ - 5.39682539762260521377e-02, /* 0x3FABA1BA, 0x1BB341FE */ - 2.18694882948595424599e-02, /* 0x3F9664F4, 0x8406D637 */ - 8.86323982359930005737e-03, /* 0x3F8226E3, 0xE96E8493 */ - 3.59207910759131235356e-03, /* 0x3F6D6D22, 0xC9560328 */ - 1.45620945432529025516e-03, /* 0x3F57DBC8, 0xFEE08315 */ - 5.88041240820264096874e-04, /* 0x3F4344D8, 0xF2F26501 */ - 2.46463134818469906812e-04, /* 0x3F3026F7, 0x1A8D1068 */ - 7.81794442939557092300e-05, /* 0x3F147E88, 0xA03792A6 */ - 7.14072491382608190305e-05, /* 0x3F12B80F, 0x32F0A7E9 */ - -1.85586374855275456654e-05, /* 0xBEF375CB, 0xDB605373 */ - 2.59073051863633712884e-05, /* 0x3EFB2A70, 0x74BF7AD4 */ -}; - -#ifdef __STDC__ - double __kernel_tan(double x, double y, int iy) -#else - double __kernel_tan(x, y, iy) - double x,y; int iy; -#endif -{ - fd_twoints u; - double z,r,v,w,s; - int ix,hx; - u.d = x; - hx = __HI(u); /* high word of x */ - ix = hx&0x7fffffff; /* high word of |x| */ - if(ix<0x3e300000) /* x < 2**-28 */ - {if((int)x==0) { /* generate inexact */ - u.d =x; - if(((ix|__LO(u))|(iy+1))==0) return one/fd_fabs(x); - else return (iy==1)? x: -one/x; - } - } - if(ix>=0x3FE59428) { /* |x|>=0.6744 */ - if(hx<0) {x = -x; y = -y;} - z = pio4-x; - w = pio4lo-y; - x = z+w; y = 0.0; - } - z = x*x; - w = z*z; - /* Break x^5*(T[1]+x^2*T[2]+...) into - * x^5(T[1]+x^4*T[3]+...+x^20*T[11]) + - * x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12])) - */ - r = T[1]+w*(T[3]+w*(T[5]+w*(T[7]+w*(T[9]+w*T[11])))); - v = z*(T[2]+w*(T[4]+w*(T[6]+w*(T[8]+w*(T[10]+w*T[12]))))); - s = z*x; - r = y + z*(s*(r+v)+y); - r += T[0]*s; - w = x+r; - if(ix>=0x3FE59428) { - v = (double)iy; - return (double)(1-((hx>>30)&2))*(v-2.0*(x-(w*w/(w+v)-r))); - } - if(iy==1) return w; - else { /* if allow error up to 2 ulp, - simply return -1.0/(x+r) here */ - /* compute -1.0/(x+r) accurately */ - double a,t; - z = w; - u.d = z; - __LO(u) = 0; - z = u.d; - v = r-(z - x); /* z+v = r+x */ - t = a = -1.0/w; /* a = -1.0/w */ - u.d = t; - __LO(u) = 0; - t = u.d; - s = 1.0+t*z; - return t+a*(s+t*v); - } -} diff --git a/js/src/fdlibm/s_asinh.c b/js/src/fdlibm/s_asinh.c deleted file mode 100644 index fdf70a91cf0d..000000000000 --- a/js/src/fdlibm/s_asinh.c +++ /dev/null @@ -1,101 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_asinh.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* asinh(x) - * Method : - * Based on - * asinh(x) = sign(x) * log [ |x| + sqrt(x*x+1) ] - * we have - * asinh(x) := x if 1+x*x=1, - * := sign(x)*(log(x)+ln2)) for large |x|, else - * := sign(x)*log(2|x|+1/(|x|+sqrt(x*x+1))) if|x|>2, else - * := sign(x)*log1p(|x| + x^2/(1 + sqrt(1+x^2))) - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif -one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ -ln2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */ -really_big= 1.00000000000000000000e+300; - -#ifdef __STDC__ - double fd_asinh(double x) -#else - double fd_asinh(x) - double x; -#endif -{ - fd_twoints u; - double t,w; - int hx,ix; - u.d = x; - hx = __HI(u); - ix = hx&0x7fffffff; - if(ix>=0x7ff00000) return x+x; /* x is inf or NaN */ - if(ix< 0x3e300000) { /* |x|<2**-28 */ - if(really_big+x>one) return x; /* return x inexact except 0 */ - } - if(ix>0x41b00000) { /* |x| > 2**28 */ - w = __ieee754_log(fd_fabs(x))+ln2; - } else if (ix>0x40000000) { /* 2**28 > |x| > 2.0 */ - t = fd_fabs(x); - w = __ieee754_log(2.0*t+one/(fd_sqrt(x*x+one)+t)); - } else { /* 2.0 > |x| > 2**-28 */ - t = x*x; - w =fd_log1p(fd_fabs(x)+t/(one+fd_sqrt(one+t))); - } - if(hx>0) return w; else return -w; -} diff --git a/js/src/fdlibm/s_atan.c b/js/src/fdlibm/s_atan.c deleted file mode 100644 index 99a00c686465..000000000000 --- a/js/src/fdlibm/s_atan.c +++ /dev/null @@ -1,175 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_atan.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - * - */ - -/* atan(x) - * Method - * 1. Reduce x to positive by atan(x) = -atan(-x). - * 2. According to the integer k=4t+0.25 chopped, t=x, the argument - * is further reduced to one of the following intervals and the - * arctangent of t is evaluated by the corresponding formula: - * - * [0,7/16] atan(x) = t-t^3*(a1+t^2*(a2+...(a10+t^2*a11)...) - * [7/16,11/16] atan(x) = atan(1/2) + atan( (t-0.5)/(1+t/2) ) - * [11/16.19/16] atan(x) = atan( 1 ) + atan( (t-1)/(1+t) ) - * [19/16,39/16] atan(x) = atan(3/2) + atan( (t-1.5)/(1+1.5t) ) - * [39/16,INF] atan(x) = atan(INF) + atan( -1/t ) - * - * Constants: - * The hexadecimal values are the intended ones for the following - * constants. The decimal values may be used, provided that the - * compiler will convert from decimal to binary accurately enough - * to produce the hexadecimal values shown. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double atanhi[] = { -#else -static double atanhi[] = { -#endif - 4.63647609000806093515e-01, /* atan(0.5)hi 0x3FDDAC67, 0x0561BB4F */ - 7.85398163397448278999e-01, /* atan(1.0)hi 0x3FE921FB, 0x54442D18 */ - 9.82793723247329054082e-01, /* atan(1.5)hi 0x3FEF730B, 0xD281F69B */ - 1.57079632679489655800e+00, /* atan(inf)hi 0x3FF921FB, 0x54442D18 */ -}; - -#ifdef __STDC__ -static const double atanlo[] = { -#else -static double atanlo[] = { -#endif - 2.26987774529616870924e-17, /* atan(0.5)lo 0x3C7A2B7F, 0x222F65E2 */ - 3.06161699786838301793e-17, /* atan(1.0)lo 0x3C81A626, 0x33145C07 */ - 1.39033110312309984516e-17, /* atan(1.5)lo 0x3C700788, 0x7AF0CBBD */ - 6.12323399573676603587e-17, /* atan(inf)lo 0x3C91A626, 0x33145C07 */ -}; - -#ifdef __STDC__ -static const double aT[] = { -#else -static double aT[] = { -#endif - 3.33333333333329318027e-01, /* 0x3FD55555, 0x5555550D */ - -1.99999999998764832476e-01, /* 0xBFC99999, 0x9998EBC4 */ - 1.42857142725034663711e-01, /* 0x3FC24924, 0x920083FF */ - -1.11111104054623557880e-01, /* 0xBFBC71C6, 0xFE231671 */ - 9.09088713343650656196e-02, /* 0x3FB745CD, 0xC54C206E */ - -7.69187620504482999495e-02, /* 0xBFB3B0F2, 0xAF749A6D */ - 6.66107313738753120669e-02, /* 0x3FB10D66, 0xA0D03D51 */ - -5.83357013379057348645e-02, /* 0xBFADDE2D, 0x52DEFD9A */ - 4.97687799461593236017e-02, /* 0x3FA97B4B, 0x24760DEB */ - -3.65315727442169155270e-02, /* 0xBFA2B444, 0x2C6A6C2F */ - 1.62858201153657823623e-02, /* 0x3F90AD3A, 0xE322DA11 */ -}; - -#ifdef __STDC__ - static const double -#else - static double -#endif -one = 1.0, -really_big = 1.0e300; - -#ifdef __STDC__ - double fd_atan(double x) -#else - double fd_atan(x) - double x; -#endif -{ - fd_twoints u; - double w,s1,s2,z; - int ix,hx,id; - - u.d = x; - hx = __HI(u); - ix = hx&0x7fffffff; - if(ix>=0x44100000) { /* if |x| >= 2^66 */ - u.d = x; - if(ix>0x7ff00000|| - (ix==0x7ff00000&&(__LO(u)!=0))) - return x+x; /* NaN */ - if(hx>0) return atanhi[3]+atanlo[3]; - else return -atanhi[3]-atanlo[3]; - } if (ix < 0x3fdc0000) { /* |x| < 0.4375 */ - if (ix < 0x3e200000) { /* |x| < 2^-29 */ - if(really_big+x>one) return x; /* raise inexact */ - } - id = -1; - } else { - x = fd_fabs(x); - if (ix < 0x3ff30000) { /* |x| < 1.1875 */ - if (ix < 0x3fe60000) { /* 7/16 <=|x|<11/16 */ - id = 0; x = (2.0*x-one)/(2.0+x); - } else { /* 11/16<=|x|< 19/16 */ - id = 1; x = (x-one)/(x+one); - } - } else { - if (ix < 0x40038000) { /* |x| < 2.4375 */ - id = 2; x = (x-1.5)/(one+1.5*x); - } else { /* 2.4375 <= |x| < 2^66 */ - id = 3; x = -1.0/x; - } - }} - /* end of argument reduction */ - z = x*x; - w = z*z; - /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */ - s1 = z*(aT[0]+w*(aT[2]+w*(aT[4]+w*(aT[6]+w*(aT[8]+w*aT[10]))))); - s2 = w*(aT[1]+w*(aT[3]+w*(aT[5]+w*(aT[7]+w*aT[9])))); - if (id<0) return x - x*(s1+s2); - else { - z = atanhi[id] - ((x*(s1+s2) - atanlo[id]) - x); - return (hx<0)? -z:z; - } -} diff --git a/js/src/fdlibm/s_cbrt.c b/js/src/fdlibm/s_cbrt.c deleted file mode 100644 index 4aed19b1bb12..000000000000 --- a/js/src/fdlibm/s_cbrt.c +++ /dev/null @@ -1,133 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_cbrt.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - * - */ - -#include "fdlibm.h" - -/* cbrt(x) - * Return cube root of x - */ -#ifdef __STDC__ -static const unsigned -#else -static unsigned -#endif - B1 = 715094163, /* B1 = (682-0.03306235651)*2**20 */ - B2 = 696219795; /* B2 = (664-0.03306235651)*2**20 */ - -#ifdef __STDC__ -static const double -#else -static double -#endif -C = 5.42857142857142815906e-01, /* 19/35 = 0x3FE15F15, 0xF15F15F1 */ -D = -7.05306122448979611050e-01, /* -864/1225 = 0xBFE691DE, 0x2532C834 */ -E = 1.41428571428571436819e+00, /* 99/70 = 0x3FF6A0EA, 0x0EA0EA0F */ -F = 1.60714285714285720630e+00, /* 45/28 = 0x3FF9B6DB, 0x6DB6DB6E */ -G = 3.57142857142857150787e-01; /* 5/14 = 0x3FD6DB6D, 0xB6DB6DB7 */ - -#ifdef __STDC__ - double fd_cbrt(double x) -#else - double fd_cbrt(x) - double x; -#endif -{ - fd_twoints u; - int hx; - double r,s,t=0.0,w; - unsigned sign; - - u.d = x; - hx = __HI(u); /* high word of x */ - sign=hx&0x80000000; /* sign= sign(x) */ - hx ^=sign; - if(hx>=0x7ff00000) return(x+x); /* cbrt(NaN,INF) is itself */ - if((hx|__LO(u))==0) { - x = u.d; - return(x); /* cbrt(0) is itself */ - } - u.d = x; - __HI(u) = hx; /* x <- |x| */ - x = u.d; - /* rough cbrt to 5 bits */ - if(hx<0x00100000) /* subnormal number */ - {u.d = t; __HI(u)=0x43500000; t=u.d; /* set t= 2**54 */ - t*=x; __HI(u)=__HI(u)/3+B2; - } - else { - u.d = t; __HI(u)=hx/3+B1; t = u.d; - } - - - /* new cbrt to 23 bits, may be implemented in single precision */ - r=t*t/x; - s=C+r*t; - t*=G+F/(s+E+D/s); - - /* chopped to 20 bits and make it larger than cbrt(x) */ - u.d = t; - __LO(u)=0; __HI(u)+=0x00000001; - t = u.d; - - /* one step newton iteration to 53 bits with error less than 0.667 ulps */ - s=t*t; /* t*t is exact */ - r=x/s; - w=t+t; - r=(r-t)/(w+r); /* r-s is exact */ - t=t+t*r; - - /* retore the sign bit */ - u.d = t; - __HI(u) |= sign; - t = u.d; - return(t); -} diff --git a/js/src/fdlibm/s_ceil.c b/js/src/fdlibm/s_ceil.c deleted file mode 100644 index 826bcac6c4aa..000000000000 --- a/js/src/fdlibm/s_ceil.c +++ /dev/null @@ -1,120 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_ceil.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * ceil(x) - * Return x rounded toward -inf to integral value - * Method: - * Bit twiddling. - * Exception: - * Inexact flag raised if x not equal to ceil(x). - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double really_big = 1.0e300; -#else -static double really_big = 1.0e300; -#endif - -#ifdef __STDC__ - double fd_ceil(double x) -#else - double fd_ceil(x) - double x; -#endif -{ - fd_twoints u; - int i0,i1,j0; - unsigned i,j; - u.d = x; - i0 = __HI(u); - i1 = __LO(u); - j0 = ((i0>>20)&0x7ff)-0x3ff; - if(j0<20) { - if(j0<0) { /* raise inexact if x != 0 */ - if(really_big+x>0.0) {/* return 0*sign(x) if |x|<1 */ - if(i0<0) {i0=0x80000000;i1=0;} - else if((i0|i1)!=0) { i0=0x3ff00000;i1=0;} - } - } else { - i = (0x000fffff)>>j0; - if(((i0&i)|i1)==0) return x; /* x is integral */ - if(really_big+x>0.0) { /* raise inexact flag */ - if(i0>0) i0 += (0x00100000)>>j0; - i0 &= (~i); i1=0; - } - } - } else if (j0>51) { - if(j0==0x400) return x+x; /* inf or NaN */ - else return x; /* x is integral */ - } else { - i = ((unsigned)(0xffffffff))>>(j0-20); - if((i1&i)==0) return x; /* x is integral */ - if(really_big+x>0.0) { /* raise inexact flag */ - if(i0>0) { - if(j0==20) i0+=1; - else { - j = i1 + (1<<(52-j0)); - if((int)j=0x7ff00000) return x-x; - - /* argument reduction needed */ - else { - n = __ieee754_rem_pio2(x,y); - switch(n&3) { - case 0: return __kernel_cos(y[0],y[1]); - case 1: return -__kernel_sin(y[0],y[1],1); - case 2: return -__kernel_cos(y[0],y[1]); - default: - return __kernel_sin(y[0],y[1],1); - } - } -} diff --git a/js/src/fdlibm/s_erf.c b/js/src/fdlibm/s_erf.c deleted file mode 100644 index 6eae8de3b104..000000000000 --- a/js/src/fdlibm/s_erf.c +++ /dev/null @@ -1,356 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_erf.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* double erf(double x) - * double erfc(double x) - * x - * 2 |\ - * erf(x) = --------- | exp(-t*t)dt - * sqrt(pi) \| - * 0 - * - * erfc(x) = 1-erf(x) - * Note that - * erf(-x) = -erf(x) - * erfc(-x) = 2 - erfc(x) - * - * Method: - * 1. For |x| in [0, 0.84375] - * erf(x) = x + x*R(x^2) - * erfc(x) = 1 - erf(x) if x in [-.84375,0.25] - * = 0.5 + ((0.5-x)-x*R) if x in [0.25,0.84375] - * where R = P/Q where P is an odd poly of degree 8 and - * Q is an odd poly of degree 10. - * -57.90 - * | R - (erf(x)-x)/x | <= 2 - * - * - * Remark. The formula is derived by noting - * erf(x) = (2/sqrt(pi))*(x - x^3/3 + x^5/10 - x^7/42 + ....) - * and that - * 2/sqrt(pi) = 1.128379167095512573896158903121545171688 - * is close to one. The interval is chosen because the fix - * point of erf(x) is near 0.6174 (i.e., erf(x)=x when x is - * near 0.6174), and by some experiment, 0.84375 is chosen to - * guarantee the error is less than one ulp for erf. - * - * 2. For |x| in [0.84375,1.25], let s = |x| - 1, and - * c = 0.84506291151 rounded to single (24 bits) - * erf(x) = sign(x) * (c + P1(s)/Q1(s)) - * erfc(x) = (1-c) - P1(s)/Q1(s) if x > 0 - * 1+(c+P1(s)/Q1(s)) if x < 0 - * |P1/Q1 - (erf(|x|)-c)| <= 2**-59.06 - * Remark: here we use the taylor series expansion at x=1. - * erf(1+s) = erf(1) + s*Poly(s) - * = 0.845.. + P1(s)/Q1(s) - * That is, we use rational approximation to approximate - * erf(1+s) - (c = (single)0.84506291151) - * Note that |P1/Q1|< 0.078 for x in [0.84375,1.25] - * where - * P1(s) = degree 6 poly in s - * Q1(s) = degree 6 poly in s - * - * 3. For x in [1.25,1/0.35(~2.857143)], - * erfc(x) = (1/x)*exp(-x*x-0.5625+R1/S1) - * erf(x) = 1 - erfc(x) - * where - * R1(z) = degree 7 poly in z, (z=1/x^2) - * S1(z) = degree 8 poly in z - * - * 4. For x in [1/0.35,28] - * erfc(x) = (1/x)*exp(-x*x-0.5625+R2/S2) if x > 0 - * = 2.0 - (1/x)*exp(-x*x-0.5625+R2/S2) if -6 x >= 28 - * erf(x) = sign(x) *(1 - tiny) (raise inexact) - * erfc(x) = tiny*tiny (raise underflow) if x > 0 - * = 2 - tiny if x<0 - * - * 7. Special case: - * erf(0) = 0, erf(inf) = 1, erf(-inf) = -1, - * erfc(0) = 1, erfc(inf) = 0, erfc(-inf) = 2, - * erfc/erf(NaN) is NaN - */ - - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif -tiny = 1e-300, -half= 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */ -one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ -two = 2.00000000000000000000e+00, /* 0x40000000, 0x00000000 */ - /* c = (float)0.84506291151 */ -erx = 8.45062911510467529297e-01, /* 0x3FEB0AC1, 0x60000000 */ -/* - * Coefficients for approximation to erf on [0,0.84375] - */ -efx = 1.28379167095512586316e-01, /* 0x3FC06EBA, 0x8214DB69 */ -efx8= 1.02703333676410069053e+00, /* 0x3FF06EBA, 0x8214DB69 */ -pp0 = 1.28379167095512558561e-01, /* 0x3FC06EBA, 0x8214DB68 */ -pp1 = -3.25042107247001499370e-01, /* 0xBFD4CD7D, 0x691CB913 */ -pp2 = -2.84817495755985104766e-02, /* 0xBF9D2A51, 0xDBD7194F */ -pp3 = -5.77027029648944159157e-03, /* 0xBF77A291, 0x236668E4 */ -pp4 = -2.37630166566501626084e-05, /* 0xBEF8EAD6, 0x120016AC */ -qq1 = 3.97917223959155352819e-01, /* 0x3FD97779, 0xCDDADC09 */ -qq2 = 6.50222499887672944485e-02, /* 0x3FB0A54C, 0x5536CEBA */ -qq3 = 5.08130628187576562776e-03, /* 0x3F74D022, 0xC4D36B0F */ -qq4 = 1.32494738004321644526e-04, /* 0x3F215DC9, 0x221C1A10 */ -qq5 = -3.96022827877536812320e-06, /* 0xBED09C43, 0x42A26120 */ -/* - * Coefficients for approximation to erf in [0.84375,1.25] - */ -pa0 = -2.36211856075265944077e-03, /* 0xBF6359B8, 0xBEF77538 */ -pa1 = 4.14856118683748331666e-01, /* 0x3FDA8D00, 0xAD92B34D */ -pa2 = -3.72207876035701323847e-01, /* 0xBFD7D240, 0xFBB8C3F1 */ -pa3 = 3.18346619901161753674e-01, /* 0x3FD45FCA, 0x805120E4 */ -pa4 = -1.10894694282396677476e-01, /* 0xBFBC6398, 0x3D3E28EC */ -pa5 = 3.54783043256182359371e-02, /* 0x3FA22A36, 0x599795EB */ -pa6 = -2.16637559486879084300e-03, /* 0xBF61BF38, 0x0A96073F */ -qa1 = 1.06420880400844228286e-01, /* 0x3FBB3E66, 0x18EEE323 */ -qa2 = 5.40397917702171048937e-01, /* 0x3FE14AF0, 0x92EB6F33 */ -qa3 = 7.18286544141962662868e-02, /* 0x3FB2635C, 0xD99FE9A7 */ -qa4 = 1.26171219808761642112e-01, /* 0x3FC02660, 0xE763351F */ -qa5 = 1.36370839120290507362e-02, /* 0x3F8BEDC2, 0x6B51DD1C */ -qa6 = 1.19844998467991074170e-02, /* 0x3F888B54, 0x5735151D */ -/* - * Coefficients for approximation to erfc in [1.25,1/0.35] - */ -ra0 = -9.86494403484714822705e-03, /* 0xBF843412, 0x600D6435 */ -ra1 = -6.93858572707181764372e-01, /* 0xBFE63416, 0xE4BA7360 */ -ra2 = -1.05586262253232909814e+01, /* 0xC0251E04, 0x41B0E726 */ -ra3 = -6.23753324503260060396e+01, /* 0xC04F300A, 0xE4CBA38D */ -ra4 = -1.62396669462573470355e+02, /* 0xC0644CB1, 0x84282266 */ -ra5 = -1.84605092906711035994e+02, /* 0xC067135C, 0xEBCCABB2 */ -ra6 = -8.12874355063065934246e+01, /* 0xC0545265, 0x57E4D2F2 */ -ra7 = -9.81432934416914548592e+00, /* 0xC023A0EF, 0xC69AC25C */ -sa1 = 1.96512716674392571292e+01, /* 0x4033A6B9, 0xBD707687 */ -sa2 = 1.37657754143519042600e+02, /* 0x4061350C, 0x526AE721 */ -sa3 = 4.34565877475229228821e+02, /* 0x407B290D, 0xD58A1A71 */ -sa4 = 6.45387271733267880336e+02, /* 0x40842B19, 0x21EC2868 */ -sa5 = 4.29008140027567833386e+02, /* 0x407AD021, 0x57700314 */ -sa6 = 1.08635005541779435134e+02, /* 0x405B28A3, 0xEE48AE2C */ -sa7 = 6.57024977031928170135e+00, /* 0x401A47EF, 0x8E484A93 */ -sa8 = -6.04244152148580987438e-02, /* 0xBFAEEFF2, 0xEE749A62 */ -/* - * Coefficients for approximation to erfc in [1/.35,28] - */ -rb0 = -9.86494292470009928597e-03, /* 0xBF843412, 0x39E86F4A */ -rb1 = -7.99283237680523006574e-01, /* 0xBFE993BA, 0x70C285DE */ -rb2 = -1.77579549177547519889e+01, /* 0xC031C209, 0x555F995A */ -rb3 = -1.60636384855821916062e+02, /* 0xC064145D, 0x43C5ED98 */ -rb4 = -6.37566443368389627722e+02, /* 0xC083EC88, 0x1375F228 */ -rb5 = -1.02509513161107724954e+03, /* 0xC0900461, 0x6A2E5992 */ -rb6 = -4.83519191608651397019e+02, /* 0xC07E384E, 0x9BDC383F */ -sb1 = 3.03380607434824582924e+01, /* 0x403E568B, 0x261D5190 */ -sb2 = 3.25792512996573918826e+02, /* 0x40745CAE, 0x221B9F0A */ -sb3 = 1.53672958608443695994e+03, /* 0x409802EB, 0x189D5118 */ -sb4 = 3.19985821950859553908e+03, /* 0x40A8FFB7, 0x688C246A */ -sb5 = 2.55305040643316442583e+03, /* 0x40A3F219, 0xCEDF3BE6 */ -sb6 = 4.74528541206955367215e+02, /* 0x407DA874, 0xE79FE763 */ -sb7 = -2.24409524465858183362e+01; /* 0xC03670E2, 0x42712D62 */ - -#ifdef __STDC__ - double fd_erf(double x) -#else - double fd_erf(x) - double x; -#endif -{ - fd_twoints u; - int hx,ix,i; - double R,S,P,Q,s,y,z,r; - u.d = x; - hx = __HI(u); - ix = hx&0x7fffffff; - if(ix>=0x7ff00000) { /* erf(nan)=nan */ - i = ((unsigned)hx>>31)<<1; - return (double)(1-i)+one/x; /* erf(+-inf)=+-1 */ - } - - if(ix < 0x3feb0000) { /* |x|<0.84375 */ - if(ix < 0x3e300000) { /* |x|<2**-28 */ - if (ix < 0x00800000) - return 0.125*(8.0*x+efx8*x); /*avoid underflow */ - return x + efx*x; - } - z = x*x; - r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4))); - s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5)))); - y = r/s; - return x + x*y; - } - if(ix < 0x3ff40000) { /* 0.84375 <= |x| < 1.25 */ - s = fd_fabs(x)-one; - P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6))))); - Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6))))); - if(hx>=0) return erx + P/Q; else return -erx - P/Q; - } - if (ix >= 0x40180000) { /* inf>|x|>=6 */ - if(hx>=0) return one-tiny; else return tiny-one; - } - x = fd_fabs(x); - s = one/(x*x); - if(ix< 0x4006DB6E) { /* |x| < 1/0.35 */ - R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*( - ra5+s*(ra6+s*ra7)))))); - S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*( - sa5+s*(sa6+s*(sa7+s*sa8))))))); - } else { /* |x| >= 1/0.35 */ - R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*( - rb5+s*rb6))))); - S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*( - sb5+s*(sb6+s*sb7)))))); - } - z = x; - u.d = z; - __LO(u) = 0; - z = u.d; - r = __ieee754_exp(-z*z-0.5625)*__ieee754_exp((z-x)*(z+x)+R/S); - if(hx>=0) return one-r/x; else return r/x-one; -} - -#ifdef __STDC__ - double erfc(double x) -#else - double erfc(x) - double x; -#endif -{ - fd_twoints u; - int hx,ix; - double R,S,P,Q,s,y,z,r; - u.d = x; - hx = __HI(u); - ix = hx&0x7fffffff; - if(ix>=0x7ff00000) { /* erfc(nan)=nan */ - /* erfc(+-inf)=0,2 */ - return (double)(((unsigned)hx>>31)<<1)+one/x; - } - - if(ix < 0x3feb0000) { /* |x|<0.84375 */ - if(ix < 0x3c700000) /* |x|<2**-56 */ - return one-x; - z = x*x; - r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4))); - s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5)))); - y = r/s; - if(hx < 0x3fd00000) { /* x<1/4 */ - return one-(x+x*y); - } else { - r = x*y; - r += (x-half); - return half - r ; - } - } - if(ix < 0x3ff40000) { /* 0.84375 <= |x| < 1.25 */ - s = fd_fabs(x)-one; - P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6))))); - Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6))))); - if(hx>=0) { - z = one-erx; return z - P/Q; - } else { - z = erx+P/Q; return one+z; - } - } - if (ix < 0x403c0000) { /* |x|<28 */ - x = fd_fabs(x); - s = one/(x*x); - if(ix< 0x4006DB6D) { /* |x| < 1/.35 ~ 2.857143*/ - R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*( - ra5+s*(ra6+s*ra7)))))); - S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*( - sa5+s*(sa6+s*(sa7+s*sa8))))))); - } else { /* |x| >= 1/.35 ~ 2.857143 */ - if(hx<0&&ix>=0x40180000) return two-tiny;/* x < -6 */ - R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*( - rb5+s*rb6))))); - S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*( - sb5+s*(sb6+s*sb7)))))); - } - z = x; - u.d = z; - __LO(u) = 0; - z = u.d; - r = __ieee754_exp(-z*z-0.5625)* - __ieee754_exp((z-x)*(z+x)+R/S); - if(hx>0) return r/x; else return two-r/x; - } else { - if(hx>0) return tiny*tiny; else return two-tiny; - } -} diff --git a/js/src/fdlibm/s_expm1.c b/js/src/fdlibm/s_expm1.c deleted file mode 100644 index 578d2e144ae1..000000000000 --- a/js/src/fdlibm/s_expm1.c +++ /dev/null @@ -1,267 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_expm1.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* expm1(x) - * Returns exp(x)-1, the exponential of x minus 1. - * - * Method - * 1. Argument reduction: - * Given x, find r and integer k such that - * - * x = k*ln2 + r, |r| <= 0.5*ln2 ~ 0.34658 - * - * Here a correction term c will be computed to compensate - * the error in r when rounded to a floating-point number. - * - * 2. Approximating expm1(r) by a special rational function on - * the interval [0,0.34658]: - * Since - * r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 - r^4/360 + ... - * we define R1(r*r) by - * r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 * R1(r*r) - * That is, - * R1(r**2) = 6/r *((exp(r)+1)/(exp(r)-1) - 2/r) - * = 6/r * ( 1 + 2.0*(1/(exp(r)-1) - 1/r)) - * = 1 - r^2/60 + r^4/2520 - r^6/100800 + ... - * We use a special Reme algorithm on [0,0.347] to generate - * a polynomial of degree 5 in r*r to approximate R1. The - * maximum error of this polynomial approximation is bounded - * by 2**-61. In other words, - * R1(z) ~ 1.0 + Q1*z + Q2*z**2 + Q3*z**3 + Q4*z**4 + Q5*z**5 - * where Q1 = -1.6666666666666567384E-2, - * Q2 = 3.9682539681370365873E-4, - * Q3 = -9.9206344733435987357E-6, - * Q4 = 2.5051361420808517002E-7, - * Q5 = -6.2843505682382617102E-9; - * (where z=r*r, and the values of Q1 to Q5 are listed below) - * with error bounded by - * | 5 | -61 - * | 1.0+Q1*z+...+Q5*z - R1(z) | <= 2 - * | | - * - * expm1(r) = exp(r)-1 is then computed by the following - * specific way which minimize the accumulation rounding error: - * 2 3 - * r r [ 3 - (R1 + R1*r/2) ] - * expm1(r) = r + --- + --- * [--------------------] - * 2 2 [ 6 - r*(3 - R1*r/2) ] - * - * To compensate the error in the argument reduction, we use - * expm1(r+c) = expm1(r) + c + expm1(r)*c - * ~ expm1(r) + c + r*c - * Thus c+r*c will be added in as the correction terms for - * expm1(r+c). Now rearrange the term to avoid optimization - * screw up: - * ( 2 2 ) - * ({ ( r [ R1 - (3 - R1*r/2) ] ) } r ) - * expm1(r+c)~r - ({r*(--- * [--------------------]-c)-c} - --- ) - * ({ ( 2 [ 6 - r*(3 - R1*r/2) ] ) } 2 ) - * ( ) - * - * = r - E - * 3. Scale back to obtain expm1(x): - * From step 1, we have - * expm1(x) = either 2^k*[expm1(r)+1] - 1 - * = or 2^k*[expm1(r) + (1-2^-k)] - * 4. Implementation notes: - * (A). To save one multiplication, we scale the coefficient Qi - * to Qi*2^i, and replace z by (x^2)/2. - * (B). To achieve maximum accuracy, we compute expm1(x) by - * (i) if x < -56*ln2, return -1.0, (raise inexact if x!=inf) - * (ii) if k=0, return r-E - * (iii) if k=-1, return 0.5*(r-E)-0.5 - * (iv) if k=1 if r < -0.25, return 2*((r+0.5)- E) - * else return 1.0+2.0*(r-E); - * (v) if (k<-2||k>56) return 2^k(1-(E-r)) - 1 (or exp(x)-1) - * (vi) if k <= 20, return 2^k((1-2^-k)-(E-r)), else - * (vii) return 2^k(1-((E+2^-k)-r)) - * - * Special cases: - * expm1(INF) is INF, expm1(NaN) is NaN; - * expm1(-INF) is -1, and - * for finite argument, only expm1(0)=0 is exact. - * - * Accuracy: - * according to an error analysis, the error is always less than - * 1 ulp (unit in the last place). - * - * Misc. info. - * For IEEE double - * if x > 7.09782712893383973096e+02 then expm1(x) overflow - * - * Constants: - * The hexadecimal values are the intended ones for the following - * constants. The decimal values may be used, provided that the - * compiler will convert from decimal to binary accurately enough - * to produce the hexadecimal values shown. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif -one = 1.0, -really_big = 1.0e+300, -tiny = 1.0e-300, -o_threshold = 7.09782712893383973096e+02,/* 0x40862E42, 0xFEFA39EF */ -ln2_hi = 6.93147180369123816490e-01,/* 0x3fe62e42, 0xfee00000 */ -ln2_lo = 1.90821492927058770002e-10,/* 0x3dea39ef, 0x35793c76 */ -invln2 = 1.44269504088896338700e+00,/* 0x3ff71547, 0x652b82fe */ - /* scaled coefficients related to expm1 */ -Q1 = -3.33333333333331316428e-02, /* BFA11111 111110F4 */ -Q2 = 1.58730158725481460165e-03, /* 3F5A01A0 19FE5585 */ -Q3 = -7.93650757867487942473e-05, /* BF14CE19 9EAADBB7 */ -Q4 = 4.00821782732936239552e-06, /* 3ED0CFCA 86E65239 */ -Q5 = -2.01099218183624371326e-07; /* BE8AFDB7 6E09C32D */ - -#ifdef __STDC__ - double fd_expm1(double x) -#else - double fd_expm1(x) - double x; -#endif -{ - fd_twoints u; - double y,hi,lo,c,t,e,hxs,hfx,r1; - int k,xsb; - unsigned hx; - - u.d = x; - hx = __HI(u); /* high word of x */ - xsb = hx&0x80000000; /* sign bit of x */ - if(xsb==0) y=x; else y= -x; /* y = |x| */ - hx &= 0x7fffffff; /* high word of |x| */ - - /* filter out huge and non-finite argument */ - if(hx >= 0x4043687A) { /* if |x|>=56*ln2 */ - if(hx >= 0x40862E42) { /* if |x|>=709.78... */ - if(hx>=0x7ff00000) { - u.d = x; - if(((hx&0xfffff)|__LO(u))!=0) - return x+x; /* NaN */ - else return (xsb==0)? x:-1.0;/* exp(+-inf)={inf,-1} */ - } - if(x > o_threshold) return really_big*really_big; /* overflow */ - } - if(xsb!=0) { /* x < -56*ln2, return -1.0 with inexact */ - if(x+tiny<0.0) /* raise inexact */ - return tiny-one; /* return -1 */ - } - } - - /* argument reduction */ - if(hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */ - if(hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */ - if(xsb==0) - {hi = x - ln2_hi; lo = ln2_lo; k = 1;} - else - {hi = x + ln2_hi; lo = -ln2_lo; k = -1;} - } else { - k = (int)(invln2*x+((xsb==0)?0.5:-0.5)); - t = k; - hi = x - t*ln2_hi; /* t*ln2_hi is exact here */ - lo = t*ln2_lo; - } - x = hi - lo; - c = (hi-x)-lo; - } - else if(hx < 0x3c900000) { /* when |x|<2**-54, return x */ - t = really_big+x; /* return x with inexact flags when x!=0 */ - return x - (t-(really_big+x)); - } - else k = 0; - - /* x is now in primary range */ - hfx = 0.5*x; - hxs = x*hfx; - r1 = one+hxs*(Q1+hxs*(Q2+hxs*(Q3+hxs*(Q4+hxs*Q5)))); - t = 3.0-r1*hfx; - e = hxs*((r1-t)/(6.0 - x*t)); - if(k==0) return x - (x*e-hxs); /* c is 0 */ - else { - e = (x*(e-c)-c); - e -= hxs; - if(k== -1) return 0.5*(x-e)-0.5; - if(k==1) - if(x < -0.25) return -2.0*(e-(x+0.5)); - else return one+2.0*(x-e); - if (k <= -2 || k>56) { /* suffice to return exp(x)-1 */ - y = one-(e-x); - u.d = y; - __HI(u) += (k<<20); /* add k to y's exponent */ - y = u.d; - return y-one; - } - t = one; - if(k<20) { - u.d = t; - __HI(u) = 0x3ff00000 - (0x200000>>k); /* t=1-2^-k */ - t = u.d; - y = t-(e-x); - u.d = y; - __HI(u) += (k<<20); /* add k to y's exponent */ - y = u.d; - } else { - u.d = t; - __HI(u) = ((0x3ff-k)<<20); /* 2^-k */ - t = u.d; - y = x-(e+t); - y += one; - u.d = y; - __HI(u) += (k<<20); /* add k to y's exponent */ - y = u.d; - } - } - return y; -} diff --git a/js/src/fdlibm/s_fabs.c b/js/src/fdlibm/s_fabs.c deleted file mode 100644 index 6b029da1013a..000000000000 --- a/js/src/fdlibm/s_fabs.c +++ /dev/null @@ -1,70 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_fabs.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * fabs(x) returns the absolute value of x. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - double fd_fabs(double x) -#else - double fd_fabs(x) - double x; -#endif -{ - fd_twoints u; - u.d = x; - __HI(u) &= 0x7fffffff; - x = u.d; - return x; -} diff --git a/js/src/fdlibm/s_finite.c b/js/src/fdlibm/s_finite.c deleted file mode 100644 index 4a0a4d3c603e..000000000000 --- a/js/src/fdlibm/s_finite.c +++ /dev/null @@ -1,71 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_finite.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * finite(x) returns 1 is x is finite, else 0; - * no branching! - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - int fd_finite(double x) -#else - int fd_finite(x) - double x; -#endif -{ - fd_twoints u; - int hx; - u.d = x; - hx = __HI(u); - return (unsigned)((hx&0x7fffffff)-0x7ff00000)>>31; -} diff --git a/js/src/fdlibm/s_floor.c b/js/src/fdlibm/s_floor.c deleted file mode 100644 index 6c23495f0e04..000000000000 --- a/js/src/fdlibm/s_floor.c +++ /dev/null @@ -1,121 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_floor.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * floor(x) - * Return x rounded toward -inf to integral value - * Method: - * Bit twiddling. - * Exception: - * Inexact flag raised if x not equal to floor(x). - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double really_big = 1.0e300; -#else -static double really_big = 1.0e300; -#endif - -#ifdef __STDC__ - double fd_floor(double x) -#else - double fd_floor(x) - double x; -#endif -{ - fd_twoints u; - int i0,i1,j0; - unsigned i,j; - u.d = x; - i0 = __HI(u); - i1 = __LO(u); - j0 = ((i0>>20)&0x7ff)-0x3ff; - if(j0<20) { - if(j0<0) { /* raise inexact if x != 0 */ - if(really_big+x>0.0) {/* return 0*sign(x) if |x|<1 */ - if(i0>=0) {i0=i1=0;} - else if(((i0&0x7fffffff)|i1)!=0) - { i0=0xbff00000;i1=0;} - } - } else { - i = (0x000fffff)>>j0; - if(((i0&i)|i1)==0) return x; /* x is integral */ - if(really_big+x>0.0) { /* raise inexact flag */ - if(i0<0) i0 += (0x00100000)>>j0; - i0 &= (~i); i1=0; - } - } - } else if (j0>51) { - if(j0==0x400) return x+x; /* inf or NaN */ - else return x; /* x is integral */ - } else { - i = ((unsigned)(0xffffffff))>>(j0-20); - if((i1&i)==0) return x; /* x is integral */ - if(really_big+x>0.0) { /* raise inexact flag */ - if(i0<0) { - if(j0==20) i0+=1; - else { - j = i1+(1<<(52-j0)); - if((int)j=0x7ff00000||((ix|lx)==0)) return x; /* 0,inf,nan */ - if (ix<0x00100000) { /* subnormal */ - x *= two54; - u.d = x; - hx = __HI(u); - ix = hx&0x7fffffff; - *eptr = -54; - } - *eptr += (ix>>20)-1022; - hx = (hx&0x800fffff)|0x3fe00000; - u.d = x; - __HI(u) = hx; - x = u.d; - return x; -} diff --git a/js/src/fdlibm/s_ilogb.c b/js/src/fdlibm/s_ilogb.c deleted file mode 100644 index f769781a62fb..000000000000 --- a/js/src/fdlibm/s_ilogb.c +++ /dev/null @@ -1,85 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_ilogb.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* ilogb(double x) - * return the binary exponent of non-zero x - * ilogb(0) = 0x80000001 - * ilogb(inf/NaN) = 0x7fffffff (no signal is raised) - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - int fd_ilogb(double x) -#else - int fd_ilogb(x) - double x; -#endif -{ - int hx,lx,ix; - fd_twoints u; - u.d = x; - hx = (__HI(u))&0x7fffffff; /* high word of x */ - if(hx<0x00100000) { - lx = __LO(u); - if((hx|lx)==0) - return 0x80000001; /* ilogb(0) = 0x80000001 */ - else /* subnormal x */ - if(hx==0) { - for (ix = -1043; lx>0; lx<<=1) ix -=1; - } else { - for (ix = -1022,hx<<=11; hx>0; hx<<=1) ix -=1; - } - return ix; - } - else if (hx<0x7ff00000) return (hx>>20)-1023; - else return 0x7fffffff; -} diff --git a/js/src/fdlibm/s_isnan.c b/js/src/fdlibm/s_isnan.c deleted file mode 100644 index 52f8759c7936..000000000000 --- a/js/src/fdlibm/s_isnan.c +++ /dev/null @@ -1,74 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_isnan.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * isnan(x) returns 1 is x is nan, else 0; - * no branching! - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - int fd_isnan(double x) -#else - int fd_isnan(x) - double x; -#endif -{ - fd_twoints u; - int hx,lx; - u.d = x; - hx = (__HI(u)&0x7fffffff); - lx = __LO(u); - hx |= (unsigned)(lx|(-lx))>>31; - hx = 0x7ff00000 - hx; - return ((unsigned)(hx))>>31; -} diff --git a/js/src/fdlibm/s_ldexp.c b/js/src/fdlibm/s_ldexp.c deleted file mode 100644 index 9475520d4802..000000000000 --- a/js/src/fdlibm/s_ldexp.c +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_ldexp.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -#include "fdlibm.h" -#include - -#ifdef __STDC__ - double fd_ldexp(double value, int exp) -#else - double fd_ldexp(value, exp) - double value; int exp; -#endif -{ - if(!fd_finite(value)||value==0.0) return value; - value = fd_scalbn(value,exp); - if(!fd_finite(value)||value==0.0) errno = ERANGE; - return value; -} diff --git a/js/src/fdlibm/s_lib_version.c b/js/src/fdlibm/s_lib_version.c deleted file mode 100644 index 2ccf67d51c89..000000000000 --- a/js/src/fdlibm/s_lib_version.c +++ /dev/null @@ -1,73 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_lib_version.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * MACRO for standards - */ - -#include "fdlibm.h" - -/* - * define and initialize _LIB_VERSION - */ -#ifdef _POSIX_MODE -_LIB_VERSION_TYPE _LIB_VERSION = _POSIX_; -#else -#ifdef _XOPEN_MODE -_LIB_VERSION_TYPE _LIB_VERSION = _XOPEN_; -#else -#ifdef _SVID3_MODE -_LIB_VERSION_TYPE _LIB_VERSION = _SVID_; -#else /* default _IEEE_MODE */ -_LIB_VERSION_TYPE _LIB_VERSION = _IEEE_; -#endif -#endif -#endif diff --git a/js/src/fdlibm/s_log1p.c b/js/src/fdlibm/s_log1p.c deleted file mode 100644 index 1840156b1cda..000000000000 --- a/js/src/fdlibm/s_log1p.c +++ /dev/null @@ -1,211 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_log1p.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* double log1p(double x) - * - * Method : - * 1. Argument Reduction: find k and f such that - * 1+x = 2^k * (1+f), - * where sqrt(2)/2 < 1+f < sqrt(2) . - * - * Note. If k=0, then f=x is exact. However, if k!=0, then f - * may not be representable exactly. In that case, a correction - * term is need. Let u=1+x rounded. Let c = (1+x)-u, then - * log(1+x) - log(u) ~ c/u. Thus, we proceed to compute log(u), - * and add back the correction term c/u. - * (Note: when x > 2**53, one can simply return log(x)) - * - * 2. Approximation of log1p(f). - * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s) - * = 2s + 2/3 s**3 + 2/5 s**5 + ....., - * = 2s + s*R - * We use a special Reme algorithm on [0,0.1716] to generate - * a polynomial of degree 14 to approximate R The maximum error - * of this polynomial approximation is bounded by 2**-58.45. In - * other words, - * 2 4 6 8 10 12 14 - * R(z) ~ Lp1*s +Lp2*s +Lp3*s +Lp4*s +Lp5*s +Lp6*s +Lp7*s - * (the values of Lp1 to Lp7 are listed in the program) - * and - * | 2 14 | -58.45 - * | Lp1*s +...+Lp7*s - R(z) | <= 2 - * | | - * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2. - * In order to guarantee error in log below 1ulp, we compute log - * by - * log1p(f) = f - (hfsq - s*(hfsq+R)). - * - * 3. Finally, log1p(x) = k*ln2 + log1p(f). - * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo))) - * Here ln2 is split into two floating point number: - * ln2_hi + ln2_lo, - * where n*ln2_hi is always exact for |n| < 2000. - * - * Special cases: - * log1p(x) is NaN with signal if x < -1 (including -INF) ; - * log1p(+INF) is +INF; log1p(-1) is -INF with signal; - * log1p(NaN) is that NaN with no signal. - * - * Accuracy: - * according to an error analysis, the error is always less than - * 1 ulp (unit in the last place). - * - * Constants: - * The hexadecimal values are the intended ones for the following - * constants. The decimal values may be used, provided that the - * compiler will convert from decimal to binary accurately enough - * to produce the hexadecimal values shown. - * - * Note: Assuming log() return accurate answer, the following - * algorithm can be used to compute log1p(x) to within a few ULP: - * - * u = 1+x; - * if(u==1.0) return x ; else - * return log(u)*(x/(u-1.0)); - * - * See HP-15C Advanced Functions Handbook, p.193. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif -ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */ -ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */ -two54 = 1.80143985094819840000e+16, /* 43500000 00000000 */ -Lp1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */ -Lp2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */ -Lp3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */ -Lp4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */ -Lp5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */ -Lp6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */ -Lp7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ - -static double zero = 0.0; - -#ifdef __STDC__ - double fd_log1p(double x) -#else - double fd_log1p(x) - double x; -#endif -{ - double hfsq,f,c,s,z,R,u; - int k,hx,hu,ax; - fd_twoints un; - - un.d = x; - hx = __HI(un); /* high word of x */ - ax = hx&0x7fffffff; - - k = 1; - if (hx < 0x3FDA827A) { /* x < 0.41422 */ - if(ax>=0x3ff00000) { /* x <= -1.0 */ - if(x==-1.0) return -two54/zero; /* log1p(-1)=+inf */ - else return (x-x)/(x-x); /* log1p(x<-1)=NaN */ - } - if(ax<0x3e200000) { /* |x| < 2**-29 */ - if(two54+x>zero /* raise inexact */ - &&ax<0x3c900000) /* |x| < 2**-54 */ - return x; - else - return x - x*x*0.5; - } - if(hx>0||hx<=((int)0xbfd2bec3)) { - k=0;f=x;hu=1;} /* -0.2929= 0x7ff00000) return x+x; - if(k!=0) { - if(hx<0x43400000) { - u = 1.0+x; - un.d = u; - hu = __HI(un); /* high word of u */ - k = (hu>>20)-1023; - c = (k>0)? 1.0-(u-x):x-(u-1.0);/* correction term */ - c /= u; - } else { - u = x; - un.d = u; - hu = __HI(un); /* high word of u */ - k = (hu>>20)-1023; - c = 0; - } - hu &= 0x000fffff; - if(hu<0x6a09e) { - un.d = u; - __HI(un) = hu|0x3ff00000; /* normalize u */ - u = un.d; - } else { - k += 1; - un.d = u; - __HI(un) = hu|0x3fe00000; /* normalize u/2 */ - u = un.d; - hu = (0x00100000-hu)>>2; - } - f = u-1.0; - } - hfsq=0.5*f*f; - if(hu==0) { /* |f| < 2**-20 */ - if(f==zero) if(k==0) return zero; - else {c += k*ln2_lo; return k*ln2_hi+c;} - R = hfsq*(1.0-0.66666666666666666*f); - if(k==0) return f-R; else - return k*ln2_hi-((R-(k*ln2_lo+c))-f); - } - s = f/(2.0+f); - z = s*s; - R = z*(Lp1+z*(Lp2+z*(Lp3+z*(Lp4+z*(Lp5+z*(Lp6+z*Lp7)))))); - if(k==0) return f-(hfsq-s*(hfsq+R)); else - return k*ln2_hi-((hfsq-(s*(hfsq+R)+(k*ln2_lo+c)))-f); -} diff --git a/js/src/fdlibm/s_logb.c b/js/src/fdlibm/s_logb.c deleted file mode 100644 index f885c4dc3897..000000000000 --- a/js/src/fdlibm/s_logb.c +++ /dev/null @@ -1,79 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_logb.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * double logb(x) - * IEEE 754 logb. Included to pass IEEE test suite. Not recommend. - * Use ilogb instead. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - double fd_logb(double x) -#else - double fd_logb(x) - double x; -#endif -{ - int lx,ix; - fd_twoints u; - - u.d = x; - ix = (__HI(u))&0x7fffffff; /* high |x| */ - lx = __LO(u); /* low x */ - if((ix|lx)==0) return -1.0/fd_fabs(x); - if(ix>=0x7ff00000) return x*x; - if((ix>>=20)==0) /* IEEE 754 logb */ - return -1022.0; - else - return (double) (ix-1023); -} diff --git a/js/src/fdlibm/s_matherr.c b/js/src/fdlibm/s_matherr.c deleted file mode 100644 index cd99ca88f3c9..000000000000 --- a/js/src/fdlibm/s_matherr.c +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_matherr.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - int fd_matherr(struct exception *x) -#else - int fd_matherr(x) - struct exception *x; -#endif -{ - int n=0; - if(x->arg1!=x->arg1) return 0; - return n; -} diff --git a/js/src/fdlibm/s_modf.c b/js/src/fdlibm/s_modf.c deleted file mode 100644 index 3b182bd3bbf7..000000000000 --- a/js/src/fdlibm/s_modf.c +++ /dev/null @@ -1,132 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_modf.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * modf(double x, double *iptr) - * return fraction part of x, and return x's integral part in *iptr. - * Method: - * Bit twiddling. - * - * Exception: - * No exception. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double one = 1.0; -#else -static double one = 1.0; -#endif - -#ifdef __STDC__ - double fd_modf(double x, double *iptr) -#else - double fd_modf(x, iptr) - double x,*iptr; -#endif -{ - int i0,i1,j0; - unsigned i; - fd_twoints u; - u.d = x; - i0 = __HI(u); /* high x */ - i1 = __LO(u); /* low x */ - j0 = ((i0>>20)&0x7ff)-0x3ff; /* exponent of x */ - if(j0<20) { /* integer part in high x */ - if(j0<0) { /* |x|<1 */ - u.d = *iptr; - __HI(u) = i0&0x80000000; - __LO(u) = 0; /* *iptr = +-0 */ - *iptr = u.d; - return x; - } else { - i = (0x000fffff)>>j0; - if(((i0&i)|i1)==0) { /* x is integral */ - *iptr = x; - u.d = x; - __HI(u) &= 0x80000000; - __LO(u) = 0; /* return +-0 */ - x = u.d; - return x; - } else { - u.d = *iptr; - __HI(u) = i0&(~i); - __LO(u) = 0; - *iptr = u.d; - return x - *iptr; - } - } - } else if (j0>51) { /* no fraction part */ - *iptr = x*one; - u.d = x; - __HI(u) &= 0x80000000; - __LO(u) = 0; /* return +-0 */ - x = u.d; - return x; - } else { /* fraction part in low x */ - i = ((unsigned)(0xffffffff))>>(j0-20); - if((i1&i)==0) { /* x is integral */ - *iptr = x; - u.d = x; - __HI(u) &= 0x80000000; - __LO(u) = 0; /* return +-0 */ - x = u.d; - return x; - } else { - u.d = *iptr; - __HI(u) = i0; - __LO(u) = i1&(~i); - *iptr = u.d; - return x - *iptr; - } - } -} diff --git a/js/src/fdlibm/s_nextafter.c b/js/src/fdlibm/s_nextafter.c deleted file mode 100644 index f71c5c8359af..000000000000 --- a/js/src/fdlibm/s_nextafter.c +++ /dev/null @@ -1,124 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_nextafter.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* IEEE functions - * nextafter(x,y) - * return the next machine floating-point number of x in the - * direction toward y. - * Special cases: - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - double fd_nextafter(double x, double y) -#else - double fd_nextafter(x,y) - double x,y; -#endif -{ - int hx,hy,ix,iy; - unsigned lx,ly; - fd_twoints ux, uy; - - ux.d = x; uy.d = y; - hx = __HI(ux); /* high word of x */ - lx = __LO(ux); /* low word of x */ - hy = __HI(uy); /* high word of y */ - ly = __LO(uy); /* low word of y */ - ix = hx&0x7fffffff; /* |x| */ - iy = hy&0x7fffffff; /* |y| */ - - if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) || /* x is nan */ - ((iy>=0x7ff00000)&&((iy-0x7ff00000)|ly)!=0)) /* y is nan */ - return x+y; - if(x==y) return x; /* x=y, return x */ - if((ix|lx)==0) { /* x == 0 */ - ux.d = x; - __HI(ux) = hy&0x80000000; /* return +-minsubnormal */ - __LO(ux) = 1; - x = ux.d; - y = x*x; - if(y==x) return y; else return x; /* raise underflow flag */ - } - if(hx>=0) { /* x > 0 */ - if(hx>hy||((hx==hy)&&(lx>ly))) { /* x > y, x -= ulp */ - if(lx==0) hx -= 1; - lx -= 1; - } else { /* x < y, x += ulp */ - lx += 1; - if(lx==0) hx += 1; - } - } else { /* x < 0 */ - if(hy>=0||hx>hy||((hx==hy)&&(lx>ly))){/* x < y, x -= ulp */ - if(lx==0) hx -= 1; - lx -= 1; - } else { /* x > y, x += ulp */ - lx += 1; - if(lx==0) hx += 1; - } - } - hy = hx&0x7ff00000; - if(hy>=0x7ff00000) return x+x; /* overflow */ - if(hy<0x00100000) { /* underflow */ - y = x*x; - if(y!=x) { /* raise underflow flag */ - uy.d = y; - __HI(uy) = hx; __LO(uy) = lx; - y = uy.d; - return y; - } - } - ux.d = x; - __HI(ux) = hx; __LO(ux) = lx; - x = ux.d; - return x; -} diff --git a/js/src/fdlibm/s_rint.c b/js/src/fdlibm/s_rint.c deleted file mode 100644 index 3c4fab6d9d9c..000000000000 --- a/js/src/fdlibm/s_rint.c +++ /dev/null @@ -1,131 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_rint.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * rint(x) - * Return x rounded to integral value according to the prevailing - * rounding mode. - * Method: - * Using floating addition. - * Exception: - * Inexact flag raised if x not equal to rint(x). - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif -TWO52[2]={ - 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ - -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ -}; - -#ifdef __STDC__ - double fd_rint(double x) -#else - double fd_rint(x) - double x; -#endif -{ - int i0,j0,sx; - unsigned i,i1; - double w,t; - fd_twoints u; - - u.d = x; - i0 = __HI(u); - sx = (i0>>31)&1; - i1 = __LO(u); - j0 = ((i0>>20)&0x7ff)-0x3ff; - if(j0<20) { - if(j0<0) { - if(((i0&0x7fffffff)|i1)==0) return x; - i1 |= (i0&0x0fffff); - i0 &= 0xfffe0000; - i0 |= ((i1|-(int)i1)>>12)&0x80000; - u.d = x; - __HI(u)=i0; - x = u.d; - w = TWO52[sx]+x; - t = w-TWO52[sx]; - u.d = t; - i0 = __HI(u); - __HI(u) = (i0&0x7fffffff)|(sx<<31); - t = u.d; - return t; - } else { - i = (0x000fffff)>>j0; - if(((i0&i)|i1)==0) return x; /* x is integral */ - i>>=1; - if(((i0&i)|i1)!=0) { - if(j0==19) i1 = 0x40000000; else - i0 = (i0&(~i))|((0x20000)>>j0); - } - } - } else if (j0>51) { - if(j0==0x400) return x+x; /* inf or NaN */ - else return x; /* x is integral */ - } else { - i = ((unsigned)(0xffffffff))>>(j0-20); - if((i1&i)==0) return x; /* x is integral */ - i>>=1; - if((i1&i)!=0) i1 = (i1&(~i))|((0x40000000)>>(j0-20)); - } - u.d = x; - __HI(u) = i0; - __LO(u) = i1; - x = u.d; - w = TWO52[sx]+x; - return w-TWO52[sx]; -} diff --git a/js/src/fdlibm/s_scalbn.c b/js/src/fdlibm/s_scalbn.c deleted file mode 100644 index 3deeaa3057e0..000000000000 --- a/js/src/fdlibm/s_scalbn.c +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_scalbn.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * scalbn (double x, int n) - * scalbn(x,n) returns x* 2**n computed by exponent - * manipulation rather than by actually performing an - * exponentiation or a multiplication. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif -two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ -twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */ -really_big = 1.0e+300, -tiny = 1.0e-300; - -#ifdef __STDC__ - double fd_scalbn (double x, int n) -#else - double fd_scalbn (x,n) - double x; int n; -#endif -{ - fd_twoints u; - int k,hx,lx; - u.d = x; - hx = __HI(u); - lx = __LO(u); - k = (hx&0x7ff00000)>>20; /* extract exponent */ - if (k==0) { /* 0 or subnormal x */ - if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */ - x *= two54; - u.d = x; - hx = __HI(u); - k = ((hx&0x7ff00000)>>20) - 54; - if (n< -50000) return tiny*x; /*underflow*/ - } - if (k==0x7ff) return x+x; /* NaN or Inf */ - k = k+n; - if (k > 0x7fe) return really_big*fd_copysign(really_big,x); /* overflow */ - if (k > 0) /* normal result */ - {u.d = x; __HI(u) = (hx&0x800fffff)|(k<<20); x = u.d; return x;} - if (k <= -54) { - if (n > 50000) /* in case integer overflow in n+k */ - return really_big*fd_copysign(really_big,x); /*overflow*/ - else return tiny*fd_copysign(tiny,x); /*underflow*/ - } - k += 54; /* subnormal result */ - u.d = x; - __HI(u) = (hx&0x800fffff)|(k<<20); - x = u.d; - return x*twom54; -} diff --git a/js/src/fdlibm/s_signgam.c b/js/src/fdlibm/s_signgam.c deleted file mode 100644 index 4eb8ce72f8c8..000000000000 --- a/js/src/fdlibm/s_signgam.c +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -#include "fdlibm.h" -int signgam = 0; diff --git a/js/src/fdlibm/s_significand.c b/js/src/fdlibm/s_significand.c deleted file mode 100644 index 2e1c0b28fb1c..000000000000 --- a/js/src/fdlibm/s_significand.c +++ /dev/null @@ -1,68 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_significand.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * significand(x) computes just - * scalb(x, (double) -ilogb(x)), - * for exercising the fraction-part(F) IEEE 754-1985 test vector. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - double fd_significand(double x) -#else - double fd_significand(x) - double x; -#endif -{ - return __ieee754_scalb(x,(double) -fd_ilogb(x)); -} diff --git a/js/src/fdlibm/s_sin.c b/js/src/fdlibm/s_sin.c deleted file mode 100644 index 8bbc5c62d928..000000000000 --- a/js/src/fdlibm/s_sin.c +++ /dev/null @@ -1,118 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_sin.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* sin(x) - * Return sine function of x. - * - * kernel function: - * __kernel_sin ... sine function on [-pi/4,pi/4] - * __kernel_cos ... cose function on [-pi/4,pi/4] - * __ieee754_rem_pio2 ... argument reduction routine - * - * Method. - * Let S,C and T denote the sin, cos and tan respectively on - * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2 - * in [-pi/4 , +pi/4], and let n = k mod 4. - * We have - * - * n sin(x) cos(x) tan(x) - * ---------------------------------------------------------- - * 0 S C T - * 1 C -S -1/T - * 2 -S -C T - * 3 -C S -1/T - * ---------------------------------------------------------- - * - * Special cases: - * Let trig be any of sin, cos, or tan. - * trig(+-INF) is NaN, with signals; - * trig(NaN) is that NaN; - * - * Accuracy: - * TRIG(x) returns trig(x) nearly rounded - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - double fd_sin(double x) -#else - double fd_sin(x) - double x; -#endif -{ - fd_twoints u; - double y[2],z=0.0; - int n, ix; - - /* High word of x. */ - u.d = x; - ix = __HI(u); - - /* |x| ~< pi/4 */ - ix &= 0x7fffffff; - if(ix <= 0x3fe921fb) return __kernel_sin(x,z,0); - - /* sin(Inf or NaN) is NaN */ - else if (ix>=0x7ff00000) return x-x; - - /* argument reduction needed */ - else { - n = __ieee754_rem_pio2(x,y); - switch(n&3) { - case 0: return __kernel_sin(y[0],y[1],1); - case 1: return __kernel_cos(y[0],y[1]); - case 2: return -__kernel_sin(y[0],y[1],1); - default: - return -__kernel_cos(y[0],y[1]); - } - } -} diff --git a/js/src/fdlibm/s_tan.c b/js/src/fdlibm/s_tan.c deleted file mode 100644 index ded36c1d7c13..000000000000 --- a/js/src/fdlibm/s_tan.c +++ /dev/null @@ -1,112 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_tan.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* tan(x) - * Return tangent function of x. - * - * kernel function: - * __kernel_tan ... tangent function on [-pi/4,pi/4] - * __ieee754_rem_pio2 ... argument reduction routine - * - * Method. - * Let S,C and T denote the sin, cos and tan respectively on - * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2 - * in [-pi/4 , +pi/4], and let n = k mod 4. - * We have - * - * n sin(x) cos(x) tan(x) - * ---------------------------------------------------------- - * 0 S C T - * 1 C -S -1/T - * 2 -S -C T - * 3 -C S -1/T - * ---------------------------------------------------------- - * - * Special cases: - * Let trig be any of sin, cos, or tan. - * trig(+-INF) is NaN, with signals; - * trig(NaN) is that NaN; - * - * Accuracy: - * TRIG(x) returns trig(x) nearly rounded - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - double fd_tan(double x) -#else - double fd_tan(x) - double x; -#endif -{ - fd_twoints u; - double y[2],z=0.0; - int n, ix; - - /* High word of x. */ - u.d = x; - ix = __HI(u); - - /* |x| ~< pi/4 */ - ix &= 0x7fffffff; - if(ix <= 0x3fe921fb) return __kernel_tan(x,z,1); - - /* tan(Inf or NaN) is NaN */ - else if (ix>=0x7ff00000) return x-x; /* NaN */ - - /* argument reduction needed */ - else { - n = __ieee754_rem_pio2(x,y); - return __kernel_tan(y[0],y[1],1-((n&1)<<1)); /* 1 -- n even - -1 -- n odd */ - } -} diff --git a/js/src/fdlibm/s_tanh.c b/js/src/fdlibm/s_tanh.c deleted file mode 100644 index aa6809f85180..000000000000 --- a/js/src/fdlibm/s_tanh.c +++ /dev/null @@ -1,122 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)s_tanh.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* Tanh(x) - * Return the Hyperbolic Tangent of x - * - * Method : - * x -x - * e - e - * 0. tanh(x) is defined to be ----------- - * x -x - * e + e - * 1. reduce x to non-negative by tanh(-x) = -tanh(x). - * 2. 0 <= x <= 2**-55 : tanh(x) := x*(one+x) - * -t - * 2**-55 < x <= 1 : tanh(x) := -----; t = expm1(-2x) - * t + 2 - * 2 - * 1 <= x <= 22.0 : tanh(x) := 1- ----- ; t=expm1(2x) - * t + 2 - * 22.0 < x <= INF : tanh(x) := 1. - * - * Special cases: - * tanh(NaN) is NaN; - * only tanh(0)=0 is exact for finite argument. - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double one=1.0, two=2.0, tiny = 1.0e-300; -#else -static double one=1.0, two=2.0, tiny = 1.0e-300; -#endif - -#ifdef __STDC__ - double fd_tanh(double x) -#else - double fd_tanh(x) - double x; -#endif -{ - double t,z; - int jx,ix; - fd_twoints u; - - /* High word of |x|. */ - u.d = x; - jx = __HI(u); - ix = jx&0x7fffffff; - - /* x is INF or NaN */ - if(ix>=0x7ff00000) { - if (jx>=0) return one/x+one; /* tanh(+-inf)=+-1 */ - else return one/x-one; /* tanh(NaN) = NaN */ - } - - /* |x| < 22 */ - if (ix < 0x40360000) { /* |x|<22 */ - if (ix<0x3c800000) /* |x|<2**-55 */ - return x*(one+x); /* tanh(small) = small */ - if (ix>=0x3ff00000) { /* |x|>=1 */ - t = fd_expm1(two*fd_fabs(x)); - z = one - two/(t+two); - } else { - t = fd_expm1(-two*fd_fabs(x)); - z= -t/(t+two); - } - /* |x| > 22, return +-1 */ - } else { - z = one - tiny; /* raised inexact flag */ - } - return (jx>=0)? z: -z; -} diff --git a/js/src/fdlibm/w_acos.c b/js/src/fdlibm/w_acos.c deleted file mode 100644 index 872c81d2081e..000000000000 --- a/js/src/fdlibm/w_acos.c +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)w_acos.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * wrap_acos(x) - */ - -#include "fdlibm.h" - - -#ifdef __STDC__ - double fd_acos(double x) /* wrapper acos */ -#else - double fd_acos(x) /* wrapper acos */ - double x; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_acos(x); -#else - double z; - z = __ieee754_acos(x); - if(_LIB_VERSION == _IEEE_ || fd_isnan(x)) return z; - if(fd_fabs(x)>1.0) { - int err; - return __kernel_standard(x,x,1,&err); /* acos(|x|>1) */ - } else - return z; -#endif -} diff --git a/js/src/fdlibm/w_acosh.c b/js/src/fdlibm/w_acosh.c deleted file mode 100644 index 745d402eabc8..000000000000 --- a/js/src/fdlibm/w_acosh.c +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)w_acosh.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - * - */ - -/* - * wrapper acosh(x) - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - double fd_acosh(double x) /* wrapper acosh */ -#else - double fd_acosh(x) /* wrapper acosh */ - double x; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_acosh(x); -#else - double z; - z = __ieee754_acosh(x); - if(_LIB_VERSION == _IEEE_ || fd_isnan(x)) return z; - if(x<1.0) { - int err; - return __kernel_standard(x,x,29,&err); /* acosh(x<1) */ - } else - return z; -#endif -} diff --git a/js/src/fdlibm/w_asin.c b/js/src/fdlibm/w_asin.c deleted file mode 100644 index 18aaefde9ba3..000000000000 --- a/js/src/fdlibm/w_asin.c +++ /dev/null @@ -1,80 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)w_asin.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - * - */ - -/* - * wrapper asin(x) - */ - - -#include "fdlibm.h" - - -#ifdef __STDC__ - double fd_asin(double x) /* wrapper asin */ -#else - double fd_asin(x) /* wrapper asin */ - double x; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_asin(x); -#else - double z; - z = __ieee754_asin(x); - if(_LIB_VERSION == _IEEE_ || fd_isnan(x)) return z; - if(fd_fabs(x)>1.0) { - int err; - return __kernel_standard(x,x,2,&err); /* asin(|x|>1) */ - } else - return z; -#endif -} diff --git a/js/src/fdlibm/w_atan2.c b/js/src/fdlibm/w_atan2.c deleted file mode 100644 index 8cfa4bbbde41..000000000000 --- a/js/src/fdlibm/w_atan2.c +++ /dev/null @@ -1,79 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)w_atan2.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - * - */ - -/* - * wrapper atan2(y,x) - */ - -#include "fdlibm.h" - - -#ifdef __STDC__ - double fd_atan2(double y, double x) /* wrapper atan2 */ -#else - double fd_atan2(y,x) /* wrapper atan2 */ - double y,x; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_atan2(y,x); -#else - double z; - z = __ieee754_atan2(y,x); - if(_LIB_VERSION == _IEEE_||fd_isnan(x)||fd_isnan(y)) return z; - if(x==0.0&&y==0.0) { - int err; - return __kernel_standard(y,x,3,&err); /* atan2(+-0,+-0) */ - } else - return z; -#endif -} diff --git a/js/src/fdlibm/w_atanh.c b/js/src/fdlibm/w_atanh.c deleted file mode 100644 index 6ba52d1e26fb..000000000000 --- a/js/src/fdlibm/w_atanh.c +++ /dev/null @@ -1,81 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)w_atanh.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ -/* - * wrapper atanh(x) - */ - -#include "fdlibm.h" - - -#ifdef __STDC__ - double fd_atanh(double x) /* wrapper atanh */ -#else - double fd_atanh(x) /* wrapper atanh */ - double x; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_atanh(x); -#else - double z,y; - z = __ieee754_atanh(x); - if(_LIB_VERSION == _IEEE_ || fd_isnan(x)) return z; - y = fd_fabs(x); - if(y>=1.0) { - int err; - if(y>1.0) - return __kernel_standard(x,x,30,&err); /* atanh(|x|>1) */ - else - return __kernel_standard(x,x,31,&err); /* atanh(|x|==1) */ - } else - return z; -#endif -} diff --git a/js/src/fdlibm/w_cosh.c b/js/src/fdlibm/w_cosh.c deleted file mode 100644 index 146449e02060..000000000000 --- a/js/src/fdlibm/w_cosh.c +++ /dev/null @@ -1,77 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)w_cosh.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * wrapper cosh(x) - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - double fd_cosh(double x) /* wrapper cosh */ -#else - double fd_cosh(x) /* wrapper cosh */ - double x; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_cosh(x); -#else - double z; - z = __ieee754_cosh(x); - if(_LIB_VERSION == _IEEE_ || fd_isnan(x)) return z; - if(fd_fabs(x)>7.10475860073943863426e+02) { - int err; - return __kernel_standard(x,x,5,&err); /* cosh overflow */ - } else - return z; -#endif -} diff --git a/js/src/fdlibm/w_exp.c b/js/src/fdlibm/w_exp.c deleted file mode 100644 index f5dea0b01111..000000000000 --- a/js/src/fdlibm/w_exp.c +++ /dev/null @@ -1,88 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)w_exp.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * wrapper exp(x) - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const double -#else -static double -#endif -o_threshold= 7.09782712893383973096e+02, /* 0x40862E42, 0xFEFA39EF */ -u_threshold= -7.45133219101941108420e+02; /* 0xc0874910, 0xD52D3051 */ - -#ifdef __STDC__ - double fd_exp(double x) /* wrapper exp */ -#else - double fd_exp(x) /* wrapper exp */ - double x; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_exp(x); -#else - double z; - z = __ieee754_exp(x); - if(_LIB_VERSION == _IEEE_) return z; - if(fd_finite(x)) { - int err; - if(x>o_threshold) - return __kernel_standard(x,x,6,&err); /* exp overflow */ - else if(xX_TLOSS) { - int err; - return __kernel_standard(x,x,34,&err); /* j0(|x|>X_TLOSS) */ - } else - return z; -#endif -} - -#ifdef __STDC__ - double y0(double x) /* wrapper y0 */ -#else - double y0(x) /* wrapper y0 */ - double x; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_y0(x); -#else - double z; - int err; - z = __ieee754_y0(x); - if(_LIB_VERSION == _IEEE_ || fd_isnan(x) ) return z; - if(x <= 0.0){ - if(x==0.0) - /* d= -one/(x-x); */ - return __kernel_standard(x,x,8,&err); - else - /* d = zero/(x-x); */ - return __kernel_standard(x,x,9,&err); - } - if(x>X_TLOSS) { - return __kernel_standard(x,x,35,&err); /* y0(x>X_TLOSS) */ - } else - return z; -#endif -} diff --git a/js/src/fdlibm/w_j1.c b/js/src/fdlibm/w_j1.c deleted file mode 100644 index 86a506bc289f..000000000000 --- a/js/src/fdlibm/w_j1.c +++ /dev/null @@ -1,106 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)w_j1.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * wrapper of j1,y1 - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - double fd_j1(double x) /* wrapper j1 */ -#else - double fd_j1(x) /* wrapper j1 */ - double x; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_j1(x); -#else - double z; - z = __ieee754_j1(x); - if(_LIB_VERSION == _IEEE_ || fd_isnan(x) ) return z; - if(fd_fabs(x)>X_TLOSS) { - int err; - return __kernel_standard(x,x,36,&err); /* j1(|x|>X_TLOSS) */ - } else - return z; -#endif -} - -#ifdef __STDC__ - double y1(double x) /* wrapper y1 */ -#else - double y1(x) /* wrapper y1 */ - double x; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_y1(x); -#else - double z; - int err; - z = __ieee754_y1(x); - if(_LIB_VERSION == _IEEE_ || fd_isnan(x) ) return z; - if(x <= 0.0){ - if(x==0.0) - /* d= -one/(x-x); */ - return __kernel_standard(x,x,10,&err); - else - /* d = zero/(x-x); */ - return __kernel_standard(x,x,11,&err); - } - if(x>X_TLOSS) { - return __kernel_standard(x,x,37,&err); /* y1(x>X_TLOSS) */ - } else - return z; -#endif -} diff --git a/js/src/fdlibm/w_jn.c b/js/src/fdlibm/w_jn.c deleted file mode 100644 index 6926b0da87ab..000000000000 --- a/js/src/fdlibm/w_jn.c +++ /dev/null @@ -1,128 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)w_jn.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * wrapper jn(int n, double x), yn(int n, double x) - * floating point Bessel's function of the 1st and 2nd kind - * of order n - * - * Special cases: - * y0(0)=y1(0)=yn(n,0) = -inf with division by zero signal; - * y0(-ve)=y1(-ve)=yn(n,-ve) are NaN with invalid signal. - * Note 2. About jn(n,x), yn(n,x) - * For n=0, j0(x) is called, - * for n=1, j1(x) is called, - * for nx, a continued fraction approximation to - * j(n,x)/j(n-1,x) is evaluated and then backward - * recursion is used starting from a supposed value - * for j(n,x). The resulting value of j(0,x) is - * compared with the actual value to correct the - * supposed value of j(n,x). - * - * yn(n,x) is similar in all respects, except - * that forward recursion is used for all - * values of n>1. - * - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - double fd_jn(int n, double x) /* wrapper jn */ -#else - double fd_jn(n,x) /* wrapper jn */ - double x; int n; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_jn(n,x); -#else - double z; - z = __ieee754_jn(n,x); - if(_LIB_VERSION == _IEEE_ || fd_isnan(x) ) return z; - if(fd_fabs(x)>X_TLOSS) { - int err; - return __kernel_standard((double)n,x,38,&err); /* jn(|x|>X_TLOSS,n) */ - } else - return z; -#endif -} - -#ifdef __STDC__ - double yn(int n, double x) /* wrapper yn */ -#else - double yn(n,x) /* wrapper yn */ - double x; int n; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_yn(n,x); -#else - double z; - int err; - z = __ieee754_yn(n,x); - if(_LIB_VERSION == _IEEE_ || fd_isnan(x) ) return z; - if(x <= 0.0){ - if(x==0.0) - /* d= -one/(x-x); */ - return __kernel_standard((double)n,x,12,&err); - else - /* d = zero/(x-x); */ - return __kernel_standard((double)n,x,13,&err); - } - if(x>X_TLOSS) { - return __kernel_standard((double)n,x,39,&err); /* yn(x>X_TLOSS,n) */ - } else - return z; -#endif -} diff --git a/js/src/fdlibm/w_lgamma.c b/js/src/fdlibm/w_lgamma.c deleted file mode 100644 index f7576e892139..000000000000 --- a/js/src/fdlibm/w_lgamma.c +++ /dev/null @@ -1,85 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)w_lgamma.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - * - */ - -/* double lgamma(double x) - * Return the logarithm of the Gamma function of x. - * - * Method: call __ieee754_lgamma_r - */ - -#include "fdlibm.h" - -extern int signgam; - -#ifdef __STDC__ - double fd_lgamma(double x) -#else - double fd_lgamma(x) - double x; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_lgamma_r(x,&signgam); -#else - double y; - y = __ieee754_lgamma_r(x,&signgam); - if(_LIB_VERSION == _IEEE_) return y; - if(!fd_finite(y)&&fd_finite(x)) { - int err; - if(fd_floor(x)==x&&x<=0.0) - return __kernel_standard(x,x,15,&err); /* lgamma pole */ - else - return __kernel_standard(x,x,14,&err); /* lgamma overflow */ - } else - return y; -#endif -} diff --git a/js/src/fdlibm/w_lgamma_r.c b/js/src/fdlibm/w_lgamma_r.c deleted file mode 100644 index ba2ad5933d5e..000000000000 --- a/js/src/fdlibm/w_lgamma_r.c +++ /dev/null @@ -1,81 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)w_lgamma_r.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * wrapper double lgamma_r(double x, int *signgamp) - */ - -#include "fdlibm.h" - - -#ifdef __STDC__ - double fd_lgamma_r(double x, int *signgamp) /* wrapper lgamma_r */ -#else - double fd_lgamma_r(x,signgamp) /* wrapper lgamma_r */ - double x; int *signgamp; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_lgamma_r(x,signgamp); -#else - double y; - y = __ieee754_lgamma_r(x,signgamp); - if(_LIB_VERSION == _IEEE_) return y; - if(!fd_finite(y)&&fd_finite(x)) { - int err; - if(fd_floor(x)==x&&x<=0.0) - return __kernel_standard(x,x,15,&err); /* lgamma pole */ - else - return __kernel_standard(x,x,14,&err); /* lgamma overflow */ - } else - return y; -#endif -} diff --git a/js/src/fdlibm/w_log.c b/js/src/fdlibm/w_log.c deleted file mode 100644 index 7e358fcf117a..000000000000 --- a/js/src/fdlibm/w_log.c +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)w_log.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * wrapper log(x) - */ - -#include "fdlibm.h" - - -#ifdef __STDC__ - double fd_log(double x) /* wrapper log */ -#else - double fd_log(x) /* wrapper log */ - double x; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_log(x); -#else - double z; - int err; - z = __ieee754_log(x); - if(_LIB_VERSION == _IEEE_ || fd_isnan(x) || x > 0.0) return z; - if(x==0.0) - return __kernel_standard(x,x,16,&err); /* log(0) */ - else - return __kernel_standard(x,x,17,&err); /* log(x<0) */ -#endif -} diff --git a/js/src/fdlibm/w_log10.c b/js/src/fdlibm/w_log10.c deleted file mode 100644 index 6b298b236f62..000000000000 --- a/js/src/fdlibm/w_log10.c +++ /dev/null @@ -1,81 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)w_log10.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * wrapper log10(X) - */ - -#include "fdlibm.h" - - -#ifdef __STDC__ - double fd_log10(double x) /* wrapper log10 */ -#else - double fd_log10(x) /* wrapper log10 */ - double x; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_log10(x); -#else - double z; - z = __ieee754_log10(x); - if(_LIB_VERSION == _IEEE_ || fd_isnan(x)) return z; - if(x<=0.0) { - int err; - if(x==0.0) - return __kernel_standard(x,x,18,&err); /* log10(0) */ - else - return __kernel_standard(x,x,19,&err); /* log10(x<0) */ - } else - return z; -#endif -} diff --git a/js/src/fdlibm/w_pow.c b/js/src/fdlibm/w_pow.c deleted file mode 100644 index 3d2c15ad305f..000000000000 --- a/js/src/fdlibm/w_pow.c +++ /dev/null @@ -1,99 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - - -/* @(#)w_pow.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * wrapper pow(x,y) return x**y - */ - -#include "fdlibm.h" - - -#ifdef __STDC__ - double fd_pow(double x, double y) /* wrapper pow */ -#else - double fd_pow(x,y) /* wrapper pow */ - double x,y; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_pow(x,y); -#else - double z; - int err; - z=__ieee754_pow(x,y); - if(_LIB_VERSION == _IEEE_|| fd_isnan(y)) return z; - if(fd_isnan(x)) { - if(y==0.0) - return __kernel_standard(x,y,42,&err); /* pow(NaN,0.0) */ - else - return z; - } - if(x==0.0){ - if(y==0.0) - return __kernel_standard(x,y,20,&err); /* pow(0.0,0.0) */ - if(fd_finite(y)&&y<0.0) - return __kernel_standard(x,y,23,&err); /* pow(0.0,negative) */ - return z; - } - if(!fd_finite(z)) { - if(fd_finite(x)&&fd_finite(y)) { - if(fd_isnan(z)) - return __kernel_standard(x,y,24,&err); /* pow neg**non-int */ - else - return __kernel_standard(x,y,21,&err); /* pow overflow */ - } - } - if(z==0.0&&fd_finite(x)&&fd_finite(y)) - return __kernel_standard(x,y,22,&err); /* pow underflow */ - return z; -#endif -} diff --git a/js/src/fdlibm/w_remainder.c b/js/src/fdlibm/w_remainder.c deleted file mode 100644 index 25d1ba171fa2..000000000000 --- a/js/src/fdlibm/w_remainder.c +++ /dev/null @@ -1,77 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)w_remainder.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * wrapper remainder(x,p) - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - double fd_remainder(double x, double y) /* wrapper remainder */ -#else - double fd_remainder(x,y) /* wrapper remainder */ - double x,y; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_remainder(x,y); -#else - double z; - z = __ieee754_remainder(x,y); - if(_LIB_VERSION == _IEEE_ || fd_isnan(y)) return z; - if(y==0.0) { - int err; - return __kernel_standard(x,y,28,&err); /* remainder(x,0) */ - } else - return z; -#endif -} diff --git a/js/src/fdlibm/w_scalb.c b/js/src/fdlibm/w_scalb.c deleted file mode 100644 index 35c16a500145..000000000000 --- a/js/src/fdlibm/w_scalb.c +++ /dev/null @@ -1,95 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)w_scalb.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * wrapper scalb(double x, double fn) is provide for - * passing various standard test suite. One - * should use scalbn() instead. - */ - -#include "fdlibm.h" - -#include - -#ifdef __STDC__ -#ifdef _SCALB_INT - double fd_scalb(double x, int fn) /* wrapper scalb */ -#else - double fd_scalb(double x, double fn) /* wrapper scalb */ -#endif -#else - double fd_scalb(x,fn) /* wrapper scalb */ -#ifdef _SCALB_INT - double x; int fn; -#else - double x,fn; -#endif -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_scalb(x,fn); -#else - double z; - int err; - z = __ieee754_scalb(x,fn); - if(_LIB_VERSION == _IEEE_) return z; - if(!(fd_finite(z)||fd_isnan(z))&&fd_finite(x)) { - return __kernel_standard(x,(double)fn,32,&err); /* scalb overflow */ - } - if(z==0.0&&z!=x) { - return __kernel_standard(x,(double)fn,33,&err); /* scalb underflow */ - } -#ifndef _SCALB_INT - if(!fd_finite(fn)) errno = ERANGE; -#endif - return z; -#endif -} diff --git a/js/src/fdlibm/w_sinh.c b/js/src/fdlibm/w_sinh.c deleted file mode 100644 index 8b04ecb7fe90..000000000000 --- a/js/src/fdlibm/w_sinh.c +++ /dev/null @@ -1,77 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)w_sinh.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * wrapper sinh(x) - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - double fd_sinh(double x) /* wrapper sinh */ -#else - double fd_sinh(x) /* wrapper sinh */ - double x; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_sinh(x); -#else - double z; - z = __ieee754_sinh(x); - if(_LIB_VERSION == _IEEE_) return z; - if(!fd_finite(z)&&fd_finite(x)) { - int err; - return __kernel_standard(x,x,25,&err); /* sinh overflow */ - } else - return z; -#endif -} diff --git a/js/src/fdlibm/w_sqrt.c b/js/src/fdlibm/w_sqrt.c deleted file mode 100644 index 462d776f8ef6..000000000000 --- a/js/src/fdlibm/w_sqrt.c +++ /dev/null @@ -1,77 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Sun Microsystems, Inc. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* @(#)w_sqrt.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * wrapper sqrt(x) - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - double fd_sqrt(double x) /* wrapper sqrt */ -#else - double fd_sqrt(x) /* wrapper sqrt */ - double x; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_sqrt(x); -#else - double z; - z = __ieee754_sqrt(x); - if(_LIB_VERSION == _IEEE_ || fd_isnan(x)) return z; - if(x<0.0) { - int err; - return __kernel_standard(x,x,26,&err); /* sqrt(negative) */ - } else - return z; -#endif -} diff --git a/js/src/jslibmath.h b/js/src/jslibmath.h index d653e2e865fa..007efd9fe7f9 100644 --- a/js/src/jslibmath.h +++ b/js/src/jslibmath.h @@ -38,32 +38,12 @@ * * ***** END LICENSE BLOCK ***** */ -/* - * 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 #include "jsconfig.h" -/* - * Define on which platforms to use fdlibm. Not used by default under - * assumption that native math library works unless proved guilty. - * Plus there can be problems with endian-ness and such in fdlibm itself. - * - * fdlibm compatibility notes: - * - fdlibm broken on OSF1/alpha - */ - -#ifndef JS_USE_FDLIBM_MATH -#define JS_USE_FDLIBM_MATH 0 -#endif - -#if !JS_USE_FDLIBM_MATH - /* * Use system provided math routines. */ @@ -102,165 +82,5 @@ extern double js_copysign(double, double); #define fd_sqrt sqrt #define fd_tan tan -#else - -/* - * Use math routines in fdlibm. - */ - -#undef __P -#ifdef __STDC__ -#define __P(p) p -#else -#define __P(p) () -#endif - -#if defined _WIN32 && !defined WINCE - -#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)); -extern double fd_pow __P((double, double)); - -#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(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 */ diff --git a/js/src/jsmath.cpp b/js/src/jsmath.cpp index 0889435a541e..0ac4d36bc45f 100644 --- a/js/src/jsmath.cpp +++ b/js/src/jsmath.cpp @@ -171,7 +171,7 @@ math_atan2(JSContext *cx, uintN argc, jsval *vp) y = js_ValueToNumber(cx, &vp[3]); if (JSVAL_IS_NULL(vp[3])) return JS_FALSE; -#if !JS_USE_FDLIBM_MATH && defined(_MSC_VER) +#if defined(_MSC_VER) /* * MSVC's atan2 does not yield the result demanded by ECMA when both x * and y are infinite. @@ -348,7 +348,6 @@ math_pow(JSContext *cx, uintN argc, jsval *vp) y = js_ValueToNumber(cx, &vp[3]); if (JSVAL_IS_NULL(vp[3])) return JS_FALSE; -#if !JS_USE_FDLIBM_MATH /* * Because C99 and ECMA specify different behavior for pow(), * we need to wrap the libm call to make it ECMA compliant. @@ -362,7 +361,6 @@ math_pow(JSContext *cx, uintN argc, jsval *vp) *vp = JSVAL_ONE; return JS_TRUE; } -#endif z = fd_pow(x, y); return js_NewNumberInRootedValue(cx, z, vp); } diff --git a/toolkit/toolkit-makefiles.sh b/toolkit/toolkit-makefiles.sh index 7b4c0aa999c2..53c21c0e7c48 100644 --- a/toolkit/toolkit-makefiles.sh +++ b/toolkit/toolkit-makefiles.sh @@ -161,7 +161,6 @@ MAKEFILES_intl=" MAKEFILES_js=" js/src/Makefile - js/src/fdlibm/Makefile " MAKEFILES_liveconnect=" From 1d4c11297ce9de82fb716253966185f0d6495780 Mon Sep 17 00:00:00 2001 From: Mats Palmgren Date: Fri, 20 Jun 2008 04:47:59 +0200 Subject: [PATCH 26/66] Use async Invalidate() to avoid crashing. b=435422 r+sr=roc --- layout/generic/nsObjectFrame.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/layout/generic/nsObjectFrame.cpp b/layout/generic/nsObjectFrame.cpp index d3f8b8a2d235..d70e2df879b0 100644 --- a/layout/generic/nsObjectFrame.cpp +++ b/layout/generic/nsObjectFrame.cpp @@ -3204,7 +3204,7 @@ nsresult nsPluginInstanceOwner::ScrollPositionDidChange(nsIScrollableView* aScro // FIXME - Only invalidate the newly revealed amount. // XXX necessary? if (mWidget) - mWidget->Invalidate(PR_TRUE); + mWidget->Invalidate(PR_FALSE); } #endif From 94ab6364191b294de50b9a4bb2f25556b65140a4 Mon Sep 17 00:00:00 2001 From: Mats Palmgren Date: Fri, 20 Jun 2008 06:07:37 +0200 Subject: [PATCH 27/66] Protect against div-by-zero when mRowHeight is zero. b=431738 r+sr=roc --- layout/xul/base/src/nsListBoxBodyFrame.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/layout/xul/base/src/nsListBoxBodyFrame.cpp b/layout/xul/base/src/nsListBoxBodyFrame.cpp index b8216797a21e..531f5237b850 100644 --- a/layout/xul/base/src/nsListBoxBodyFrame.cpp +++ b/layout/xul/base/src/nsListBoxBodyFrame.cpp @@ -397,7 +397,7 @@ nsListBoxBodyFrame::GetPrefSize(nsBoxLayoutState& aBoxLayoutState) NS_IMETHODIMP nsListBoxBodyFrame::PositionChanged(nsISupports* aScrollbar, PRInt32 aOldIndex, PRInt32& aNewIndex) { - if (mScrolling) + if (mScrolling || mRowHeight == 0) return NS_OK; nscoord oldTwipIndex, newTwipIndex; @@ -449,6 +449,9 @@ nsListBoxBodyFrame::PositionChanged(nsISupports* aScrollbar, PRInt32 aOldIndex, NS_IMETHODIMP nsListBoxBodyFrame::VisibilityChanged(nsISupports* aScrollbar, PRBool aVisible) { + if (mRowHeight == 0) + return NS_OK; + PRInt32 lastPageTopRow = GetRowCount() - (GetAvailableHeight() / mRowHeight); if (lastPageTopRow < 0) lastPageTopRow = 0; From 2b1bc4f9bd533ee473c8e0b770c8ebba9ac82b3e Mon Sep 17 00:00:00 2001 From: Mats Palmgren Date: Fri, 20 Jun 2008 06:09:51 +0200 Subject: [PATCH 28/66] Crash test for bug 431738 by Jesse Ruderman. --- layout/xul/base/src/crashtests/431738.xhtml | 7 +++++++ layout/xul/base/src/crashtests/crashtests.list | 1 + 2 files changed, 8 insertions(+) create mode 100644 layout/xul/base/src/crashtests/431738.xhtml diff --git a/layout/xul/base/src/crashtests/431738.xhtml b/layout/xul/base/src/crashtests/431738.xhtml new file mode 100644 index 000000000000..9ce917a3fb31 --- /dev/null +++ b/layout/xul/base/src/crashtests/431738.xhtml @@ -0,0 +1,7 @@ + + +
+ +
+ + diff --git a/layout/xul/base/src/crashtests/crashtests.list b/layout/xul/base/src/crashtests/crashtests.list index 485e72185319..982fa3fd04e4 100644 --- a/layout/xul/base/src/crashtests/crashtests.list +++ b/layout/xul/base/src/crashtests/crashtests.list @@ -24,3 +24,4 @@ load 398326-1.xhtml load 402912-1.xhtml load 408904-1.xul load 412479-1.xhtml +load 431738.xhtml From bd4639345bdd1a15771ab5d48bea26e39060432f Mon Sep 17 00:00:00 2001 From: Mats Palmgren Date: Fri, 20 Jun 2008 06:39:56 +0200 Subject: [PATCH 29/66] Take left border+padding into account when calculating distance from block edge for TAB. b=430926 r+sr=roc --- layout/generic/nsLineLayout.h | 9 +++++++-- layout/generic/nsTextFrameThebes.cpp | 4 +++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/layout/generic/nsLineLayout.h b/layout/generic/nsLineLayout.h index c4c6fdb97d59..193e1bcadf70 100644 --- a/layout/generic/nsLineLayout.h +++ b/layout/generic/nsLineLayout.h @@ -348,9 +348,14 @@ public: } /** - * Return the horizontal offset of the current reflowed-frame from the - * edge of the line container. This is always positive, measured from + * Returns the accumulated advance width of frames before the current frame + * on the line, plus the line container's left border+padding. + * This is always positive, the advance width is measured from * the right edge for RTL blocks and from the left edge for LTR blocks. + * In other words, the current frame's distance from the line container's + * start content edge is: + * GetCurrentFrameXDistanceFromBlock() - lineContainer->GetUsedBorderAndPadding().left + * Note the use of .left for both LTR and RTL line containers. */ nscoord GetCurrentFrameXDistanceFromBlock(); diff --git a/layout/generic/nsTextFrameThebes.cpp b/layout/generic/nsTextFrameThebes.cpp index 98b3b920532d..6281deec6d39 100644 --- a/layout/generic/nsTextFrameThebes.cpp +++ b/layout/generic/nsTextFrameThebes.cpp @@ -5531,7 +5531,9 @@ nsTextFrame::Reflow(nsPresContext* aPresContext, iter.SetOriginalOffset(offset); nscoord xOffsetForTabs = (mTextRun->GetFlags() & nsTextFrameUtils::TEXT_HAS_TAB) ? - lineLayout.GetCurrentFrameXDistanceFromBlock() : -1; + (lineLayout.GetCurrentFrameXDistanceFromBlock() - + lineContainer->GetUsedBorderAndPadding().left) + : -1; PropertyProvider provider(mTextRun, textStyle, frag, this, iter, length, lineContainer, xOffsetForTabs); From 196b377fae399a767cd56f2df81ff8a92c87a553 Mon Sep 17 00:00:00 2001 From: Alexander Surkov Date: Fri, 20 Jun 2008 13:50:27 +0800 Subject: [PATCH 30/66] =?UTF-8?q?Bug=20438782=20=E2=80=93=20Links=20should?= =?UTF-8?q?=20not=20unconditionally=20receive=20an=20accessible=20action?= =?UTF-8?q?=20of=20jump,=20r=3DMarcoZ?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- accessible/src/html/nsHTMLLinkAccessible.cpp | 29 ++++++++++++++++++- accessible/src/html/nsHTMLLinkAccessible.h | 5 ++++ .../test_nsIAccessibleHyperLink.html | 24 ++++++++++++++- 3 files changed, 56 insertions(+), 2 deletions(-) diff --git a/accessible/src/html/nsHTMLLinkAccessible.cpp b/accessible/src/html/nsHTMLLinkAccessible.cpp index 44652b8aa1db..9b340efe1438 100644 --- a/accessible/src/html/nsHTMLLinkAccessible.cpp +++ b/accessible/src/html/nsHTMLLinkAccessible.cpp @@ -143,6 +143,9 @@ nsHTMLLinkAccessible::GetNumActions(PRUint8 *aNumActions) { NS_ENSURE_ARG_POINTER(aNumActions); + if (!IsLinked()) + return nsHyperTextAccessible::GetNumActions(aNumActions); + *aNumActions = 1; return NS_OK; } @@ -150,8 +153,12 @@ nsHTMLLinkAccessible::GetNumActions(PRUint8 *aNumActions) NS_IMETHODIMP nsHTMLLinkAccessible::GetActionName(PRUint8 aIndex, nsAString& aName) { - // Action 0 (default action): Jump to link aName.Truncate(); + + if (!IsLinked()) + return nsHyperTextAccessible::GetActionName(aIndex, aName); + + // Action 0 (default action): Jump to link if (aIndex != eAction_Jump) return NS_ERROR_INVALID_ARG; @@ -162,6 +169,9 @@ nsHTMLLinkAccessible::GetActionName(PRUint8 aIndex, nsAString& aName) NS_IMETHODIMP nsHTMLLinkAccessible::DoAction(PRUint8 aIndex) { + if (!IsLinked()) + return nsHyperTextAccessible::DoAction(aIndex); + // Action 0 (default action): Jump to link if (aIndex != eAction_Jump) return NS_ERROR_INVALID_ARG; @@ -190,3 +200,20 @@ nsHTMLLinkAccessible::GetURI(PRInt32 aIndex, nsIURI **aURI) return link->GetHrefURI(aURI); } + +//////////////////////////////////////////////////////////////////////////////// +// Protected members + +PRBool +nsHTMLLinkAccessible::IsLinked() +{ + nsCOMPtr link(do_QueryInterface(mDOMNode)); + if (!link) + return PR_FALSE; + + nsLinkState linkState; + nsresult rv = link->GetLinkState(linkState); + + return NS_SUCCEEDED(rv) && linkState != eLinkState_NotLink && + linkState != eLinkState_Unknown; +} diff --git a/accessible/src/html/nsHTMLLinkAccessible.h b/accessible/src/html/nsHTMLLinkAccessible.h index 9aeec3c16a30..a9adeac02e3e 100644 --- a/accessible/src/html/nsHTMLLinkAccessible.h +++ b/accessible/src/html/nsHTMLLinkAccessible.h @@ -64,6 +64,11 @@ public: protected: enum { eAction_Jump = 0 }; + + /** + * Returns true if the link has href attribute. + */ + PRBool IsLinked(); }; #endif diff --git a/accessible/tests/mochitest/test_nsIAccessibleHyperLink.html b/accessible/tests/mochitest/test_nsIAccessibleHyperLink.html index 82176d2c6c98..c0f2ef876e92 100644 --- a/accessible/tests/mochitest/test_nsIAccessibleHyperLink.html +++ b/accessible/tests/mochitest/test_nsIAccessibleHyperLink.html @@ -61,7 +61,23 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=418368 is(state.value & aAbsentState, 0, "state bits should not be present in ID " + aID + "!"); } - + + function testAction(aId, aAcc, aActionName) + { + var numActions = aActionName ? 1 : 0; + is(aAcc.numActions, numActions, + "Wrong actions number for ID " + aId); + try { + is(aAcc.getActionName(0), aActionName, + "Wrong action name for ID " + aId); + } catch (e) { + if (numActions) + ok(false, "Exception on action name getting for ID " + aId); + else + ok(true, "Correct action name for ID " + aId); + } + } + function doTest() { // Mapping needed state flags for easier handling. @@ -131,6 +147,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=418368 testStates("AriaHyperlink", ariaHyperlinkAcc, (state_focusable | state_focused | state_linked), (ext_state_horizontal), (0)); + testAction("AriaHyperlink", ariaHyperlinkAcc, "click"); ////////////////////////////////////////////////////////////////////////// // ARIA hyperlink with status invalid @@ -227,6 +244,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=418368 testStates("emptyLink", EmptyHLAcc, (state_focusable | state_linked), (ext_state_horizontal), (0)); + testAction("emptyLink", EmptyHLAcc, "jump"); ////////////////////////////////////////////////////////////////////////// // normal hyperlink with embedded span @@ -251,6 +269,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=418368 testStates("LinkWithSpan", hyperlinkWithSpanAcc, (state_focusable | state_focused | state_linked), (ext_state_horizontal), (0)); + testAction("LinkWithSpan", hyperlinkWithSpanAcc, "jump"); ////////////////////////////////////////////////////////////////////////// // Named anchor, should never have state_linked @@ -268,6 +287,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=418368 testStates("namedAnchor", namedAnchorAcc, (state_selectable), (ext_state_horizontal), (state_focusable | state_linked)); + testAction("namedAnchor", namedAnchorAcc, ""); ////////////////////////////////////////////////////////////////////////// // No link (hasn't any attribute), should never have state_linked @@ -285,6 +305,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=418368 testStates("noLink", noLinkAcc, 0, (ext_state_horizontal), (state_focusable | state_linked)); + testAction("noLink", noLinkAcc, ""); ////////////////////////////////////////////////////////////////////////// // Link with registered 'click' event, should have state_linked @@ -302,6 +323,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=418368 testStates("linkWithClick", linkWithClickAcc, (state_linked), (ext_state_horizontal), 0); + testAction("linkWithClick", linkWithClickAcc, "click"); ////////////////////////////////////////////////////////////////////////// // Maps to group links (bug 431615). From 388d7768f6c8e81770de1f17eb8b6e021e8b6760 Mon Sep 17 00:00:00 2001 From: Igor Bukanov Date: Fri, 20 Jun 2008 09:36:56 +0200 Subject: [PATCH 31/66] [Bug 433382] More efficient interpreter switch when computed goto is not available. r=brendan --- js/src/Makefile.in | 17 +- js/src/Makefile.ref | 34 +-- js/src/jsdbgapi.cpp | 2 + js/src/jsemit.cpp | 2 + js/src/jsinterp.cpp | 416 ++++++++++++++------------ js/src/jsinterp.h | 7 + js/src/jsobj.cpp | 2 + js/src/jsopcode.cpp | 26 +- js/src/jsopcode.h | 8 - js/src/jsopcode.tbl | 6 +- js/src/jsxdrapi.h | 2 +- js/src/liveconnect/nsCLiveconnect.cpp | 4 +- js/src/rules.mk | 2 - 13 files changed, 281 insertions(+), 247 deletions(-) diff --git a/js/src/Makefile.in b/js/src/Makefile.in index d0d0e922fe7a..1d9af756377d 100644 --- a/js/src/Makefile.in +++ b/js/src/Makefile.in @@ -242,6 +242,10 @@ JSJAVA_CFLAGS = \ HOST_SIMPLE_PROGRAMS += host_jskwgen$(HOST_BIN_SUFFIX) GARBAGE += jsautokw.h host_jskwgen$(HOST_BIN_SUFFIX) + +HOST_SIMPLE_PROGRAMS += host_jsoplengen$(HOST_BIN_SUFFIX) +GARBAGE += jsautooplen.h host_jsoplengen$(HOST_BIN_SUFFIX) + USE_HOST_CXX = 1 ifdef HAVE_DTRACE @@ -445,18 +449,23 @@ jscpucfg$(HOST_BIN_SUFFIX): jscpucfg.cpp Makefile.in endif endif -# Extra dependancies and rules for keyword switch code -jsscan.$(OBJ_SUFFIX): jsautokw.h jskeyword.tbl - +# Extra dependancies and rules for auto-generated headers host_jskwgen.$(OBJ_SUFFIX): jsconfig.h jskeyword.tbl jsautokw.h: host_jskwgen$(HOST_BIN_SUFFIX) ./host_jskwgen$(HOST_BIN_SUFFIX) $@ +host_jsoplengen.$(OBJ_SUFFIX): jsopcode.tbl + +jsautooplen.h: host_jsoplengen$(HOST_BIN_SUFFIX) + ./host_jsoplengen$(HOST_BIN_SUFFIX) $@ + +# Force auto-header generation before compiling any source that may use them +$(CSRCS:%.cpp=%.$(OBJ_SUFFIX)): jsautokw.h jsautooplen.h + ifdef HAVE_DTRACE javascript-trace.h: $(srcdir)/javascript-trace.d dtrace -h -s $(srcdir)/javascript-trace.d -o javascript-trace.h.in sed 's/if _DTRACE_VERSION/ifdef INCLUDE_MOZILLA_DTRACE/' \ javascript-trace.h.in > javascript-trace.h endif - diff --git a/js/src/Makefile.ref b/js/src/Makefile.ref index a6ada0ca6cfa..520e801d71ca 100644 --- a/js/src/Makefile.ref +++ b/js/src/Makefile.ref @@ -277,39 +277,39 @@ nsinstall-target: cd ../../config; $(MAKE) OBJDIR=$(OBJDIR) OBJDIR_NAME=$(OBJDIR) # -# Rules for keyword switch generation +# Automatic header generation # -GARBAGE += $(OBJDIR)/jsautokw.h $(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX) -GARBAGE += $(OBJDIR)/jskwgen.$(OBJ_SUFFIX) +AUTO_HEADERS = $(OBJDIR)/jsautokw.h $(OBJDIR)/jsautooplen.h -$(OBJDIR)/jsscan.$(OBJ_SUFFIX): $(OBJDIR)/jsautokw.h jskeyword.tbl +$(OBJDIR)/jsautokw.h: jskeyword.tbl -$(OBJDIR)/jskwgen.$(OBJ_SUFFIX): jskwgen.cpp jskeyword.tbl +$(OBJDIR)/jsautooplen.h: jsopcode.tbl -$(OBJDIR)/jsautokw.h: $(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX) jskeyword.tbl - $(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX) $@ +GARBAGE += $(AUTO_HEADERS) +GARBAGE += $(AUTO_HEADERS:$(OBJDIR)/jsauto%.h=$(OBJDIR)/js%gen$(HOST_BIN_SUFFIX)) ifdef USE_MSVC -$(OBJDIR)/jskwgen.obj: jskwgen.cpp jskeyword.tbl +GARBAGE += $(AUTO_HEADERS:$(OBJDIR)/jsauto%.h=$(OBJDIR)/js%gen.obj) + +$(AUTO_HEADERS): $(OBJDIR)/jsauto%.h: js%gen.cpp @$(MAKE_OBJDIR) $(CXX) -Fo$(OBJDIR)/ -c $(CFLAGS) $< - -$(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX): $(OBJDIR)/jskwgen.$(OBJ_SUFFIX) - link.exe -out:"$@" $(EXE_LINK_FLAGS) $^ - + link.exe -out:"$(OBJDIR)/js$*gen$(HOST_BIN_SUFFIX)" $(EXE_LINK_FLAGS) $(OBJDIR)/js$*gen.obj + $(OBJDIR)/js$*gen$(HOST_BIN_SUFFIX) $@ else -$(OBJDIR)/jskwgen.o: jskwgen.cpp jskeyword.tbl +$(AUTO_HEADERS): $(OBJDIR)/jsauto%.h: js%gen.cpp @$(MAKE_OBJDIR) - $(CXX) -o $@ -c $(CFLAGS) $< - -$(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX): $(OBJDIR)/jskwgen.$(OBJ_SUFFIX) - $(CXX) -o $@ $(CFLAGS) $(LDFLAGS) $^ + $(CXX) -o $(OBJDIR)/js$*gen$(HOST_BIN_SUFFIX) $(CFLAGS) $(LDFLAGS) $< + $(OBJDIR)/js$*gen$(HOST_BIN_SUFFIX) $@ endif +# force creation of autoheaders before compiling any source that may use them +$(LIB_OBJS) : $(AUTO_HEADERS) + # # JS shell executable # diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index 311d7cc06edd..7309ebbabf53 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -62,6 +62,8 @@ #include "jsscript.h" #include "jsstr.h" +#include "jsautooplen.h" + typedef struct JSTrap { JSCList links; JSScript *script; diff --git a/js/src/jsemit.cpp b/js/src/jsemit.cpp index daff25c9e53a..638ade9eef55 100644 --- a/js/src/jsemit.cpp +++ b/js/src/jsemit.cpp @@ -66,6 +66,8 @@ #include "jsscope.h" #include "jsscript.h" +#include "jsautooplen.h" + /* Allocation chunk counts, must be powers of two in general. */ #define BYTECODE_CHUNK 256 /* code allocation increment */ #define SRCNOTE_CHUNK 64 /* initial srcnote allocation increment */ diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 3c58cabee4b7..9bc14c21e7af 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -77,6 +77,8 @@ #include "jsxml.h" #endif +#include "jsautooplen.h" + #ifdef js_invoke_c__ uint32 @@ -2074,6 +2076,77 @@ js_DoIncDec(JSContext *cx, const JSCodeSpec *cs, jsval *vp, jsval *vp2) return JS_TRUE; } +#ifdef DEBUG + +void +js_TraceOpcode(JSContext *cx, jsint len) +{ + FILE *tracefp; + JSStackFrame *fp; + JSFrameRegs *regs; + JSOp prevop; + intN ndefs, n, nuses; + jsval *siter; + JSString *str; + JSOp op; + + tracefp = (FILE *) cx->tracefp; + JS_ASSERT(tracefp); + fp = cx->fp; + regs = fp->regs; + if (len != 0) { + prevop = (JSOp) regs->pc[-len]; + ndefs = js_CodeSpec[prevop].ndefs; + if (ndefs != 0) { + if (prevop == JSOP_FORELEM && regs->sp[-1] == JSVAL_FALSE) + --ndefs; + for (n = -ndefs; n < 0; n++) { + char *bytes = js_DecompileValueGenerator(cx, n, regs->sp[n], + NULL); + if (bytes) { + fprintf(tracefp, "%s %s", + (n == -ndefs) ? " output:" : ",", + bytes); + JS_free(cx, bytes); + } + } + fprintf(tracefp, " @ %d\n", regs->sp - fp->spbase); + } + fprintf(tracefp, " stack: "); + for (siter = fp->spbase; siter < regs->sp; siter++) { + str = js_ValueToString(cx, *siter); + if (!str) + fputs("", tracefp); + else + js_FileEscapedString(tracefp, str, 0); + fputc(' ', tracefp); + } + fputc('\n', tracefp); + } + + fprintf(tracefp, "%4u: ", js_PCToLineNumber(cx, fp->script, regs->pc)); + js_Disassemble1(cx, fp->script, regs->pc, + PTRDIFF(regs->pc, fp->script->code, jsbytecode), + JS_FALSE, tracefp); + op = (JSOp) *regs->pc; + nuses = js_CodeSpec[op].nuses; + if (nuses != 0) { + for (n = -nuses; n < 0; n++) { + char *bytes = js_DecompileValueGenerator(cx, n, regs->sp[n], + NULL); + if (bytes) { + fprintf(tracefp, "%s %s", + (n == -nuses) ? " inputs:" : ",", + bytes); + JS_free(cx, bytes); + } + } + fprintf(tracefp, " @ %d\n", regs->sp - fp->spbase); + } +} + +#endif /* DEBUG */ + #ifdef JS_OPMETER # include @@ -2425,6 +2498,13 @@ JS_STATIC_ASSERT(!CAN_DO_FAST_INC_DEC(INT_TO_JSVAL(JSVAL_INT_MAX))); # endif #endif + +/* + * Interpreter assumes the following to implement condition-free interrupt + * implementation when !JS_THREADED_INTERP. + */ +JS_STATIC_ASSERT(JSOP_INTERRUPT == 0); + /* * Ensure that the intrepreter switch can close call-bytecode cases in the * same way as non-call bytecodes. @@ -2462,7 +2542,6 @@ js_Interpret(JSContext *cx) JSFrameRegs regs; JSObject *obj, *obj2, *parent; JSBool ok, cond; - JSTrapHandler interruptHandler; jsint len; jsbytecode *endpc, *pc2; JSOp op, op2; @@ -2481,8 +2560,11 @@ js_Interpret(JSContext *cx) JSClass *clasp; JSFunction *fun; JSType type; -#if !JS_THREADED_INTERP && defined DEBUG - FILE *tracefp = NULL; +#if JS_THREADED_INTERP + register const void * const *jumpTable; +#else + register uint32 switchMask; + uintN switchOp; #endif #if JS_HAS_EXPORT_IMPORT JSIdArray *ida; @@ -2502,42 +2584,68 @@ js_Interpret(JSContext *cx) #endif #if JS_THREADED_INTERP - static void *normalJumpTable[] = { + static const void *const normalJumpTable[] = { # define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \ JS_EXTENSION &&L_##op, # include "jsopcode.tbl" # undef OPDEF }; - static void *interruptJumpTable[] = { + static const void *const interruptJumpTable[] = { # define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \ - JS_EXTENSION &&interrupt, + JS_EXTENSION &&L_JSOP_INTERRUPT, # include "jsopcode.tbl" # undef OPDEF }; - register void **jumpTable = normalJumpTable; - METER_OP_INIT(op); /* to nullify first METER_OP_PAIR */ # define DO_OP() JS_EXTENSION_(goto *jumpTable[op]) -# define DO_NEXT_OP(n) do { METER_OP_PAIR(op, regs.pc[n]); \ - op = (JSOp) *(regs.pc += (n)); \ - DO_OP(); } while (0) +# define DO_NEXT_OP(n) JS_BEGIN_MACRO \ + METER_OP_PAIR(op, regs.pc[n]); \ + op = (JSOp) *(regs.pc += (n)); \ + DO_OP(); \ + JS_END_MACRO + # define BEGIN_CASE(OP) L_##OP: # define END_CASE(OP) DO_NEXT_OP(OP##_LENGTH); # define END_VARLEN_CASE DO_NEXT_OP(len); -# define EMPTY_CASE(OP) BEGIN_CASE(OP) op = (JSOp) *++regs.pc; DO_OP(); -#else +# define ADD_EMPTY_CASE(OP) BEGIN_CASE(OP) \ + JS_ASSERT(js_CodeSpec[OP].length == 1); \ + op = (JSOp) *++regs.pc; \ + DO_OP(); + +# define END_EMPTY_CASES + +#else /* !JS_THREADED_INTERP */ + # define DO_OP() goto do_op -# define DO_NEXT_OP(n) goto advance_pc +# define DO_NEXT_OP(n) JS_BEGIN_MACRO \ + JS_ASSERT((n) == len); \ + goto advance_pc; \ + JS_END_MACRO + # define BEGIN_CASE(OP) case OP: -# define END_CASE(OP) break; -# define END_VARLEN_CASE break; -# define EMPTY_CASE(OP) BEGIN_CASE(OP) END_CASE(OP) +# define END_CASE(OP) END_CASE_LEN(OP##_LENGTH) +# define END_CASE_LEN(n) END_CASE_LENX(n) +# define END_CASE_LENX(n) END_CASE_LEN##n + +/* + * To share the code for all len == 1 cases we use the specialized label with + * code that falls through to advance_pc: . + */ +# define END_CASE_LEN1 goto advance_pc_by_one; +# define END_CASE_LEN2 len = 2; goto advance_pc; +# define END_CASE_LEN3 len = 3; goto advance_pc; +# define END_CASE_LEN4 len = 4; goto advance_pc; +# define END_CASE_LEN5 len = 5; goto advance_pc; +# define END_VARLEN_CASE goto advance_pc; +# define ADD_EMPTY_CASE(OP) BEGIN_CASE(OP) +# define END_EMPTY_CASES goto advance_pc_by_one; + #endif - /* Check for too deep a C stack. */ + /* Check for too deep of a native thread stack. */ JS_CHECK_RECURSION(cx, return JS_FALSE); rt = cx->runtime; @@ -2616,18 +2724,15 @@ js_Interpret(JSContext *cx) * the compiler can keep it in a register when it is non-null. */ #if JS_THREADED_INTERP -# define LOAD_JUMP_TABLE() \ - (jumpTable = interruptHandler ? interruptJumpTable : normalJumpTable) +# define LOAD_INTERRUPT_HANDLER(cx) \ + ((void) (jumpTable = (cx)->debugHooks->interruptHandler \ + ? interruptJumpTable \ + : normalJumpTable)) #else -# define LOAD_JUMP_TABLE() ((void) 0) +# define LOAD_INTERRUPT_HANDLER(cx) \ + ((void) (switchMask = (cx)->debugHooks->interruptHandler ? 0 : 255)) #endif -#define LOAD_INTERRUPT_HANDLER(cx) \ - JS_BEGIN_MACRO \ - interruptHandler = (cx)->debugHooks->interruptHandler; \ - LOAD_JUMP_TABLE(); \ - JS_END_MACRO - LOAD_INTERRUPT_HANDLER(cx); /* @@ -2675,107 +2780,89 @@ js_Interpret(JSContext *cx) } } -#if JS_THREADED_INTERP - /* - * This is a loop, but it does not look like a loop. The loop-closing - * jump is distributed throughout interruptJumpTable, and comes back to - * the interrupt label. The dispatch on op is through normalJumpTable. - * The trick is LOAD_INTERRUPT_HANDLER setting jumpTable appropriately. - * - * It is important that "op" be initialized before the interrupt label - * because it is possible for "op" to be specially assigned during the - * normally processing of an opcode while looping (in particular, this - * happens in JSOP_TRAP while debugging). We rely on DO_NEXT_OP to - * correctly manage "op" in all other cases. + * It is important that "op" be initialized before calling DO_OP because + * it is possible for "op" to be specially assigned during the normal + * processing of an opcode while looping. We rely on DO_NEXT_OP to manage + * "op" correctly in all other cases. */ - op = (JSOp) *regs.pc; - if (interruptHandler) { -interrupt: - switch (interruptHandler(cx, script, regs.pc, &rval, - cx->debugHooks->interruptHandlerData)) { - case JSTRAP_ERROR: - goto error; - case JSTRAP_CONTINUE: - break; - case JSTRAP_RETURN: - fp->rval = rval; - ok = JS_TRUE; - goto forced_return; - case JSTRAP_THROW: - cx->throwing = JS_TRUE; - cx->exception = rval; - goto error; - default:; - } - LOAD_INTERRUPT_HANDLER(cx); - } - - JS_ASSERT((uintN)op < (uintN)JSOP_LIMIT); - JS_EXTENSION_(goto *normalJumpTable[op]); - -#else /* !JS_THREADED_INTERP */ + len = 0; + DO_NEXT_OP(len); +#if JS_THREADED_INTERP + /* + * This is a loop, but it does not look like a loop. The loop-closing + * jump is distributed throughout goto *jumpTable[op] inside of DO_OP. + * When interrupts are enabled, jumpTable is set to interruptJumpTable + * where all jumps point to the JSOP_INTERRUPT case. The latter, after + * calling the interrupt handler, dispatches through normalJumpTable to + * continue the normal bytecode processing. + */ +#else for (;;) { + advance_pc_by_one: + JS_ASSERT(js_CodeSpec[op].length == 1); + len = 1; + advance_pc: + regs.pc += len; op = (JSOp) *regs.pc; - do_op: - len = js_CodeSpec[op].length; - #ifdef DEBUG - tracefp = (FILE *) cx->tracefp; - if (tracefp) { - intN nuses, n; - - fprintf(tracefp, "%4u: ", js_PCToLineNumber(cx, script, regs.pc)); - js_Disassemble1(cx, script, regs.pc, - PTRDIFF(regs.pc, script->code, jsbytecode), - JS_FALSE, tracefp); - nuses = js_CodeSpec[op].nuses; - if (nuses) { - for (n = -nuses; n < 0; n++) { - char *bytes = js_DecompileValueGenerator(cx, n, regs.sp[n], - NULL); - if (bytes) { - fprintf(tracefp, "%s %s", - (n == -nuses) ? " inputs:" : ",", - bytes); - JS_free(cx, bytes); - } - } - fprintf(tracefp, " @ %d\n", regs.sp - fp->spbase); - } - } -#endif /* DEBUG */ - - if (interruptHandler) { - switch (interruptHandler(cx, script, regs.pc, &rval, - cx->debugHooks->interruptHandlerData)) { - case JSTRAP_ERROR: - goto error; - case JSTRAP_CONTINUE: - break; - case JSTRAP_RETURN: - fp->rval = rval; - ok = JS_TRUE; - goto forced_return; - case JSTRAP_THROW: - cx->throwing = JS_TRUE; - cx->exception = rval; - goto error; - default:; - } - LOAD_INTERRUPT_HANDLER(cx); - } - - switch (op) { + if (cx->tracefp) + js_TraceOpcode(cx, len); +#endif + do_op: + switchOp = op & switchMask; + do_switch: + switch (switchOp) { #endif /* !JS_THREADED_INTERP */ - EMPTY_CASE(JSOP_NOP) + BEGIN_CASE(JSOP_INTERRUPT) + { + JSTrapHandler handler; - EMPTY_CASE(JSOP_GROUP) + handler = cx->debugHooks->interruptHandler; + if (handler) { + switch (handler(cx, script, regs.pc, &rval, + cx->debugHooks->interruptHandlerData)) { + case JSTRAP_ERROR: + goto error; + case JSTRAP_CONTINUE: + break; + case JSTRAP_RETURN: + fp->rval = rval; + ok = JS_TRUE; + goto forced_return; + case JSTRAP_THROW: + cx->throwing = JS_TRUE; + cx->exception = rval; + goto error; + default:; + } + } + LOAD_INTERRUPT_HANDLER(cx); - /* EMPTY_CASE is not used here as JSOP_LINENO_LENGTH == 3. */ +#if JS_THREADED_INTERP + JS_EXTENSION_(goto *normalJumpTable[op]); +#else + switchOp = op; + goto do_switch; +#endif + } + + /* No-ops for ease of decompilation. */ + ADD_EMPTY_CASE(JSOP_NOP) + ADD_EMPTY_CASE(JSOP_GROUP) + ADD_EMPTY_CASE(JSOP_CONDSWITCH) + ADD_EMPTY_CASE(JSOP_TRY) + ADD_EMPTY_CASE(JSOP_FINALLY) +#if JS_HAS_XML_SUPPORT + ADD_EMPTY_CASE(JSOP_STARTXML) + ADD_EMPTY_CASE(JSOP_STARTXMLEXPR) +#endif + END_EMPTY_CASES + + /* ADD_EMPTY_CASE is not used here as JSOP_LINENO_LENGTH == 3. */ BEGIN_CASE(JSOP_LINENO) END_CASE(JSOP_LINENO) @@ -2810,12 +2897,6 @@ interrupt: #endif END_CASE(JSOP_POPN) - BEGIN_CASE(JSOP_SWAP) - rtmp = regs.sp[-1]; - regs.sp[-1] = regs.sp[-2]; - regs.sp[-2] = rtmp; - END_CASE(JSOP_SWAP) - BEGIN_CASE(JSOP_SETRVAL) BEGIN_CASE(JSOP_POPV) ASSERT_NOT_THROWING(cx); @@ -4139,7 +4220,6 @@ interrupt: i = 0; COMPUTE_THIS(cx, fp, obj); PUSH(JSVAL_NULL); - len = JSOP_GETTHISPROP_LENGTH; goto do_getprop_with_obj; #undef COMPUTE_THIS @@ -4149,7 +4229,6 @@ interrupt: slot = GET_ARGNO(regs.pc); JS_ASSERT(slot < fp->fun->nargs); PUSH_OPND(fp->argv[slot]); - len = JSOP_GETARGPROP_LENGTH; goto do_getprop_body; BEGIN_CASE(JSOP_GETVARPROP) @@ -4157,7 +4236,6 @@ interrupt: slot = GET_VARNO(regs.pc); JS_ASSERT(slot < fp->fun->u.i.nvars); PUSH_OPND(fp->vars[slot]); - len = JSOP_GETVARPROP_LENGTH; goto do_getprop_body; BEGIN_CASE(JSOP_GETLOCALPROP) @@ -4165,13 +4243,11 @@ interrupt: slot = GET_UINT16(regs.pc); JS_ASSERT(slot < script->depth); PUSH_OPND(fp->spbase[slot]); - len = JSOP_GETLOCALPROP_LENGTH; goto do_getprop_body; BEGIN_CASE(JSOP_GETPROP) BEGIN_CASE(JSOP_GETXPROP) i = 0; - len = JSOP_GETPROP_LENGTH; do_getprop_body: lval = FETCH_OPND(-1); @@ -4217,6 +4293,8 @@ interrupt: } while (0); STORE_OPND(-1, rval); + JS_ASSERT(JSOP_GETPROP_LENGTH + i == js_CodeSpec[op].length); + len = JSOP_GETPROP_LENGTH + i; END_VARLEN_CASE BEGIN_CASE(JSOP_LENGTH) @@ -4241,8 +4319,7 @@ interrupt: goto error; } } else { - i = -1; - len = JSOP_LENGTH_LENGTH; + i = -2; goto do_getprop_with_lval; } END_CASE(JSOP_LENGTH) @@ -4996,12 +5073,12 @@ interrupt: goto error; if (!prop) { /* Kludge to allow (typeof foo == "undefined") tests. */ - len = JSOP_NAME_LENGTH; endpc = script->code + script->length; - for (pc2 = regs.pc + len; pc2 < endpc; pc2++) { + for (pc2 = regs.pc + JSOP_NAME_LENGTH; pc2 < endpc; pc2++) { op2 = (JSOp)*pc2; if (op2 == JSOP_TYPEOF) { PUSH_OPND(JSVAL_VOID); + len = JSOP_NAME_LENGTH; DO_NEXT_OP(len); } if (op2 != JSOP_GROUP) @@ -5338,8 +5415,6 @@ interrupt: : GET_JUMPX_OFFSET(pc2); END_VARLEN_CASE - EMPTY_CASE(JSOP_CONDSWITCH) - #if JS_HAS_EXPORT_IMPORT BEGIN_CASE(JSOP_EXPORTALL) obj = fp->varobj; @@ -5414,15 +5489,13 @@ interrupt: #endif /* JS_HAS_EXPORT_IMPORT */ BEGIN_CASE(JSOP_TRAP) - switch (JS_HandleTrap(cx, script, regs.pc, &rval)) { + { + JSTrapStatus status; + + status = JS_HandleTrap(cx, script, regs.pc, &rval); + switch (status) { case JSTRAP_ERROR: goto error; - case JSTRAP_CONTINUE: - JS_ASSERT(JSVAL_IS_INT(rval)); - op = (JSOp) JSVAL_TO_INT(rval); - JS_ASSERT((uintN)op < (uintN)JSOP_LIMIT); - LOAD_INTERRUPT_HANDLER(cx); - DO_OP(); case JSTRAP_RETURN: fp->rval = rval; ok = JS_TRUE; @@ -5432,9 +5505,15 @@ interrupt: cx->exception = rval; goto error; default:; + break; } + JS_ASSERT(status == JSTRAP_CONTINUE); LOAD_INTERRUPT_HANDLER(cx); - END_CASE(JSOP_TRAP) + JS_ASSERT(JSVAL_IS_INT(rval)); + op = (JSOp) JSVAL_TO_INT(rval); + JS_ASSERT((uintN)op < (uintN)JSOP_LIMIT); + DO_OP(); + } BEGIN_CASE(JSOP_ARGUMENTS) if (!js_GetArgsValue(cx, fp, &rval)) @@ -6172,7 +6251,7 @@ interrupt: goto error; } regs.sp -= 2; - END_CASE(JSOP_INITELEM); + END_CASE(JSOP_INITELEM) #if JS_HAS_SHARP_VARS BEGIN_CASE(JSOP_DEFSHARP) @@ -6219,15 +6298,11 @@ interrupt: END_CASE(JSOP_USESHARP) #endif /* JS_HAS_SHARP_VARS */ - /* No-ops for ease of decompilation and jit'ing. */ - EMPTY_CASE(JSOP_TRY) - EMPTY_CASE(JSOP_FINALLY) - BEGIN_CASE(JSOP_GOSUB) PUSH(JSVAL_FALSE); i = PTRDIFF(regs.pc, script->main, jsbytecode) + JSOP_GOSUB_LENGTH; - len = GET_JUMP_OFFSET(regs.pc); PUSH(INT_TO_JSVAL(i)); + len = GET_JUMP_OFFSET(regs.pc); END_VARLEN_CASE BEGIN_CASE(JSOP_GOSUBX) @@ -6482,9 +6557,6 @@ interrupt: regs.sp--; END_CASE(JSOP_ENDFILTER); - EMPTY_CASE(JSOP_STARTXML) - EMPTY_CASE(JSOP_STARTXMLEXPR) - BEGIN_CASE(JSOP_TOXML) rval = FETCH_OPND(-1); obj = js_ValueToXMLObject(cx, rval); @@ -6784,48 +6856,6 @@ interrupt: #if !JS_THREADED_INTERP } /* switch (op) */ - - advance_pc: - regs.pc += len; - -#ifdef DEBUG - if (tracefp) { - intN ndefs, n; - jsval *siter; - - /* - * op may be invalid here when a catch or finally handler jumps to - * advance_pc. - */ - op = (JSOp) regs.pc[-len]; - ndefs = js_CodeSpec[op].ndefs; - if (ndefs) { - if (op == JSOP_FORELEM && regs.sp[-1] == JSVAL_FALSE) - --ndefs; - for (n = -ndefs; n < 0; n++) { - char *bytes = js_DecompileValueGenerator(cx, n, regs.sp[n], - NULL); - if (bytes) { - fprintf(tracefp, "%s %s", - (n == -ndefs) ? " output:" : ",", - bytes); - JS_free(cx, bytes); - } - } - fprintf(tracefp, " @ %d\n", regs.sp - fp->spbase); - } - fprintf(tracefp, " stack: "); - for (siter = fp->spbase; siter < regs.sp; siter++) { - str = js_ValueToString(cx, *siter); - if (!str) - fputs("", tracefp); - else - js_FileEscapedString(tracefp, str, 0); - fputc(' ', tracefp); - } - fputc('\n', tracefp); - } -#endif /* DEBUG */ } #endif /* !JS_THREADED_INTERP */ diff --git a/js/src/jsinterp.h b/js/src/jsinterp.h index 7fb54660a749..3f8bdfe9bba7 100644 --- a/js/src/jsinterp.h +++ b/js/src/jsinterp.h @@ -507,6 +507,13 @@ js_OnUnknownMethod(JSContext *cx, jsval *vp); extern JSBool js_DoIncDec(JSContext *cx, const JSCodeSpec *cs, jsval *vp, jsval *vp2); +/* + * Opcode tracing helper. When len is not 0, cx->fp->regs->pc[-len] gives the + * previous opcode. + */ +extern void +js_TraceOpcode(JSContext *cx, jsint len); + /* * JS_OPMETER helper functions. */ diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index a9540166152c..e8ac435e8daa 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -88,6 +88,8 @@ #include "jsdtracef.h" #endif +#include "jsautooplen.h" + #ifdef JS_THREADSAFE #define NATIVE_DROP_PROPERTY js_DropProperty diff --git a/js/src/jsopcode.cpp b/js/src/jsopcode.cpp index cf0accc147d5..91e0f9e0fa7f 100644 --- a/js/src/jsopcode.cpp +++ b/js/src/jsopcode.cpp @@ -75,6 +75,14 @@ # include "jsnum.h" #endif +#include "jsautooplen.h" + +/* Verify JSOP_XXX_LENGTH constant definitions. */ +#define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \ + JS_STATIC_ASSERT(op##_LENGTH == length); +#include "jsopcode.tbl" +#undef OPDEF + static const char js_incop_strs[][3] = {"++", "--"}; const JSCodeSpec js_CodeSpec[] = { @@ -2152,14 +2160,6 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) todo = -2; break; - case JSOP_SWAP: - /* - * We don't generate this opcode currently, and previously we - * did not need to decompile it. If old, serialized bytecode - * uses it still, we should fall through and set todo = -2. - */ - /* FALL THROUGH */ - case JSOP_GOSUB: case JSOP_GOSUBX: /* @@ -4993,8 +4993,7 @@ DecompileExpression(JSContext *cx, JSScript *script, JSFunction *fun, /* None of these stack-writing ops generates novel values. */ JS_ASSERT(op != JSOP_CASE && op != JSOP_CASEX && - op != JSOP_DUP && op != JSOP_DUP2 && - op != JSOP_SWAP); + op != JSOP_DUP && op != JSOP_DUP2); /* * |this| could convert to a very long object initialiser, so cite it by @@ -5274,13 +5273,6 @@ ReconstructPCStack(JSContext *cx, JSScript *script, jsbytecode *pc, pcstack[pcdepth + 3] = pcstack[pcdepth + 1]; break; - case JSOP_SWAP: - JS_ASSERT(ndefs == 2); - pc2 = pcstack[pcdepth]; - pcstack[pcdepth] = pcstack[pcdepth + 1]; - pcstack[pcdepth + 1] = pc2; - break; - case JSOP_LEAVEBLOCKEXPR: /* * The decompiler wants to see [leaveblockexpr] on pcstack, not diff --git a/js/src/jsopcode.h b/js/src/jsopcode.h index 9e185e4c3b07..831b95fa9401 100644 --- a/js/src/jsopcode.h +++ b/js/src/jsopcode.h @@ -60,14 +60,6 @@ typedef enum JSOp { JSOP_LIMIT } JSOp; -typedef enum JSOpLength { -#define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \ - op##_LENGTH = length, -#include "jsopcode.tbl" -#undef OPDEF - JSOP_LIMIT_LENGTH -} JSOpLength; - /* * JS bytecode formats. */ diff --git a/js/src/jsopcode.tbl b/js/src/jsopcode.tbl index 7806e08e018f..f9ea46a03a5d 100644 --- a/js/src/jsopcode.tbl +++ b/js/src/jsopcode.tbl @@ -97,7 +97,7 @@ /* legend: op val name image len use def prec format */ /* Longstanding JavaScript bytecodes. */ -OPDEF(JSOP_NOP, 0, "nop", NULL, 1, 0, 0, 0, JOF_BYTE) +OPDEF(JSOP_INTERRUPT, 0, "interrupt", 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, 2, JOF_BYTE) OPDEF(JSOP_ENTERWITH, 3, "enterwith", NULL, 1, 1, 1, 0, JOF_BYTE|JOF_PARENHEAD) @@ -331,9 +331,9 @@ OPDEF(JSOP_TRY, 133,"try", NULL, 1, 0, 0, 0, JOF_BYTE) OPDEF(JSOP_FINALLY, 134,"finally", NULL, 1, 0, 0, 0, JOF_BYTE) /* - * Swap the top two stack elements. + * Generic nop for the decompiler. */ -OPDEF(JSOP_SWAP, 135,"swap", NULL, 1, 2, 2, 0, JOF_BYTE) +OPDEF(JSOP_NOP, 135,"nop", NULL, 1, 0, 0, 0, JOF_BYTE) /* * Bytecodes that avoid making an arguments object in most cases: diff --git a/js/src/jsxdrapi.h b/js/src/jsxdrapi.h index 3026b49ee215..68a45432af94 100644 --- a/js/src/jsxdrapi.h +++ b/js/src/jsxdrapi.h @@ -202,7 +202,7 @@ JS_XDRFindClassById(JSXDRState *xdr, uint32 id); * before deserialization of bytecode. If the saved version does not match * the current version, abort deserialization and invalidate the file. */ -#define JSXDR_BYTECODE_VERSION (0xb973c0de - 25) +#define JSXDR_BYTECODE_VERSION (0xb973c0de - 26) /* * Library-private functions. diff --git a/js/src/liveconnect/nsCLiveconnect.cpp b/js/src/liveconnect/nsCLiveconnect.cpp index 4adfc740142b..3c0c344fcfc2 100644 --- a/js/src/liveconnect/nsCLiveconnect.cpp +++ b/js/src/liveconnect/nsCLiveconnect.cpp @@ -192,8 +192,8 @@ AutoPushJSContext::AutoPushJSContext(nsISupports* aSecuritySupports, mFrame.callee = JS_GetFunctionObject(fun); mFrame.scopeChain = JS_GetParent(cx, mFrame.callee); mFrame.down = cx->fp; - mRegs.pc = script->code + script->length - - JSOP_STOP_LENGTH; + mRegs.pc = script->code + script->length - 1; + JS_ASSERT(static_cast(*mRegs.pc) == JSOP_STOP); mRegs.sp = NULL; mFrame.regs = &mRegs; cx->fp = &mFrame; diff --git a/js/src/rules.mk b/js/src/rules.mk index 4ab596f23a69..ad80ad0f449a 100644 --- a/js/src/rules.mk +++ b/js/src/rules.mk @@ -185,11 +185,9 @@ endif clean: rm -rf $(OBJS) $(GARBAGE) - @cd fdlibm; $(MAKE) -f Makefile.ref clean clobber: rm -rf $(OBJS) $(TARGETS) $(DEPENDENCIES) - @cd fdlibm; $(MAKE) -f Makefile.ref clobber tar: tar cvf $(TARNAME) $(TARFILES) From f433beca71746a252f29b5d3c0391ed1b455fc78 Mon Sep 17 00:00:00 2001 From: Igor Bukanov Date: Fri, 20 Jun 2008 09:45:29 +0200 Subject: [PATCH 32/66] Backed out changeset 21527193c49b: the patch has used CSRCS, not CPPSRCS. --- js/src/Makefile.in | 17 +- js/src/Makefile.ref | 34 +-- js/src/jsdbgapi.cpp | 2 - js/src/jsemit.cpp | 2 - js/src/jsinterp.cpp | 410 ++++++++++++-------------- js/src/jsinterp.h | 7 - js/src/jsobj.cpp | 2 - js/src/jsopcode.cpp | 26 +- js/src/jsopcode.h | 8 + js/src/jsopcode.tbl | 6 +- js/src/jsxdrapi.h | 2 +- js/src/liveconnect/nsCLiveconnect.cpp | 4 +- js/src/rules.mk | 2 + 13 files changed, 244 insertions(+), 278 deletions(-) diff --git a/js/src/Makefile.in b/js/src/Makefile.in index 1d9af756377d..d0d0e922fe7a 100644 --- a/js/src/Makefile.in +++ b/js/src/Makefile.in @@ -242,10 +242,6 @@ JSJAVA_CFLAGS = \ HOST_SIMPLE_PROGRAMS += host_jskwgen$(HOST_BIN_SUFFIX) GARBAGE += jsautokw.h host_jskwgen$(HOST_BIN_SUFFIX) - -HOST_SIMPLE_PROGRAMS += host_jsoplengen$(HOST_BIN_SUFFIX) -GARBAGE += jsautooplen.h host_jsoplengen$(HOST_BIN_SUFFIX) - USE_HOST_CXX = 1 ifdef HAVE_DTRACE @@ -449,23 +445,18 @@ jscpucfg$(HOST_BIN_SUFFIX): jscpucfg.cpp Makefile.in endif endif -# Extra dependancies and rules for auto-generated headers +# Extra dependancies and rules for keyword switch code +jsscan.$(OBJ_SUFFIX): jsautokw.h jskeyword.tbl + host_jskwgen.$(OBJ_SUFFIX): jsconfig.h jskeyword.tbl jsautokw.h: host_jskwgen$(HOST_BIN_SUFFIX) ./host_jskwgen$(HOST_BIN_SUFFIX) $@ -host_jsoplengen.$(OBJ_SUFFIX): jsopcode.tbl - -jsautooplen.h: host_jsoplengen$(HOST_BIN_SUFFIX) - ./host_jsoplengen$(HOST_BIN_SUFFIX) $@ - -# Force auto-header generation before compiling any source that may use them -$(CSRCS:%.cpp=%.$(OBJ_SUFFIX)): jsautokw.h jsautooplen.h - ifdef HAVE_DTRACE javascript-trace.h: $(srcdir)/javascript-trace.d dtrace -h -s $(srcdir)/javascript-trace.d -o javascript-trace.h.in sed 's/if _DTRACE_VERSION/ifdef INCLUDE_MOZILLA_DTRACE/' \ javascript-trace.h.in > javascript-trace.h endif + diff --git a/js/src/Makefile.ref b/js/src/Makefile.ref index 520e801d71ca..a6ada0ca6cfa 100644 --- a/js/src/Makefile.ref +++ b/js/src/Makefile.ref @@ -277,39 +277,39 @@ nsinstall-target: cd ../../config; $(MAKE) OBJDIR=$(OBJDIR) OBJDIR_NAME=$(OBJDIR) # -# Automatic header generation +# Rules for keyword switch generation # -AUTO_HEADERS = $(OBJDIR)/jsautokw.h $(OBJDIR)/jsautooplen.h +GARBAGE += $(OBJDIR)/jsautokw.h $(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX) +GARBAGE += $(OBJDIR)/jskwgen.$(OBJ_SUFFIX) -$(OBJDIR)/jsautokw.h: jskeyword.tbl +$(OBJDIR)/jsscan.$(OBJ_SUFFIX): $(OBJDIR)/jsautokw.h jskeyword.tbl -$(OBJDIR)/jsautooplen.h: jsopcode.tbl +$(OBJDIR)/jskwgen.$(OBJ_SUFFIX): jskwgen.cpp jskeyword.tbl -GARBAGE += $(AUTO_HEADERS) -GARBAGE += $(AUTO_HEADERS:$(OBJDIR)/jsauto%.h=$(OBJDIR)/js%gen$(HOST_BIN_SUFFIX)) +$(OBJDIR)/jsautokw.h: $(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX) jskeyword.tbl + $(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX) $@ ifdef USE_MSVC -GARBAGE += $(AUTO_HEADERS:$(OBJDIR)/jsauto%.h=$(OBJDIR)/js%gen.obj) - -$(AUTO_HEADERS): $(OBJDIR)/jsauto%.h: js%gen.cpp +$(OBJDIR)/jskwgen.obj: jskwgen.cpp jskeyword.tbl @$(MAKE_OBJDIR) $(CXX) -Fo$(OBJDIR)/ -c $(CFLAGS) $< - link.exe -out:"$(OBJDIR)/js$*gen$(HOST_BIN_SUFFIX)" $(EXE_LINK_FLAGS) $(OBJDIR)/js$*gen.obj - $(OBJDIR)/js$*gen$(HOST_BIN_SUFFIX) $@ + +$(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX): $(OBJDIR)/jskwgen.$(OBJ_SUFFIX) + link.exe -out:"$@" $(EXE_LINK_FLAGS) $^ + else -$(AUTO_HEADERS): $(OBJDIR)/jsauto%.h: js%gen.cpp +$(OBJDIR)/jskwgen.o: jskwgen.cpp jskeyword.tbl @$(MAKE_OBJDIR) - $(CXX) -o $(OBJDIR)/js$*gen$(HOST_BIN_SUFFIX) $(CFLAGS) $(LDFLAGS) $< - $(OBJDIR)/js$*gen$(HOST_BIN_SUFFIX) $@ + $(CXX) -o $@ -c $(CFLAGS) $< + +$(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX): $(OBJDIR)/jskwgen.$(OBJ_SUFFIX) + $(CXX) -o $@ $(CFLAGS) $(LDFLAGS) $^ endif -# force creation of autoheaders before compiling any source that may use them -$(LIB_OBJS) : $(AUTO_HEADERS) - # # JS shell executable # diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index 7309ebbabf53..311d7cc06edd 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -62,8 +62,6 @@ #include "jsscript.h" #include "jsstr.h" -#include "jsautooplen.h" - typedef struct JSTrap { JSCList links; JSScript *script; diff --git a/js/src/jsemit.cpp b/js/src/jsemit.cpp index 638ade9eef55..daff25c9e53a 100644 --- a/js/src/jsemit.cpp +++ b/js/src/jsemit.cpp @@ -66,8 +66,6 @@ #include "jsscope.h" #include "jsscript.h" -#include "jsautooplen.h" - /* Allocation chunk counts, must be powers of two in general. */ #define BYTECODE_CHUNK 256 /* code allocation increment */ #define SRCNOTE_CHUNK 64 /* initial srcnote allocation increment */ diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 9bc14c21e7af..3c58cabee4b7 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -77,8 +77,6 @@ #include "jsxml.h" #endif -#include "jsautooplen.h" - #ifdef js_invoke_c__ uint32 @@ -2076,77 +2074,6 @@ js_DoIncDec(JSContext *cx, const JSCodeSpec *cs, jsval *vp, jsval *vp2) return JS_TRUE; } -#ifdef DEBUG - -void -js_TraceOpcode(JSContext *cx, jsint len) -{ - FILE *tracefp; - JSStackFrame *fp; - JSFrameRegs *regs; - JSOp prevop; - intN ndefs, n, nuses; - jsval *siter; - JSString *str; - JSOp op; - - tracefp = (FILE *) cx->tracefp; - JS_ASSERT(tracefp); - fp = cx->fp; - regs = fp->regs; - if (len != 0) { - prevop = (JSOp) regs->pc[-len]; - ndefs = js_CodeSpec[prevop].ndefs; - if (ndefs != 0) { - if (prevop == JSOP_FORELEM && regs->sp[-1] == JSVAL_FALSE) - --ndefs; - for (n = -ndefs; n < 0; n++) { - char *bytes = js_DecompileValueGenerator(cx, n, regs->sp[n], - NULL); - if (bytes) { - fprintf(tracefp, "%s %s", - (n == -ndefs) ? " output:" : ",", - bytes); - JS_free(cx, bytes); - } - } - fprintf(tracefp, " @ %d\n", regs->sp - fp->spbase); - } - fprintf(tracefp, " stack: "); - for (siter = fp->spbase; siter < regs->sp; siter++) { - str = js_ValueToString(cx, *siter); - if (!str) - fputs("", tracefp); - else - js_FileEscapedString(tracefp, str, 0); - fputc(' ', tracefp); - } - fputc('\n', tracefp); - } - - fprintf(tracefp, "%4u: ", js_PCToLineNumber(cx, fp->script, regs->pc)); - js_Disassemble1(cx, fp->script, regs->pc, - PTRDIFF(regs->pc, fp->script->code, jsbytecode), - JS_FALSE, tracefp); - op = (JSOp) *regs->pc; - nuses = js_CodeSpec[op].nuses; - if (nuses != 0) { - for (n = -nuses; n < 0; n++) { - char *bytes = js_DecompileValueGenerator(cx, n, regs->sp[n], - NULL); - if (bytes) { - fprintf(tracefp, "%s %s", - (n == -nuses) ? " inputs:" : ",", - bytes); - JS_free(cx, bytes); - } - } - fprintf(tracefp, " @ %d\n", regs->sp - fp->spbase); - } -} - -#endif /* DEBUG */ - #ifdef JS_OPMETER # include @@ -2498,13 +2425,6 @@ JS_STATIC_ASSERT(!CAN_DO_FAST_INC_DEC(INT_TO_JSVAL(JSVAL_INT_MAX))); # endif #endif - -/* - * Interpreter assumes the following to implement condition-free interrupt - * implementation when !JS_THREADED_INTERP. - */ -JS_STATIC_ASSERT(JSOP_INTERRUPT == 0); - /* * Ensure that the intrepreter switch can close call-bytecode cases in the * same way as non-call bytecodes. @@ -2542,6 +2462,7 @@ js_Interpret(JSContext *cx) JSFrameRegs regs; JSObject *obj, *obj2, *parent; JSBool ok, cond; + JSTrapHandler interruptHandler; jsint len; jsbytecode *endpc, *pc2; JSOp op, op2; @@ -2560,11 +2481,8 @@ js_Interpret(JSContext *cx) JSClass *clasp; JSFunction *fun; JSType type; -#if JS_THREADED_INTERP - register const void * const *jumpTable; -#else - register uint32 switchMask; - uintN switchOp; +#if !JS_THREADED_INTERP && defined DEBUG + FILE *tracefp = NULL; #endif #if JS_HAS_EXPORT_IMPORT JSIdArray *ida; @@ -2584,68 +2502,42 @@ js_Interpret(JSContext *cx) #endif #if JS_THREADED_INTERP - static const void *const normalJumpTable[] = { + static void *normalJumpTable[] = { # define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \ JS_EXTENSION &&L_##op, # include "jsopcode.tbl" # undef OPDEF }; - static const void *const interruptJumpTable[] = { + static void *interruptJumpTable[] = { # define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \ - JS_EXTENSION &&L_JSOP_INTERRUPT, + JS_EXTENSION &&interrupt, # include "jsopcode.tbl" # undef OPDEF }; + register void **jumpTable = normalJumpTable; + METER_OP_INIT(op); /* to nullify first METER_OP_PAIR */ # define DO_OP() JS_EXTENSION_(goto *jumpTable[op]) -# define DO_NEXT_OP(n) JS_BEGIN_MACRO \ - METER_OP_PAIR(op, regs.pc[n]); \ - op = (JSOp) *(regs.pc += (n)); \ - DO_OP(); \ - JS_END_MACRO - +# define DO_NEXT_OP(n) do { METER_OP_PAIR(op, regs.pc[n]); \ + op = (JSOp) *(regs.pc += (n)); \ + DO_OP(); } while (0) # define BEGIN_CASE(OP) L_##OP: # define END_CASE(OP) DO_NEXT_OP(OP##_LENGTH); # define END_VARLEN_CASE DO_NEXT_OP(len); -# define ADD_EMPTY_CASE(OP) BEGIN_CASE(OP) \ - JS_ASSERT(js_CodeSpec[OP].length == 1); \ - op = (JSOp) *++regs.pc; \ - DO_OP(); - -# define END_EMPTY_CASES - -#else /* !JS_THREADED_INTERP */ - +# define EMPTY_CASE(OP) BEGIN_CASE(OP) op = (JSOp) *++regs.pc; DO_OP(); +#else # define DO_OP() goto do_op -# define DO_NEXT_OP(n) JS_BEGIN_MACRO \ - JS_ASSERT((n) == len); \ - goto advance_pc; \ - JS_END_MACRO - +# define DO_NEXT_OP(n) goto advance_pc # define BEGIN_CASE(OP) case OP: -# define END_CASE(OP) END_CASE_LEN(OP##_LENGTH) -# define END_CASE_LEN(n) END_CASE_LENX(n) -# define END_CASE_LENX(n) END_CASE_LEN##n - -/* - * To share the code for all len == 1 cases we use the specialized label with - * code that falls through to advance_pc: . - */ -# define END_CASE_LEN1 goto advance_pc_by_one; -# define END_CASE_LEN2 len = 2; goto advance_pc; -# define END_CASE_LEN3 len = 3; goto advance_pc; -# define END_CASE_LEN4 len = 4; goto advance_pc; -# define END_CASE_LEN5 len = 5; goto advance_pc; -# define END_VARLEN_CASE goto advance_pc; -# define ADD_EMPTY_CASE(OP) BEGIN_CASE(OP) -# define END_EMPTY_CASES goto advance_pc_by_one; - +# define END_CASE(OP) break; +# define END_VARLEN_CASE break; +# define EMPTY_CASE(OP) BEGIN_CASE(OP) END_CASE(OP) #endif - /* Check for too deep of a native thread stack. */ + /* Check for too deep a C stack. */ JS_CHECK_RECURSION(cx, return JS_FALSE); rt = cx->runtime; @@ -2724,15 +2616,18 @@ js_Interpret(JSContext *cx) * the compiler can keep it in a register when it is non-null. */ #if JS_THREADED_INTERP -# define LOAD_INTERRUPT_HANDLER(cx) \ - ((void) (jumpTable = (cx)->debugHooks->interruptHandler \ - ? interruptJumpTable \ - : normalJumpTable)) +# define LOAD_JUMP_TABLE() \ + (jumpTable = interruptHandler ? interruptJumpTable : normalJumpTable) #else -# define LOAD_INTERRUPT_HANDLER(cx) \ - ((void) (switchMask = (cx)->debugHooks->interruptHandler ? 0 : 255)) +# define LOAD_JUMP_TABLE() ((void) 0) #endif +#define LOAD_INTERRUPT_HANDLER(cx) \ + JS_BEGIN_MACRO \ + interruptHandler = (cx)->debugHooks->interruptHandler; \ + LOAD_JUMP_TABLE(); \ + JS_END_MACRO + LOAD_INTERRUPT_HANDLER(cx); /* @@ -2780,89 +2675,107 @@ js_Interpret(JSContext *cx) } } - /* - * It is important that "op" be initialized before calling DO_OP because - * it is possible for "op" to be specially assigned during the normal - * processing of an opcode while looping. We rely on DO_NEXT_OP to manage - * "op" correctly in all other cases. - */ - len = 0; - DO_NEXT_OP(len); - #if JS_THREADED_INTERP + /* - * This is a loop, but it does not look like a loop. The loop-closing - * jump is distributed throughout goto *jumpTable[op] inside of DO_OP. - * When interrupts are enabled, jumpTable is set to interruptJumpTable - * where all jumps point to the JSOP_INTERRUPT case. The latter, after - * calling the interrupt handler, dispatches through normalJumpTable to - * continue the normal bytecode processing. + * This is a loop, but it does not look like a loop. The loop-closing + * jump is distributed throughout interruptJumpTable, and comes back to + * the interrupt label. The dispatch on op is through normalJumpTable. + * The trick is LOAD_INTERRUPT_HANDLER setting jumpTable appropriately. + * + * It is important that "op" be initialized before the interrupt label + * because it is possible for "op" to be specially assigned during the + * normally processing of an opcode while looping (in particular, this + * happens in JSOP_TRAP while debugging). We rely on DO_NEXT_OP to + * correctly manage "op" in all other cases. */ -#else + op = (JSOp) *regs.pc; + if (interruptHandler) { +interrupt: + switch (interruptHandler(cx, script, regs.pc, &rval, + cx->debugHooks->interruptHandlerData)) { + case JSTRAP_ERROR: + goto error; + case JSTRAP_CONTINUE: + break; + case JSTRAP_RETURN: + fp->rval = rval; + ok = JS_TRUE; + goto forced_return; + case JSTRAP_THROW: + cx->throwing = JS_TRUE; + cx->exception = rval; + goto error; + default:; + } + LOAD_INTERRUPT_HANDLER(cx); + } + + JS_ASSERT((uintN)op < (uintN)JSOP_LIMIT); + JS_EXTENSION_(goto *normalJumpTable[op]); + +#else /* !JS_THREADED_INTERP */ + for (;;) { - advance_pc_by_one: - JS_ASSERT(js_CodeSpec[op].length == 1); - len = 1; - advance_pc: - regs.pc += len; op = (JSOp) *regs.pc; -#ifdef DEBUG - if (cx->tracefp) - js_TraceOpcode(cx, len); -#endif - do_op: - switchOp = op & switchMask; - do_switch: - switch (switchOp) { -#endif /* !JS_THREADED_INTERP */ + len = js_CodeSpec[op].length; - BEGIN_CASE(JSOP_INTERRUPT) - { - JSTrapHandler handler; +#ifdef DEBUG + tracefp = (FILE *) cx->tracefp; + if (tracefp) { + intN nuses, n; - handler = cx->debugHooks->interruptHandler; - if (handler) { - switch (handler(cx, script, regs.pc, &rval, - cx->debugHooks->interruptHandlerData)) { - case JSTRAP_ERROR: - goto error; - case JSTRAP_CONTINUE: - break; - case JSTRAP_RETURN: - fp->rval = rval; - ok = JS_TRUE; - goto forced_return; - case JSTRAP_THROW: - cx->throwing = JS_TRUE; - cx->exception = rval; - goto error; - default:; + fprintf(tracefp, "%4u: ", js_PCToLineNumber(cx, script, regs.pc)); + js_Disassemble1(cx, script, regs.pc, + PTRDIFF(regs.pc, script->code, jsbytecode), + JS_FALSE, tracefp); + nuses = js_CodeSpec[op].nuses; + if (nuses) { + for (n = -nuses; n < 0; n++) { + char *bytes = js_DecompileValueGenerator(cx, n, regs.sp[n], + NULL); + if (bytes) { + fprintf(tracefp, "%s %s", + (n == -nuses) ? " inputs:" : ",", + bytes); + JS_free(cx, bytes); + } } + fprintf(tracefp, " @ %d\n", regs.sp - fp->spbase); + } + } +#endif /* DEBUG */ + + if (interruptHandler) { + switch (interruptHandler(cx, script, regs.pc, &rval, + cx->debugHooks->interruptHandlerData)) { + case JSTRAP_ERROR: + goto error; + case JSTRAP_CONTINUE: + break; + case JSTRAP_RETURN: + fp->rval = rval; + ok = JS_TRUE; + goto forced_return; + case JSTRAP_THROW: + cx->throwing = JS_TRUE; + cx->exception = rval; + goto error; + default:; } LOAD_INTERRUPT_HANDLER(cx); + } -#if JS_THREADED_INTERP - JS_EXTENSION_(goto *normalJumpTable[op]); -#else - switchOp = op; - goto do_switch; -#endif - } + switch (op) { - /* No-ops for ease of decompilation. */ - ADD_EMPTY_CASE(JSOP_NOP) - ADD_EMPTY_CASE(JSOP_GROUP) - ADD_EMPTY_CASE(JSOP_CONDSWITCH) - ADD_EMPTY_CASE(JSOP_TRY) - ADD_EMPTY_CASE(JSOP_FINALLY) -#if JS_HAS_XML_SUPPORT - ADD_EMPTY_CASE(JSOP_STARTXML) - ADD_EMPTY_CASE(JSOP_STARTXMLEXPR) -#endif - END_EMPTY_CASES +#endif /* !JS_THREADED_INTERP */ - /* ADD_EMPTY_CASE is not used here as JSOP_LINENO_LENGTH == 3. */ + EMPTY_CASE(JSOP_NOP) + + EMPTY_CASE(JSOP_GROUP) + + /* EMPTY_CASE is not used here as JSOP_LINENO_LENGTH == 3. */ BEGIN_CASE(JSOP_LINENO) END_CASE(JSOP_LINENO) @@ -2897,6 +2810,12 @@ js_Interpret(JSContext *cx) #endif END_CASE(JSOP_POPN) + BEGIN_CASE(JSOP_SWAP) + rtmp = regs.sp[-1]; + regs.sp[-1] = regs.sp[-2]; + regs.sp[-2] = rtmp; + END_CASE(JSOP_SWAP) + BEGIN_CASE(JSOP_SETRVAL) BEGIN_CASE(JSOP_POPV) ASSERT_NOT_THROWING(cx); @@ -4220,6 +4139,7 @@ js_Interpret(JSContext *cx) i = 0; COMPUTE_THIS(cx, fp, obj); PUSH(JSVAL_NULL); + len = JSOP_GETTHISPROP_LENGTH; goto do_getprop_with_obj; #undef COMPUTE_THIS @@ -4229,6 +4149,7 @@ js_Interpret(JSContext *cx) slot = GET_ARGNO(regs.pc); JS_ASSERT(slot < fp->fun->nargs); PUSH_OPND(fp->argv[slot]); + len = JSOP_GETARGPROP_LENGTH; goto do_getprop_body; BEGIN_CASE(JSOP_GETVARPROP) @@ -4236,6 +4157,7 @@ js_Interpret(JSContext *cx) slot = GET_VARNO(regs.pc); JS_ASSERT(slot < fp->fun->u.i.nvars); PUSH_OPND(fp->vars[slot]); + len = JSOP_GETVARPROP_LENGTH; goto do_getprop_body; BEGIN_CASE(JSOP_GETLOCALPROP) @@ -4243,11 +4165,13 @@ js_Interpret(JSContext *cx) slot = GET_UINT16(regs.pc); JS_ASSERT(slot < script->depth); PUSH_OPND(fp->spbase[slot]); + len = JSOP_GETLOCALPROP_LENGTH; goto do_getprop_body; BEGIN_CASE(JSOP_GETPROP) BEGIN_CASE(JSOP_GETXPROP) i = 0; + len = JSOP_GETPROP_LENGTH; do_getprop_body: lval = FETCH_OPND(-1); @@ -4293,8 +4217,6 @@ js_Interpret(JSContext *cx) } while (0); STORE_OPND(-1, rval); - JS_ASSERT(JSOP_GETPROP_LENGTH + i == js_CodeSpec[op].length); - len = JSOP_GETPROP_LENGTH + i; END_VARLEN_CASE BEGIN_CASE(JSOP_LENGTH) @@ -4319,7 +4241,8 @@ js_Interpret(JSContext *cx) goto error; } } else { - i = -2; + i = -1; + len = JSOP_LENGTH_LENGTH; goto do_getprop_with_lval; } END_CASE(JSOP_LENGTH) @@ -5073,12 +4996,12 @@ js_Interpret(JSContext *cx) goto error; if (!prop) { /* Kludge to allow (typeof foo == "undefined") tests. */ + len = JSOP_NAME_LENGTH; endpc = script->code + script->length; - for (pc2 = regs.pc + JSOP_NAME_LENGTH; pc2 < endpc; pc2++) { + for (pc2 = regs.pc + len; pc2 < endpc; pc2++) { op2 = (JSOp)*pc2; if (op2 == JSOP_TYPEOF) { PUSH_OPND(JSVAL_VOID); - len = JSOP_NAME_LENGTH; DO_NEXT_OP(len); } if (op2 != JSOP_GROUP) @@ -5415,6 +5338,8 @@ js_Interpret(JSContext *cx) : GET_JUMPX_OFFSET(pc2); END_VARLEN_CASE + EMPTY_CASE(JSOP_CONDSWITCH) + #if JS_HAS_EXPORT_IMPORT BEGIN_CASE(JSOP_EXPORTALL) obj = fp->varobj; @@ -5489,13 +5414,15 @@ js_Interpret(JSContext *cx) #endif /* JS_HAS_EXPORT_IMPORT */ BEGIN_CASE(JSOP_TRAP) - { - JSTrapStatus status; - - status = JS_HandleTrap(cx, script, regs.pc, &rval); - switch (status) { + switch (JS_HandleTrap(cx, script, regs.pc, &rval)) { case JSTRAP_ERROR: goto error; + case JSTRAP_CONTINUE: + JS_ASSERT(JSVAL_IS_INT(rval)); + op = (JSOp) JSVAL_TO_INT(rval); + JS_ASSERT((uintN)op < (uintN)JSOP_LIMIT); + LOAD_INTERRUPT_HANDLER(cx); + DO_OP(); case JSTRAP_RETURN: fp->rval = rval; ok = JS_TRUE; @@ -5505,15 +5432,9 @@ js_Interpret(JSContext *cx) cx->exception = rval; goto error; default:; - break; } - JS_ASSERT(status == JSTRAP_CONTINUE); LOAD_INTERRUPT_HANDLER(cx); - JS_ASSERT(JSVAL_IS_INT(rval)); - op = (JSOp) JSVAL_TO_INT(rval); - JS_ASSERT((uintN)op < (uintN)JSOP_LIMIT); - DO_OP(); - } + END_CASE(JSOP_TRAP) BEGIN_CASE(JSOP_ARGUMENTS) if (!js_GetArgsValue(cx, fp, &rval)) @@ -6251,7 +6172,7 @@ js_Interpret(JSContext *cx) goto error; } regs.sp -= 2; - END_CASE(JSOP_INITELEM) + END_CASE(JSOP_INITELEM); #if JS_HAS_SHARP_VARS BEGIN_CASE(JSOP_DEFSHARP) @@ -6298,11 +6219,15 @@ js_Interpret(JSContext *cx) END_CASE(JSOP_USESHARP) #endif /* JS_HAS_SHARP_VARS */ + /* No-ops for ease of decompilation and jit'ing. */ + EMPTY_CASE(JSOP_TRY) + EMPTY_CASE(JSOP_FINALLY) + BEGIN_CASE(JSOP_GOSUB) PUSH(JSVAL_FALSE); i = PTRDIFF(regs.pc, script->main, jsbytecode) + JSOP_GOSUB_LENGTH; - PUSH(INT_TO_JSVAL(i)); len = GET_JUMP_OFFSET(regs.pc); + PUSH(INT_TO_JSVAL(i)); END_VARLEN_CASE BEGIN_CASE(JSOP_GOSUBX) @@ -6557,6 +6482,9 @@ js_Interpret(JSContext *cx) regs.sp--; END_CASE(JSOP_ENDFILTER); + EMPTY_CASE(JSOP_STARTXML) + EMPTY_CASE(JSOP_STARTXMLEXPR) + BEGIN_CASE(JSOP_TOXML) rval = FETCH_OPND(-1); obj = js_ValueToXMLObject(cx, rval); @@ -6856,6 +6784,48 @@ js_Interpret(JSContext *cx) #if !JS_THREADED_INTERP } /* switch (op) */ + + advance_pc: + regs.pc += len; + +#ifdef DEBUG + if (tracefp) { + intN ndefs, n; + jsval *siter; + + /* + * op may be invalid here when a catch or finally handler jumps to + * advance_pc. + */ + op = (JSOp) regs.pc[-len]; + ndefs = js_CodeSpec[op].ndefs; + if (ndefs) { + if (op == JSOP_FORELEM && regs.sp[-1] == JSVAL_FALSE) + --ndefs; + for (n = -ndefs; n < 0; n++) { + char *bytes = js_DecompileValueGenerator(cx, n, regs.sp[n], + NULL); + if (bytes) { + fprintf(tracefp, "%s %s", + (n == -ndefs) ? " output:" : ",", + bytes); + JS_free(cx, bytes); + } + } + fprintf(tracefp, " @ %d\n", regs.sp - fp->spbase); + } + fprintf(tracefp, " stack: "); + for (siter = fp->spbase; siter < regs.sp; siter++) { + str = js_ValueToString(cx, *siter); + if (!str) + fputs("", tracefp); + else + js_FileEscapedString(tracefp, str, 0); + fputc(' ', tracefp); + } + fputc('\n', tracefp); + } +#endif /* DEBUG */ } #endif /* !JS_THREADED_INTERP */ diff --git a/js/src/jsinterp.h b/js/src/jsinterp.h index 3f8bdfe9bba7..7fb54660a749 100644 --- a/js/src/jsinterp.h +++ b/js/src/jsinterp.h @@ -507,13 +507,6 @@ js_OnUnknownMethod(JSContext *cx, jsval *vp); extern JSBool js_DoIncDec(JSContext *cx, const JSCodeSpec *cs, jsval *vp, jsval *vp2); -/* - * Opcode tracing helper. When len is not 0, cx->fp->regs->pc[-len] gives the - * previous opcode. - */ -extern void -js_TraceOpcode(JSContext *cx, jsint len); - /* * JS_OPMETER helper functions. */ diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index e8ac435e8daa..a9540166152c 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -88,8 +88,6 @@ #include "jsdtracef.h" #endif -#include "jsautooplen.h" - #ifdef JS_THREADSAFE #define NATIVE_DROP_PROPERTY js_DropProperty diff --git a/js/src/jsopcode.cpp b/js/src/jsopcode.cpp index 91e0f9e0fa7f..cf0accc147d5 100644 --- a/js/src/jsopcode.cpp +++ b/js/src/jsopcode.cpp @@ -75,14 +75,6 @@ # include "jsnum.h" #endif -#include "jsautooplen.h" - -/* Verify JSOP_XXX_LENGTH constant definitions. */ -#define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \ - JS_STATIC_ASSERT(op##_LENGTH == length); -#include "jsopcode.tbl" -#undef OPDEF - static const char js_incop_strs[][3] = {"++", "--"}; const JSCodeSpec js_CodeSpec[] = { @@ -2160,6 +2152,14 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) todo = -2; break; + case JSOP_SWAP: + /* + * We don't generate this opcode currently, and previously we + * did not need to decompile it. If old, serialized bytecode + * uses it still, we should fall through and set todo = -2. + */ + /* FALL THROUGH */ + case JSOP_GOSUB: case JSOP_GOSUBX: /* @@ -4993,7 +4993,8 @@ DecompileExpression(JSContext *cx, JSScript *script, JSFunction *fun, /* None of these stack-writing ops generates novel values. */ JS_ASSERT(op != JSOP_CASE && op != JSOP_CASEX && - op != JSOP_DUP && op != JSOP_DUP2); + op != JSOP_DUP && op != JSOP_DUP2 && + op != JSOP_SWAP); /* * |this| could convert to a very long object initialiser, so cite it by @@ -5273,6 +5274,13 @@ ReconstructPCStack(JSContext *cx, JSScript *script, jsbytecode *pc, pcstack[pcdepth + 3] = pcstack[pcdepth + 1]; break; + case JSOP_SWAP: + JS_ASSERT(ndefs == 2); + pc2 = pcstack[pcdepth]; + pcstack[pcdepth] = pcstack[pcdepth + 1]; + pcstack[pcdepth + 1] = pc2; + break; + case JSOP_LEAVEBLOCKEXPR: /* * The decompiler wants to see [leaveblockexpr] on pcstack, not diff --git a/js/src/jsopcode.h b/js/src/jsopcode.h index 831b95fa9401..9e185e4c3b07 100644 --- a/js/src/jsopcode.h +++ b/js/src/jsopcode.h @@ -60,6 +60,14 @@ typedef enum JSOp { JSOP_LIMIT } JSOp; +typedef enum JSOpLength { +#define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \ + op##_LENGTH = length, +#include "jsopcode.tbl" +#undef OPDEF + JSOP_LIMIT_LENGTH +} JSOpLength; + /* * JS bytecode formats. */ diff --git a/js/src/jsopcode.tbl b/js/src/jsopcode.tbl index f9ea46a03a5d..7806e08e018f 100644 --- a/js/src/jsopcode.tbl +++ b/js/src/jsopcode.tbl @@ -97,7 +97,7 @@ /* legend: op val name image len use def prec format */ /* Longstanding JavaScript bytecodes. */ -OPDEF(JSOP_INTERRUPT, 0, "interrupt", NULL, 1, 0, 0, 0, JOF_BYTE) +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, 2, JOF_BYTE) OPDEF(JSOP_ENTERWITH, 3, "enterwith", NULL, 1, 1, 1, 0, JOF_BYTE|JOF_PARENHEAD) @@ -331,9 +331,9 @@ OPDEF(JSOP_TRY, 133,"try", NULL, 1, 0, 0, 0, JOF_BYTE) OPDEF(JSOP_FINALLY, 134,"finally", NULL, 1, 0, 0, 0, JOF_BYTE) /* - * Generic nop for the decompiler. + * Swap the top two stack elements. */ -OPDEF(JSOP_NOP, 135,"nop", NULL, 1, 0, 0, 0, JOF_BYTE) +OPDEF(JSOP_SWAP, 135,"swap", NULL, 1, 2, 2, 0, JOF_BYTE) /* * Bytecodes that avoid making an arguments object in most cases: diff --git a/js/src/jsxdrapi.h b/js/src/jsxdrapi.h index 68a45432af94..3026b49ee215 100644 --- a/js/src/jsxdrapi.h +++ b/js/src/jsxdrapi.h @@ -202,7 +202,7 @@ JS_XDRFindClassById(JSXDRState *xdr, uint32 id); * before deserialization of bytecode. If the saved version does not match * the current version, abort deserialization and invalidate the file. */ -#define JSXDR_BYTECODE_VERSION (0xb973c0de - 26) +#define JSXDR_BYTECODE_VERSION (0xb973c0de - 25) /* * Library-private functions. diff --git a/js/src/liveconnect/nsCLiveconnect.cpp b/js/src/liveconnect/nsCLiveconnect.cpp index 3c0c344fcfc2..4adfc740142b 100644 --- a/js/src/liveconnect/nsCLiveconnect.cpp +++ b/js/src/liveconnect/nsCLiveconnect.cpp @@ -192,8 +192,8 @@ AutoPushJSContext::AutoPushJSContext(nsISupports* aSecuritySupports, mFrame.callee = JS_GetFunctionObject(fun); mFrame.scopeChain = JS_GetParent(cx, mFrame.callee); mFrame.down = cx->fp; - mRegs.pc = script->code + script->length - 1; - JS_ASSERT(static_cast(*mRegs.pc) == JSOP_STOP); + mRegs.pc = script->code + script->length + - JSOP_STOP_LENGTH; mRegs.sp = NULL; mFrame.regs = &mRegs; cx->fp = &mFrame; diff --git a/js/src/rules.mk b/js/src/rules.mk index ad80ad0f449a..4ab596f23a69 100644 --- a/js/src/rules.mk +++ b/js/src/rules.mk @@ -185,9 +185,11 @@ endif clean: rm -rf $(OBJS) $(GARBAGE) + @cd fdlibm; $(MAKE) -f Makefile.ref clean clobber: rm -rf $(OBJS) $(TARGETS) $(DEPENDENCIES) + @cd fdlibm; $(MAKE) -f Makefile.ref clobber tar: tar cvf $(TARNAME) $(TARFILES) From bc084d42f7413b56699a8001a0d63f029569fefb Mon Sep 17 00:00:00 2001 From: Igor Bukanov Date: Fri, 20 Jun 2008 10:06:45 +0200 Subject: [PATCH 33/66] [Bug 433382] More efficient interpreter switch when computed goto is not available. r=brendan --- js/src/Makefile.in | 17 +- js/src/Makefile.ref | 34 +-- js/src/jsdbgapi.cpp | 2 + js/src/jsemit.cpp | 2 + js/src/jsinterp.cpp | 416 ++++++++++++++------------ js/src/jsinterp.h | 7 + js/src/jsobj.cpp | 2 + js/src/jsopcode.cpp | 26 +- js/src/jsopcode.h | 8 - js/src/jsopcode.tbl | 6 +- js/src/jsxdrapi.h | 2 +- js/src/liveconnect/nsCLiveconnect.cpp | 4 +- js/src/rules.mk | 2 - 13 files changed, 281 insertions(+), 247 deletions(-) diff --git a/js/src/Makefile.in b/js/src/Makefile.in index d0d0e922fe7a..8a4d75809181 100644 --- a/js/src/Makefile.in +++ b/js/src/Makefile.in @@ -242,6 +242,10 @@ JSJAVA_CFLAGS = \ HOST_SIMPLE_PROGRAMS += host_jskwgen$(HOST_BIN_SUFFIX) GARBAGE += jsautokw.h host_jskwgen$(HOST_BIN_SUFFIX) + +HOST_SIMPLE_PROGRAMS += host_jsoplengen$(HOST_BIN_SUFFIX) +GARBAGE += jsautooplen.h host_jsoplengen$(HOST_BIN_SUFFIX) + USE_HOST_CXX = 1 ifdef HAVE_DTRACE @@ -445,18 +449,23 @@ jscpucfg$(HOST_BIN_SUFFIX): jscpucfg.cpp Makefile.in endif endif -# Extra dependancies and rules for keyword switch code -jsscan.$(OBJ_SUFFIX): jsautokw.h jskeyword.tbl - +# Extra dependancies and rules for auto-generated headers host_jskwgen.$(OBJ_SUFFIX): jsconfig.h jskeyword.tbl jsautokw.h: host_jskwgen$(HOST_BIN_SUFFIX) ./host_jskwgen$(HOST_BIN_SUFFIX) $@ +host_jsoplengen.$(OBJ_SUFFIX): jsopcode.tbl + +jsautooplen.h: host_jsoplengen$(HOST_BIN_SUFFIX) + ./host_jsoplengen$(HOST_BIN_SUFFIX) $@ + +# Force auto-header generation before compiling any source that may use them +$(CPPSRCS:%.cpp=%.$(OBJ_SUFFIX)): jsautokw.h jsautooplen.h + ifdef HAVE_DTRACE javascript-trace.h: $(srcdir)/javascript-trace.d dtrace -h -s $(srcdir)/javascript-trace.d -o javascript-trace.h.in sed 's/if _DTRACE_VERSION/ifdef INCLUDE_MOZILLA_DTRACE/' \ javascript-trace.h.in > javascript-trace.h endif - diff --git a/js/src/Makefile.ref b/js/src/Makefile.ref index a6ada0ca6cfa..520e801d71ca 100644 --- a/js/src/Makefile.ref +++ b/js/src/Makefile.ref @@ -277,39 +277,39 @@ nsinstall-target: cd ../../config; $(MAKE) OBJDIR=$(OBJDIR) OBJDIR_NAME=$(OBJDIR) # -# Rules for keyword switch generation +# Automatic header generation # -GARBAGE += $(OBJDIR)/jsautokw.h $(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX) -GARBAGE += $(OBJDIR)/jskwgen.$(OBJ_SUFFIX) +AUTO_HEADERS = $(OBJDIR)/jsautokw.h $(OBJDIR)/jsautooplen.h -$(OBJDIR)/jsscan.$(OBJ_SUFFIX): $(OBJDIR)/jsautokw.h jskeyword.tbl +$(OBJDIR)/jsautokw.h: jskeyword.tbl -$(OBJDIR)/jskwgen.$(OBJ_SUFFIX): jskwgen.cpp jskeyword.tbl +$(OBJDIR)/jsautooplen.h: jsopcode.tbl -$(OBJDIR)/jsautokw.h: $(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX) jskeyword.tbl - $(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX) $@ +GARBAGE += $(AUTO_HEADERS) +GARBAGE += $(AUTO_HEADERS:$(OBJDIR)/jsauto%.h=$(OBJDIR)/js%gen$(HOST_BIN_SUFFIX)) ifdef USE_MSVC -$(OBJDIR)/jskwgen.obj: jskwgen.cpp jskeyword.tbl +GARBAGE += $(AUTO_HEADERS:$(OBJDIR)/jsauto%.h=$(OBJDIR)/js%gen.obj) + +$(AUTO_HEADERS): $(OBJDIR)/jsauto%.h: js%gen.cpp @$(MAKE_OBJDIR) $(CXX) -Fo$(OBJDIR)/ -c $(CFLAGS) $< - -$(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX): $(OBJDIR)/jskwgen.$(OBJ_SUFFIX) - link.exe -out:"$@" $(EXE_LINK_FLAGS) $^ - + link.exe -out:"$(OBJDIR)/js$*gen$(HOST_BIN_SUFFIX)" $(EXE_LINK_FLAGS) $(OBJDIR)/js$*gen.obj + $(OBJDIR)/js$*gen$(HOST_BIN_SUFFIX) $@ else -$(OBJDIR)/jskwgen.o: jskwgen.cpp jskeyword.tbl +$(AUTO_HEADERS): $(OBJDIR)/jsauto%.h: js%gen.cpp @$(MAKE_OBJDIR) - $(CXX) -o $@ -c $(CFLAGS) $< - -$(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX): $(OBJDIR)/jskwgen.$(OBJ_SUFFIX) - $(CXX) -o $@ $(CFLAGS) $(LDFLAGS) $^ + $(CXX) -o $(OBJDIR)/js$*gen$(HOST_BIN_SUFFIX) $(CFLAGS) $(LDFLAGS) $< + $(OBJDIR)/js$*gen$(HOST_BIN_SUFFIX) $@ endif +# force creation of autoheaders before compiling any source that may use them +$(LIB_OBJS) : $(AUTO_HEADERS) + # # JS shell executable # diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index 311d7cc06edd..7309ebbabf53 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -62,6 +62,8 @@ #include "jsscript.h" #include "jsstr.h" +#include "jsautooplen.h" + typedef struct JSTrap { JSCList links; JSScript *script; diff --git a/js/src/jsemit.cpp b/js/src/jsemit.cpp index daff25c9e53a..638ade9eef55 100644 --- a/js/src/jsemit.cpp +++ b/js/src/jsemit.cpp @@ -66,6 +66,8 @@ #include "jsscope.h" #include "jsscript.h" +#include "jsautooplen.h" + /* Allocation chunk counts, must be powers of two in general. */ #define BYTECODE_CHUNK 256 /* code allocation increment */ #define SRCNOTE_CHUNK 64 /* initial srcnote allocation increment */ diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 3c58cabee4b7..9bc14c21e7af 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -77,6 +77,8 @@ #include "jsxml.h" #endif +#include "jsautooplen.h" + #ifdef js_invoke_c__ uint32 @@ -2074,6 +2076,77 @@ js_DoIncDec(JSContext *cx, const JSCodeSpec *cs, jsval *vp, jsval *vp2) return JS_TRUE; } +#ifdef DEBUG + +void +js_TraceOpcode(JSContext *cx, jsint len) +{ + FILE *tracefp; + JSStackFrame *fp; + JSFrameRegs *regs; + JSOp prevop; + intN ndefs, n, nuses; + jsval *siter; + JSString *str; + JSOp op; + + tracefp = (FILE *) cx->tracefp; + JS_ASSERT(tracefp); + fp = cx->fp; + regs = fp->regs; + if (len != 0) { + prevop = (JSOp) regs->pc[-len]; + ndefs = js_CodeSpec[prevop].ndefs; + if (ndefs != 0) { + if (prevop == JSOP_FORELEM && regs->sp[-1] == JSVAL_FALSE) + --ndefs; + for (n = -ndefs; n < 0; n++) { + char *bytes = js_DecompileValueGenerator(cx, n, regs->sp[n], + NULL); + if (bytes) { + fprintf(tracefp, "%s %s", + (n == -ndefs) ? " output:" : ",", + bytes); + JS_free(cx, bytes); + } + } + fprintf(tracefp, " @ %d\n", regs->sp - fp->spbase); + } + fprintf(tracefp, " stack: "); + for (siter = fp->spbase; siter < regs->sp; siter++) { + str = js_ValueToString(cx, *siter); + if (!str) + fputs("", tracefp); + else + js_FileEscapedString(tracefp, str, 0); + fputc(' ', tracefp); + } + fputc('\n', tracefp); + } + + fprintf(tracefp, "%4u: ", js_PCToLineNumber(cx, fp->script, regs->pc)); + js_Disassemble1(cx, fp->script, regs->pc, + PTRDIFF(regs->pc, fp->script->code, jsbytecode), + JS_FALSE, tracefp); + op = (JSOp) *regs->pc; + nuses = js_CodeSpec[op].nuses; + if (nuses != 0) { + for (n = -nuses; n < 0; n++) { + char *bytes = js_DecompileValueGenerator(cx, n, regs->sp[n], + NULL); + if (bytes) { + fprintf(tracefp, "%s %s", + (n == -nuses) ? " inputs:" : ",", + bytes); + JS_free(cx, bytes); + } + } + fprintf(tracefp, " @ %d\n", regs->sp - fp->spbase); + } +} + +#endif /* DEBUG */ + #ifdef JS_OPMETER # include @@ -2425,6 +2498,13 @@ JS_STATIC_ASSERT(!CAN_DO_FAST_INC_DEC(INT_TO_JSVAL(JSVAL_INT_MAX))); # endif #endif + +/* + * Interpreter assumes the following to implement condition-free interrupt + * implementation when !JS_THREADED_INTERP. + */ +JS_STATIC_ASSERT(JSOP_INTERRUPT == 0); + /* * Ensure that the intrepreter switch can close call-bytecode cases in the * same way as non-call bytecodes. @@ -2462,7 +2542,6 @@ js_Interpret(JSContext *cx) JSFrameRegs regs; JSObject *obj, *obj2, *parent; JSBool ok, cond; - JSTrapHandler interruptHandler; jsint len; jsbytecode *endpc, *pc2; JSOp op, op2; @@ -2481,8 +2560,11 @@ js_Interpret(JSContext *cx) JSClass *clasp; JSFunction *fun; JSType type; -#if !JS_THREADED_INTERP && defined DEBUG - FILE *tracefp = NULL; +#if JS_THREADED_INTERP + register const void * const *jumpTable; +#else + register uint32 switchMask; + uintN switchOp; #endif #if JS_HAS_EXPORT_IMPORT JSIdArray *ida; @@ -2502,42 +2584,68 @@ js_Interpret(JSContext *cx) #endif #if JS_THREADED_INTERP - static void *normalJumpTable[] = { + static const void *const normalJumpTable[] = { # define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \ JS_EXTENSION &&L_##op, # include "jsopcode.tbl" # undef OPDEF }; - static void *interruptJumpTable[] = { + static const void *const interruptJumpTable[] = { # define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \ - JS_EXTENSION &&interrupt, + JS_EXTENSION &&L_JSOP_INTERRUPT, # include "jsopcode.tbl" # undef OPDEF }; - register void **jumpTable = normalJumpTable; - METER_OP_INIT(op); /* to nullify first METER_OP_PAIR */ # define DO_OP() JS_EXTENSION_(goto *jumpTable[op]) -# define DO_NEXT_OP(n) do { METER_OP_PAIR(op, regs.pc[n]); \ - op = (JSOp) *(regs.pc += (n)); \ - DO_OP(); } while (0) +# define DO_NEXT_OP(n) JS_BEGIN_MACRO \ + METER_OP_PAIR(op, regs.pc[n]); \ + op = (JSOp) *(regs.pc += (n)); \ + DO_OP(); \ + JS_END_MACRO + # define BEGIN_CASE(OP) L_##OP: # define END_CASE(OP) DO_NEXT_OP(OP##_LENGTH); # define END_VARLEN_CASE DO_NEXT_OP(len); -# define EMPTY_CASE(OP) BEGIN_CASE(OP) op = (JSOp) *++regs.pc; DO_OP(); -#else +# define ADD_EMPTY_CASE(OP) BEGIN_CASE(OP) \ + JS_ASSERT(js_CodeSpec[OP].length == 1); \ + op = (JSOp) *++regs.pc; \ + DO_OP(); + +# define END_EMPTY_CASES + +#else /* !JS_THREADED_INTERP */ + # define DO_OP() goto do_op -# define DO_NEXT_OP(n) goto advance_pc +# define DO_NEXT_OP(n) JS_BEGIN_MACRO \ + JS_ASSERT((n) == len); \ + goto advance_pc; \ + JS_END_MACRO + # define BEGIN_CASE(OP) case OP: -# define END_CASE(OP) break; -# define END_VARLEN_CASE break; -# define EMPTY_CASE(OP) BEGIN_CASE(OP) END_CASE(OP) +# define END_CASE(OP) END_CASE_LEN(OP##_LENGTH) +# define END_CASE_LEN(n) END_CASE_LENX(n) +# define END_CASE_LENX(n) END_CASE_LEN##n + +/* + * To share the code for all len == 1 cases we use the specialized label with + * code that falls through to advance_pc: . + */ +# define END_CASE_LEN1 goto advance_pc_by_one; +# define END_CASE_LEN2 len = 2; goto advance_pc; +# define END_CASE_LEN3 len = 3; goto advance_pc; +# define END_CASE_LEN4 len = 4; goto advance_pc; +# define END_CASE_LEN5 len = 5; goto advance_pc; +# define END_VARLEN_CASE goto advance_pc; +# define ADD_EMPTY_CASE(OP) BEGIN_CASE(OP) +# define END_EMPTY_CASES goto advance_pc_by_one; + #endif - /* Check for too deep a C stack. */ + /* Check for too deep of a native thread stack. */ JS_CHECK_RECURSION(cx, return JS_FALSE); rt = cx->runtime; @@ -2616,18 +2724,15 @@ js_Interpret(JSContext *cx) * the compiler can keep it in a register when it is non-null. */ #if JS_THREADED_INTERP -# define LOAD_JUMP_TABLE() \ - (jumpTable = interruptHandler ? interruptJumpTable : normalJumpTable) +# define LOAD_INTERRUPT_HANDLER(cx) \ + ((void) (jumpTable = (cx)->debugHooks->interruptHandler \ + ? interruptJumpTable \ + : normalJumpTable)) #else -# define LOAD_JUMP_TABLE() ((void) 0) +# define LOAD_INTERRUPT_HANDLER(cx) \ + ((void) (switchMask = (cx)->debugHooks->interruptHandler ? 0 : 255)) #endif -#define LOAD_INTERRUPT_HANDLER(cx) \ - JS_BEGIN_MACRO \ - interruptHandler = (cx)->debugHooks->interruptHandler; \ - LOAD_JUMP_TABLE(); \ - JS_END_MACRO - LOAD_INTERRUPT_HANDLER(cx); /* @@ -2675,107 +2780,89 @@ js_Interpret(JSContext *cx) } } -#if JS_THREADED_INTERP - /* - * This is a loop, but it does not look like a loop. The loop-closing - * jump is distributed throughout interruptJumpTable, and comes back to - * the interrupt label. The dispatch on op is through normalJumpTable. - * The trick is LOAD_INTERRUPT_HANDLER setting jumpTable appropriately. - * - * It is important that "op" be initialized before the interrupt label - * because it is possible for "op" to be specially assigned during the - * normally processing of an opcode while looping (in particular, this - * happens in JSOP_TRAP while debugging). We rely on DO_NEXT_OP to - * correctly manage "op" in all other cases. + * It is important that "op" be initialized before calling DO_OP because + * it is possible for "op" to be specially assigned during the normal + * processing of an opcode while looping. We rely on DO_NEXT_OP to manage + * "op" correctly in all other cases. */ - op = (JSOp) *regs.pc; - if (interruptHandler) { -interrupt: - switch (interruptHandler(cx, script, regs.pc, &rval, - cx->debugHooks->interruptHandlerData)) { - case JSTRAP_ERROR: - goto error; - case JSTRAP_CONTINUE: - break; - case JSTRAP_RETURN: - fp->rval = rval; - ok = JS_TRUE; - goto forced_return; - case JSTRAP_THROW: - cx->throwing = JS_TRUE; - cx->exception = rval; - goto error; - default:; - } - LOAD_INTERRUPT_HANDLER(cx); - } - - JS_ASSERT((uintN)op < (uintN)JSOP_LIMIT); - JS_EXTENSION_(goto *normalJumpTable[op]); - -#else /* !JS_THREADED_INTERP */ + len = 0; + DO_NEXT_OP(len); +#if JS_THREADED_INTERP + /* + * This is a loop, but it does not look like a loop. The loop-closing + * jump is distributed throughout goto *jumpTable[op] inside of DO_OP. + * When interrupts are enabled, jumpTable is set to interruptJumpTable + * where all jumps point to the JSOP_INTERRUPT case. The latter, after + * calling the interrupt handler, dispatches through normalJumpTable to + * continue the normal bytecode processing. + */ +#else for (;;) { + advance_pc_by_one: + JS_ASSERT(js_CodeSpec[op].length == 1); + len = 1; + advance_pc: + regs.pc += len; op = (JSOp) *regs.pc; - do_op: - len = js_CodeSpec[op].length; - #ifdef DEBUG - tracefp = (FILE *) cx->tracefp; - if (tracefp) { - intN nuses, n; - - fprintf(tracefp, "%4u: ", js_PCToLineNumber(cx, script, regs.pc)); - js_Disassemble1(cx, script, regs.pc, - PTRDIFF(regs.pc, script->code, jsbytecode), - JS_FALSE, tracefp); - nuses = js_CodeSpec[op].nuses; - if (nuses) { - for (n = -nuses; n < 0; n++) { - char *bytes = js_DecompileValueGenerator(cx, n, regs.sp[n], - NULL); - if (bytes) { - fprintf(tracefp, "%s %s", - (n == -nuses) ? " inputs:" : ",", - bytes); - JS_free(cx, bytes); - } - } - fprintf(tracefp, " @ %d\n", regs.sp - fp->spbase); - } - } -#endif /* DEBUG */ - - if (interruptHandler) { - switch (interruptHandler(cx, script, regs.pc, &rval, - cx->debugHooks->interruptHandlerData)) { - case JSTRAP_ERROR: - goto error; - case JSTRAP_CONTINUE: - break; - case JSTRAP_RETURN: - fp->rval = rval; - ok = JS_TRUE; - goto forced_return; - case JSTRAP_THROW: - cx->throwing = JS_TRUE; - cx->exception = rval; - goto error; - default:; - } - LOAD_INTERRUPT_HANDLER(cx); - } - - switch (op) { + if (cx->tracefp) + js_TraceOpcode(cx, len); +#endif + do_op: + switchOp = op & switchMask; + do_switch: + switch (switchOp) { #endif /* !JS_THREADED_INTERP */ - EMPTY_CASE(JSOP_NOP) + BEGIN_CASE(JSOP_INTERRUPT) + { + JSTrapHandler handler; - EMPTY_CASE(JSOP_GROUP) + handler = cx->debugHooks->interruptHandler; + if (handler) { + switch (handler(cx, script, regs.pc, &rval, + cx->debugHooks->interruptHandlerData)) { + case JSTRAP_ERROR: + goto error; + case JSTRAP_CONTINUE: + break; + case JSTRAP_RETURN: + fp->rval = rval; + ok = JS_TRUE; + goto forced_return; + case JSTRAP_THROW: + cx->throwing = JS_TRUE; + cx->exception = rval; + goto error; + default:; + } + } + LOAD_INTERRUPT_HANDLER(cx); - /* EMPTY_CASE is not used here as JSOP_LINENO_LENGTH == 3. */ +#if JS_THREADED_INTERP + JS_EXTENSION_(goto *normalJumpTable[op]); +#else + switchOp = op; + goto do_switch; +#endif + } + + /* No-ops for ease of decompilation. */ + ADD_EMPTY_CASE(JSOP_NOP) + ADD_EMPTY_CASE(JSOP_GROUP) + ADD_EMPTY_CASE(JSOP_CONDSWITCH) + ADD_EMPTY_CASE(JSOP_TRY) + ADD_EMPTY_CASE(JSOP_FINALLY) +#if JS_HAS_XML_SUPPORT + ADD_EMPTY_CASE(JSOP_STARTXML) + ADD_EMPTY_CASE(JSOP_STARTXMLEXPR) +#endif + END_EMPTY_CASES + + /* ADD_EMPTY_CASE is not used here as JSOP_LINENO_LENGTH == 3. */ BEGIN_CASE(JSOP_LINENO) END_CASE(JSOP_LINENO) @@ -2810,12 +2897,6 @@ interrupt: #endif END_CASE(JSOP_POPN) - BEGIN_CASE(JSOP_SWAP) - rtmp = regs.sp[-1]; - regs.sp[-1] = regs.sp[-2]; - regs.sp[-2] = rtmp; - END_CASE(JSOP_SWAP) - BEGIN_CASE(JSOP_SETRVAL) BEGIN_CASE(JSOP_POPV) ASSERT_NOT_THROWING(cx); @@ -4139,7 +4220,6 @@ interrupt: i = 0; COMPUTE_THIS(cx, fp, obj); PUSH(JSVAL_NULL); - len = JSOP_GETTHISPROP_LENGTH; goto do_getprop_with_obj; #undef COMPUTE_THIS @@ -4149,7 +4229,6 @@ interrupt: slot = GET_ARGNO(regs.pc); JS_ASSERT(slot < fp->fun->nargs); PUSH_OPND(fp->argv[slot]); - len = JSOP_GETARGPROP_LENGTH; goto do_getprop_body; BEGIN_CASE(JSOP_GETVARPROP) @@ -4157,7 +4236,6 @@ interrupt: slot = GET_VARNO(regs.pc); JS_ASSERT(slot < fp->fun->u.i.nvars); PUSH_OPND(fp->vars[slot]); - len = JSOP_GETVARPROP_LENGTH; goto do_getprop_body; BEGIN_CASE(JSOP_GETLOCALPROP) @@ -4165,13 +4243,11 @@ interrupt: slot = GET_UINT16(regs.pc); JS_ASSERT(slot < script->depth); PUSH_OPND(fp->spbase[slot]); - len = JSOP_GETLOCALPROP_LENGTH; goto do_getprop_body; BEGIN_CASE(JSOP_GETPROP) BEGIN_CASE(JSOP_GETXPROP) i = 0; - len = JSOP_GETPROP_LENGTH; do_getprop_body: lval = FETCH_OPND(-1); @@ -4217,6 +4293,8 @@ interrupt: } while (0); STORE_OPND(-1, rval); + JS_ASSERT(JSOP_GETPROP_LENGTH + i == js_CodeSpec[op].length); + len = JSOP_GETPROP_LENGTH + i; END_VARLEN_CASE BEGIN_CASE(JSOP_LENGTH) @@ -4241,8 +4319,7 @@ interrupt: goto error; } } else { - i = -1; - len = JSOP_LENGTH_LENGTH; + i = -2; goto do_getprop_with_lval; } END_CASE(JSOP_LENGTH) @@ -4996,12 +5073,12 @@ interrupt: goto error; if (!prop) { /* Kludge to allow (typeof foo == "undefined") tests. */ - len = JSOP_NAME_LENGTH; endpc = script->code + script->length; - for (pc2 = regs.pc + len; pc2 < endpc; pc2++) { + for (pc2 = regs.pc + JSOP_NAME_LENGTH; pc2 < endpc; pc2++) { op2 = (JSOp)*pc2; if (op2 == JSOP_TYPEOF) { PUSH_OPND(JSVAL_VOID); + len = JSOP_NAME_LENGTH; DO_NEXT_OP(len); } if (op2 != JSOP_GROUP) @@ -5338,8 +5415,6 @@ interrupt: : GET_JUMPX_OFFSET(pc2); END_VARLEN_CASE - EMPTY_CASE(JSOP_CONDSWITCH) - #if JS_HAS_EXPORT_IMPORT BEGIN_CASE(JSOP_EXPORTALL) obj = fp->varobj; @@ -5414,15 +5489,13 @@ interrupt: #endif /* JS_HAS_EXPORT_IMPORT */ BEGIN_CASE(JSOP_TRAP) - switch (JS_HandleTrap(cx, script, regs.pc, &rval)) { + { + JSTrapStatus status; + + status = JS_HandleTrap(cx, script, regs.pc, &rval); + switch (status) { case JSTRAP_ERROR: goto error; - case JSTRAP_CONTINUE: - JS_ASSERT(JSVAL_IS_INT(rval)); - op = (JSOp) JSVAL_TO_INT(rval); - JS_ASSERT((uintN)op < (uintN)JSOP_LIMIT); - LOAD_INTERRUPT_HANDLER(cx); - DO_OP(); case JSTRAP_RETURN: fp->rval = rval; ok = JS_TRUE; @@ -5432,9 +5505,15 @@ interrupt: cx->exception = rval; goto error; default:; + break; } + JS_ASSERT(status == JSTRAP_CONTINUE); LOAD_INTERRUPT_HANDLER(cx); - END_CASE(JSOP_TRAP) + JS_ASSERT(JSVAL_IS_INT(rval)); + op = (JSOp) JSVAL_TO_INT(rval); + JS_ASSERT((uintN)op < (uintN)JSOP_LIMIT); + DO_OP(); + } BEGIN_CASE(JSOP_ARGUMENTS) if (!js_GetArgsValue(cx, fp, &rval)) @@ -6172,7 +6251,7 @@ interrupt: goto error; } regs.sp -= 2; - END_CASE(JSOP_INITELEM); + END_CASE(JSOP_INITELEM) #if JS_HAS_SHARP_VARS BEGIN_CASE(JSOP_DEFSHARP) @@ -6219,15 +6298,11 @@ interrupt: END_CASE(JSOP_USESHARP) #endif /* JS_HAS_SHARP_VARS */ - /* No-ops for ease of decompilation and jit'ing. */ - EMPTY_CASE(JSOP_TRY) - EMPTY_CASE(JSOP_FINALLY) - BEGIN_CASE(JSOP_GOSUB) PUSH(JSVAL_FALSE); i = PTRDIFF(regs.pc, script->main, jsbytecode) + JSOP_GOSUB_LENGTH; - len = GET_JUMP_OFFSET(regs.pc); PUSH(INT_TO_JSVAL(i)); + len = GET_JUMP_OFFSET(regs.pc); END_VARLEN_CASE BEGIN_CASE(JSOP_GOSUBX) @@ -6482,9 +6557,6 @@ interrupt: regs.sp--; END_CASE(JSOP_ENDFILTER); - EMPTY_CASE(JSOP_STARTXML) - EMPTY_CASE(JSOP_STARTXMLEXPR) - BEGIN_CASE(JSOP_TOXML) rval = FETCH_OPND(-1); obj = js_ValueToXMLObject(cx, rval); @@ -6784,48 +6856,6 @@ interrupt: #if !JS_THREADED_INTERP } /* switch (op) */ - - advance_pc: - regs.pc += len; - -#ifdef DEBUG - if (tracefp) { - intN ndefs, n; - jsval *siter; - - /* - * op may be invalid here when a catch or finally handler jumps to - * advance_pc. - */ - op = (JSOp) regs.pc[-len]; - ndefs = js_CodeSpec[op].ndefs; - if (ndefs) { - if (op == JSOP_FORELEM && regs.sp[-1] == JSVAL_FALSE) - --ndefs; - for (n = -ndefs; n < 0; n++) { - char *bytes = js_DecompileValueGenerator(cx, n, regs.sp[n], - NULL); - if (bytes) { - fprintf(tracefp, "%s %s", - (n == -ndefs) ? " output:" : ",", - bytes); - JS_free(cx, bytes); - } - } - fprintf(tracefp, " @ %d\n", regs.sp - fp->spbase); - } - fprintf(tracefp, " stack: "); - for (siter = fp->spbase; siter < regs.sp; siter++) { - str = js_ValueToString(cx, *siter); - if (!str) - fputs("", tracefp); - else - js_FileEscapedString(tracefp, str, 0); - fputc(' ', tracefp); - } - fputc('\n', tracefp); - } -#endif /* DEBUG */ } #endif /* !JS_THREADED_INTERP */ diff --git a/js/src/jsinterp.h b/js/src/jsinterp.h index 7fb54660a749..3f8bdfe9bba7 100644 --- a/js/src/jsinterp.h +++ b/js/src/jsinterp.h @@ -507,6 +507,13 @@ js_OnUnknownMethod(JSContext *cx, jsval *vp); extern JSBool js_DoIncDec(JSContext *cx, const JSCodeSpec *cs, jsval *vp, jsval *vp2); +/* + * Opcode tracing helper. When len is not 0, cx->fp->regs->pc[-len] gives the + * previous opcode. + */ +extern void +js_TraceOpcode(JSContext *cx, jsint len); + /* * JS_OPMETER helper functions. */ diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index a9540166152c..e8ac435e8daa 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -88,6 +88,8 @@ #include "jsdtracef.h" #endif +#include "jsautooplen.h" + #ifdef JS_THREADSAFE #define NATIVE_DROP_PROPERTY js_DropProperty diff --git a/js/src/jsopcode.cpp b/js/src/jsopcode.cpp index cf0accc147d5..91e0f9e0fa7f 100644 --- a/js/src/jsopcode.cpp +++ b/js/src/jsopcode.cpp @@ -75,6 +75,14 @@ # include "jsnum.h" #endif +#include "jsautooplen.h" + +/* Verify JSOP_XXX_LENGTH constant definitions. */ +#define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \ + JS_STATIC_ASSERT(op##_LENGTH == length); +#include "jsopcode.tbl" +#undef OPDEF + static const char js_incop_strs[][3] = {"++", "--"}; const JSCodeSpec js_CodeSpec[] = { @@ -2152,14 +2160,6 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) todo = -2; break; - case JSOP_SWAP: - /* - * We don't generate this opcode currently, and previously we - * did not need to decompile it. If old, serialized bytecode - * uses it still, we should fall through and set todo = -2. - */ - /* FALL THROUGH */ - case JSOP_GOSUB: case JSOP_GOSUBX: /* @@ -4993,8 +4993,7 @@ DecompileExpression(JSContext *cx, JSScript *script, JSFunction *fun, /* None of these stack-writing ops generates novel values. */ JS_ASSERT(op != JSOP_CASE && op != JSOP_CASEX && - op != JSOP_DUP && op != JSOP_DUP2 && - op != JSOP_SWAP); + op != JSOP_DUP && op != JSOP_DUP2); /* * |this| could convert to a very long object initialiser, so cite it by @@ -5274,13 +5273,6 @@ ReconstructPCStack(JSContext *cx, JSScript *script, jsbytecode *pc, pcstack[pcdepth + 3] = pcstack[pcdepth + 1]; break; - case JSOP_SWAP: - JS_ASSERT(ndefs == 2); - pc2 = pcstack[pcdepth]; - pcstack[pcdepth] = pcstack[pcdepth + 1]; - pcstack[pcdepth + 1] = pc2; - break; - case JSOP_LEAVEBLOCKEXPR: /* * The decompiler wants to see [leaveblockexpr] on pcstack, not diff --git a/js/src/jsopcode.h b/js/src/jsopcode.h index 9e185e4c3b07..831b95fa9401 100644 --- a/js/src/jsopcode.h +++ b/js/src/jsopcode.h @@ -60,14 +60,6 @@ typedef enum JSOp { JSOP_LIMIT } JSOp; -typedef enum JSOpLength { -#define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \ - op##_LENGTH = length, -#include "jsopcode.tbl" -#undef OPDEF - JSOP_LIMIT_LENGTH -} JSOpLength; - /* * JS bytecode formats. */ diff --git a/js/src/jsopcode.tbl b/js/src/jsopcode.tbl index 7806e08e018f..f9ea46a03a5d 100644 --- a/js/src/jsopcode.tbl +++ b/js/src/jsopcode.tbl @@ -97,7 +97,7 @@ /* legend: op val name image len use def prec format */ /* Longstanding JavaScript bytecodes. */ -OPDEF(JSOP_NOP, 0, "nop", NULL, 1, 0, 0, 0, JOF_BYTE) +OPDEF(JSOP_INTERRUPT, 0, "interrupt", 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, 2, JOF_BYTE) OPDEF(JSOP_ENTERWITH, 3, "enterwith", NULL, 1, 1, 1, 0, JOF_BYTE|JOF_PARENHEAD) @@ -331,9 +331,9 @@ OPDEF(JSOP_TRY, 133,"try", NULL, 1, 0, 0, 0, JOF_BYTE) OPDEF(JSOP_FINALLY, 134,"finally", NULL, 1, 0, 0, 0, JOF_BYTE) /* - * Swap the top two stack elements. + * Generic nop for the decompiler. */ -OPDEF(JSOP_SWAP, 135,"swap", NULL, 1, 2, 2, 0, JOF_BYTE) +OPDEF(JSOP_NOP, 135,"nop", NULL, 1, 0, 0, 0, JOF_BYTE) /* * Bytecodes that avoid making an arguments object in most cases: diff --git a/js/src/jsxdrapi.h b/js/src/jsxdrapi.h index 3026b49ee215..68a45432af94 100644 --- a/js/src/jsxdrapi.h +++ b/js/src/jsxdrapi.h @@ -202,7 +202,7 @@ JS_XDRFindClassById(JSXDRState *xdr, uint32 id); * before deserialization of bytecode. If the saved version does not match * the current version, abort deserialization and invalidate the file. */ -#define JSXDR_BYTECODE_VERSION (0xb973c0de - 25) +#define JSXDR_BYTECODE_VERSION (0xb973c0de - 26) /* * Library-private functions. diff --git a/js/src/liveconnect/nsCLiveconnect.cpp b/js/src/liveconnect/nsCLiveconnect.cpp index 4adfc740142b..3c0c344fcfc2 100644 --- a/js/src/liveconnect/nsCLiveconnect.cpp +++ b/js/src/liveconnect/nsCLiveconnect.cpp @@ -192,8 +192,8 @@ AutoPushJSContext::AutoPushJSContext(nsISupports* aSecuritySupports, mFrame.callee = JS_GetFunctionObject(fun); mFrame.scopeChain = JS_GetParent(cx, mFrame.callee); mFrame.down = cx->fp; - mRegs.pc = script->code + script->length - - JSOP_STOP_LENGTH; + mRegs.pc = script->code + script->length - 1; + JS_ASSERT(static_cast(*mRegs.pc) == JSOP_STOP); mRegs.sp = NULL; mFrame.regs = &mRegs; cx->fp = &mFrame; diff --git a/js/src/rules.mk b/js/src/rules.mk index 4ab596f23a69..ad80ad0f449a 100644 --- a/js/src/rules.mk +++ b/js/src/rules.mk @@ -185,11 +185,9 @@ endif clean: rm -rf $(OBJS) $(GARBAGE) - @cd fdlibm; $(MAKE) -f Makefile.ref clean clobber: rm -rf $(OBJS) $(TARGETS) $(DEPENDENCIES) - @cd fdlibm; $(MAKE) -f Makefile.ref clobber tar: tar cvf $(TARNAME) $(TARFILES) From 7a2a078f0f46170ee0fbc2493c587dc8b5cfe349 Mon Sep 17 00:00:00 2001 From: Igor Bukanov Date: Fri, 20 Jun 2008 11:46:36 +0200 Subject: [PATCH 34/66] Backed out changeset 97977f224aff due to build breakage --- js/src/Makefile.in | 17 +- js/src/Makefile.ref | 34 +-- js/src/jsdbgapi.cpp | 2 - js/src/jsemit.cpp | 2 - js/src/jsinterp.cpp | 410 ++++++++++++-------------- js/src/jsinterp.h | 7 - js/src/jsobj.cpp | 2 - js/src/jsopcode.cpp | 26 +- js/src/jsopcode.h | 8 + js/src/jsopcode.tbl | 6 +- js/src/jsxdrapi.h | 2 +- js/src/liveconnect/nsCLiveconnect.cpp | 4 +- js/src/rules.mk | 2 + 13 files changed, 244 insertions(+), 278 deletions(-) diff --git a/js/src/Makefile.in b/js/src/Makefile.in index 8a4d75809181..d0d0e922fe7a 100644 --- a/js/src/Makefile.in +++ b/js/src/Makefile.in @@ -242,10 +242,6 @@ JSJAVA_CFLAGS = \ HOST_SIMPLE_PROGRAMS += host_jskwgen$(HOST_BIN_SUFFIX) GARBAGE += jsautokw.h host_jskwgen$(HOST_BIN_SUFFIX) - -HOST_SIMPLE_PROGRAMS += host_jsoplengen$(HOST_BIN_SUFFIX) -GARBAGE += jsautooplen.h host_jsoplengen$(HOST_BIN_SUFFIX) - USE_HOST_CXX = 1 ifdef HAVE_DTRACE @@ -449,23 +445,18 @@ jscpucfg$(HOST_BIN_SUFFIX): jscpucfg.cpp Makefile.in endif endif -# Extra dependancies and rules for auto-generated headers +# Extra dependancies and rules for keyword switch code +jsscan.$(OBJ_SUFFIX): jsautokw.h jskeyword.tbl + host_jskwgen.$(OBJ_SUFFIX): jsconfig.h jskeyword.tbl jsautokw.h: host_jskwgen$(HOST_BIN_SUFFIX) ./host_jskwgen$(HOST_BIN_SUFFIX) $@ -host_jsoplengen.$(OBJ_SUFFIX): jsopcode.tbl - -jsautooplen.h: host_jsoplengen$(HOST_BIN_SUFFIX) - ./host_jsoplengen$(HOST_BIN_SUFFIX) $@ - -# Force auto-header generation before compiling any source that may use them -$(CPPSRCS:%.cpp=%.$(OBJ_SUFFIX)): jsautokw.h jsautooplen.h - ifdef HAVE_DTRACE javascript-trace.h: $(srcdir)/javascript-trace.d dtrace -h -s $(srcdir)/javascript-trace.d -o javascript-trace.h.in sed 's/if _DTRACE_VERSION/ifdef INCLUDE_MOZILLA_DTRACE/' \ javascript-trace.h.in > javascript-trace.h endif + diff --git a/js/src/Makefile.ref b/js/src/Makefile.ref index 520e801d71ca..a6ada0ca6cfa 100644 --- a/js/src/Makefile.ref +++ b/js/src/Makefile.ref @@ -277,39 +277,39 @@ nsinstall-target: cd ../../config; $(MAKE) OBJDIR=$(OBJDIR) OBJDIR_NAME=$(OBJDIR) # -# Automatic header generation +# Rules for keyword switch generation # -AUTO_HEADERS = $(OBJDIR)/jsautokw.h $(OBJDIR)/jsautooplen.h +GARBAGE += $(OBJDIR)/jsautokw.h $(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX) +GARBAGE += $(OBJDIR)/jskwgen.$(OBJ_SUFFIX) -$(OBJDIR)/jsautokw.h: jskeyword.tbl +$(OBJDIR)/jsscan.$(OBJ_SUFFIX): $(OBJDIR)/jsautokw.h jskeyword.tbl -$(OBJDIR)/jsautooplen.h: jsopcode.tbl +$(OBJDIR)/jskwgen.$(OBJ_SUFFIX): jskwgen.cpp jskeyword.tbl -GARBAGE += $(AUTO_HEADERS) -GARBAGE += $(AUTO_HEADERS:$(OBJDIR)/jsauto%.h=$(OBJDIR)/js%gen$(HOST_BIN_SUFFIX)) +$(OBJDIR)/jsautokw.h: $(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX) jskeyword.tbl + $(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX) $@ ifdef USE_MSVC -GARBAGE += $(AUTO_HEADERS:$(OBJDIR)/jsauto%.h=$(OBJDIR)/js%gen.obj) - -$(AUTO_HEADERS): $(OBJDIR)/jsauto%.h: js%gen.cpp +$(OBJDIR)/jskwgen.obj: jskwgen.cpp jskeyword.tbl @$(MAKE_OBJDIR) $(CXX) -Fo$(OBJDIR)/ -c $(CFLAGS) $< - link.exe -out:"$(OBJDIR)/js$*gen$(HOST_BIN_SUFFIX)" $(EXE_LINK_FLAGS) $(OBJDIR)/js$*gen.obj - $(OBJDIR)/js$*gen$(HOST_BIN_SUFFIX) $@ + +$(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX): $(OBJDIR)/jskwgen.$(OBJ_SUFFIX) + link.exe -out:"$@" $(EXE_LINK_FLAGS) $^ + else -$(AUTO_HEADERS): $(OBJDIR)/jsauto%.h: js%gen.cpp +$(OBJDIR)/jskwgen.o: jskwgen.cpp jskeyword.tbl @$(MAKE_OBJDIR) - $(CXX) -o $(OBJDIR)/js$*gen$(HOST_BIN_SUFFIX) $(CFLAGS) $(LDFLAGS) $< - $(OBJDIR)/js$*gen$(HOST_BIN_SUFFIX) $@ + $(CXX) -o $@ -c $(CFLAGS) $< + +$(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX): $(OBJDIR)/jskwgen.$(OBJ_SUFFIX) + $(CXX) -o $@ $(CFLAGS) $(LDFLAGS) $^ endif -# force creation of autoheaders before compiling any source that may use them -$(LIB_OBJS) : $(AUTO_HEADERS) - # # JS shell executable # diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index 7309ebbabf53..311d7cc06edd 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -62,8 +62,6 @@ #include "jsscript.h" #include "jsstr.h" -#include "jsautooplen.h" - typedef struct JSTrap { JSCList links; JSScript *script; diff --git a/js/src/jsemit.cpp b/js/src/jsemit.cpp index 638ade9eef55..daff25c9e53a 100644 --- a/js/src/jsemit.cpp +++ b/js/src/jsemit.cpp @@ -66,8 +66,6 @@ #include "jsscope.h" #include "jsscript.h" -#include "jsautooplen.h" - /* Allocation chunk counts, must be powers of two in general. */ #define BYTECODE_CHUNK 256 /* code allocation increment */ #define SRCNOTE_CHUNK 64 /* initial srcnote allocation increment */ diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 9bc14c21e7af..3c58cabee4b7 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -77,8 +77,6 @@ #include "jsxml.h" #endif -#include "jsautooplen.h" - #ifdef js_invoke_c__ uint32 @@ -2076,77 +2074,6 @@ js_DoIncDec(JSContext *cx, const JSCodeSpec *cs, jsval *vp, jsval *vp2) return JS_TRUE; } -#ifdef DEBUG - -void -js_TraceOpcode(JSContext *cx, jsint len) -{ - FILE *tracefp; - JSStackFrame *fp; - JSFrameRegs *regs; - JSOp prevop; - intN ndefs, n, nuses; - jsval *siter; - JSString *str; - JSOp op; - - tracefp = (FILE *) cx->tracefp; - JS_ASSERT(tracefp); - fp = cx->fp; - regs = fp->regs; - if (len != 0) { - prevop = (JSOp) regs->pc[-len]; - ndefs = js_CodeSpec[prevop].ndefs; - if (ndefs != 0) { - if (prevop == JSOP_FORELEM && regs->sp[-1] == JSVAL_FALSE) - --ndefs; - for (n = -ndefs; n < 0; n++) { - char *bytes = js_DecompileValueGenerator(cx, n, regs->sp[n], - NULL); - if (bytes) { - fprintf(tracefp, "%s %s", - (n == -ndefs) ? " output:" : ",", - bytes); - JS_free(cx, bytes); - } - } - fprintf(tracefp, " @ %d\n", regs->sp - fp->spbase); - } - fprintf(tracefp, " stack: "); - for (siter = fp->spbase; siter < regs->sp; siter++) { - str = js_ValueToString(cx, *siter); - if (!str) - fputs("", tracefp); - else - js_FileEscapedString(tracefp, str, 0); - fputc(' ', tracefp); - } - fputc('\n', tracefp); - } - - fprintf(tracefp, "%4u: ", js_PCToLineNumber(cx, fp->script, regs->pc)); - js_Disassemble1(cx, fp->script, regs->pc, - PTRDIFF(regs->pc, fp->script->code, jsbytecode), - JS_FALSE, tracefp); - op = (JSOp) *regs->pc; - nuses = js_CodeSpec[op].nuses; - if (nuses != 0) { - for (n = -nuses; n < 0; n++) { - char *bytes = js_DecompileValueGenerator(cx, n, regs->sp[n], - NULL); - if (bytes) { - fprintf(tracefp, "%s %s", - (n == -nuses) ? " inputs:" : ",", - bytes); - JS_free(cx, bytes); - } - } - fprintf(tracefp, " @ %d\n", regs->sp - fp->spbase); - } -} - -#endif /* DEBUG */ - #ifdef JS_OPMETER # include @@ -2498,13 +2425,6 @@ JS_STATIC_ASSERT(!CAN_DO_FAST_INC_DEC(INT_TO_JSVAL(JSVAL_INT_MAX))); # endif #endif - -/* - * Interpreter assumes the following to implement condition-free interrupt - * implementation when !JS_THREADED_INTERP. - */ -JS_STATIC_ASSERT(JSOP_INTERRUPT == 0); - /* * Ensure that the intrepreter switch can close call-bytecode cases in the * same way as non-call bytecodes. @@ -2542,6 +2462,7 @@ js_Interpret(JSContext *cx) JSFrameRegs regs; JSObject *obj, *obj2, *parent; JSBool ok, cond; + JSTrapHandler interruptHandler; jsint len; jsbytecode *endpc, *pc2; JSOp op, op2; @@ -2560,11 +2481,8 @@ js_Interpret(JSContext *cx) JSClass *clasp; JSFunction *fun; JSType type; -#if JS_THREADED_INTERP - register const void * const *jumpTable; -#else - register uint32 switchMask; - uintN switchOp; +#if !JS_THREADED_INTERP && defined DEBUG + FILE *tracefp = NULL; #endif #if JS_HAS_EXPORT_IMPORT JSIdArray *ida; @@ -2584,68 +2502,42 @@ js_Interpret(JSContext *cx) #endif #if JS_THREADED_INTERP - static const void *const normalJumpTable[] = { + static void *normalJumpTable[] = { # define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \ JS_EXTENSION &&L_##op, # include "jsopcode.tbl" # undef OPDEF }; - static const void *const interruptJumpTable[] = { + static void *interruptJumpTable[] = { # define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \ - JS_EXTENSION &&L_JSOP_INTERRUPT, + JS_EXTENSION &&interrupt, # include "jsopcode.tbl" # undef OPDEF }; + register void **jumpTable = normalJumpTable; + METER_OP_INIT(op); /* to nullify first METER_OP_PAIR */ # define DO_OP() JS_EXTENSION_(goto *jumpTable[op]) -# define DO_NEXT_OP(n) JS_BEGIN_MACRO \ - METER_OP_PAIR(op, regs.pc[n]); \ - op = (JSOp) *(regs.pc += (n)); \ - DO_OP(); \ - JS_END_MACRO - +# define DO_NEXT_OP(n) do { METER_OP_PAIR(op, regs.pc[n]); \ + op = (JSOp) *(regs.pc += (n)); \ + DO_OP(); } while (0) # define BEGIN_CASE(OP) L_##OP: # define END_CASE(OP) DO_NEXT_OP(OP##_LENGTH); # define END_VARLEN_CASE DO_NEXT_OP(len); -# define ADD_EMPTY_CASE(OP) BEGIN_CASE(OP) \ - JS_ASSERT(js_CodeSpec[OP].length == 1); \ - op = (JSOp) *++regs.pc; \ - DO_OP(); - -# define END_EMPTY_CASES - -#else /* !JS_THREADED_INTERP */ - +# define EMPTY_CASE(OP) BEGIN_CASE(OP) op = (JSOp) *++regs.pc; DO_OP(); +#else # define DO_OP() goto do_op -# define DO_NEXT_OP(n) JS_BEGIN_MACRO \ - JS_ASSERT((n) == len); \ - goto advance_pc; \ - JS_END_MACRO - +# define DO_NEXT_OP(n) goto advance_pc # define BEGIN_CASE(OP) case OP: -# define END_CASE(OP) END_CASE_LEN(OP##_LENGTH) -# define END_CASE_LEN(n) END_CASE_LENX(n) -# define END_CASE_LENX(n) END_CASE_LEN##n - -/* - * To share the code for all len == 1 cases we use the specialized label with - * code that falls through to advance_pc: . - */ -# define END_CASE_LEN1 goto advance_pc_by_one; -# define END_CASE_LEN2 len = 2; goto advance_pc; -# define END_CASE_LEN3 len = 3; goto advance_pc; -# define END_CASE_LEN4 len = 4; goto advance_pc; -# define END_CASE_LEN5 len = 5; goto advance_pc; -# define END_VARLEN_CASE goto advance_pc; -# define ADD_EMPTY_CASE(OP) BEGIN_CASE(OP) -# define END_EMPTY_CASES goto advance_pc_by_one; - +# define END_CASE(OP) break; +# define END_VARLEN_CASE break; +# define EMPTY_CASE(OP) BEGIN_CASE(OP) END_CASE(OP) #endif - /* Check for too deep of a native thread stack. */ + /* Check for too deep a C stack. */ JS_CHECK_RECURSION(cx, return JS_FALSE); rt = cx->runtime; @@ -2724,15 +2616,18 @@ js_Interpret(JSContext *cx) * the compiler can keep it in a register when it is non-null. */ #if JS_THREADED_INTERP -# define LOAD_INTERRUPT_HANDLER(cx) \ - ((void) (jumpTable = (cx)->debugHooks->interruptHandler \ - ? interruptJumpTable \ - : normalJumpTable)) +# define LOAD_JUMP_TABLE() \ + (jumpTable = interruptHandler ? interruptJumpTable : normalJumpTable) #else -# define LOAD_INTERRUPT_HANDLER(cx) \ - ((void) (switchMask = (cx)->debugHooks->interruptHandler ? 0 : 255)) +# define LOAD_JUMP_TABLE() ((void) 0) #endif +#define LOAD_INTERRUPT_HANDLER(cx) \ + JS_BEGIN_MACRO \ + interruptHandler = (cx)->debugHooks->interruptHandler; \ + LOAD_JUMP_TABLE(); \ + JS_END_MACRO + LOAD_INTERRUPT_HANDLER(cx); /* @@ -2780,89 +2675,107 @@ js_Interpret(JSContext *cx) } } - /* - * It is important that "op" be initialized before calling DO_OP because - * it is possible for "op" to be specially assigned during the normal - * processing of an opcode while looping. We rely on DO_NEXT_OP to manage - * "op" correctly in all other cases. - */ - len = 0; - DO_NEXT_OP(len); - #if JS_THREADED_INTERP + /* - * This is a loop, but it does not look like a loop. The loop-closing - * jump is distributed throughout goto *jumpTable[op] inside of DO_OP. - * When interrupts are enabled, jumpTable is set to interruptJumpTable - * where all jumps point to the JSOP_INTERRUPT case. The latter, after - * calling the interrupt handler, dispatches through normalJumpTable to - * continue the normal bytecode processing. + * This is a loop, but it does not look like a loop. The loop-closing + * jump is distributed throughout interruptJumpTable, and comes back to + * the interrupt label. The dispatch on op is through normalJumpTable. + * The trick is LOAD_INTERRUPT_HANDLER setting jumpTable appropriately. + * + * It is important that "op" be initialized before the interrupt label + * because it is possible for "op" to be specially assigned during the + * normally processing of an opcode while looping (in particular, this + * happens in JSOP_TRAP while debugging). We rely on DO_NEXT_OP to + * correctly manage "op" in all other cases. */ -#else + op = (JSOp) *regs.pc; + if (interruptHandler) { +interrupt: + switch (interruptHandler(cx, script, regs.pc, &rval, + cx->debugHooks->interruptHandlerData)) { + case JSTRAP_ERROR: + goto error; + case JSTRAP_CONTINUE: + break; + case JSTRAP_RETURN: + fp->rval = rval; + ok = JS_TRUE; + goto forced_return; + case JSTRAP_THROW: + cx->throwing = JS_TRUE; + cx->exception = rval; + goto error; + default:; + } + LOAD_INTERRUPT_HANDLER(cx); + } + + JS_ASSERT((uintN)op < (uintN)JSOP_LIMIT); + JS_EXTENSION_(goto *normalJumpTable[op]); + +#else /* !JS_THREADED_INTERP */ + for (;;) { - advance_pc_by_one: - JS_ASSERT(js_CodeSpec[op].length == 1); - len = 1; - advance_pc: - regs.pc += len; op = (JSOp) *regs.pc; -#ifdef DEBUG - if (cx->tracefp) - js_TraceOpcode(cx, len); -#endif - do_op: - switchOp = op & switchMask; - do_switch: - switch (switchOp) { -#endif /* !JS_THREADED_INTERP */ + len = js_CodeSpec[op].length; - BEGIN_CASE(JSOP_INTERRUPT) - { - JSTrapHandler handler; +#ifdef DEBUG + tracefp = (FILE *) cx->tracefp; + if (tracefp) { + intN nuses, n; - handler = cx->debugHooks->interruptHandler; - if (handler) { - switch (handler(cx, script, regs.pc, &rval, - cx->debugHooks->interruptHandlerData)) { - case JSTRAP_ERROR: - goto error; - case JSTRAP_CONTINUE: - break; - case JSTRAP_RETURN: - fp->rval = rval; - ok = JS_TRUE; - goto forced_return; - case JSTRAP_THROW: - cx->throwing = JS_TRUE; - cx->exception = rval; - goto error; - default:; + fprintf(tracefp, "%4u: ", js_PCToLineNumber(cx, script, regs.pc)); + js_Disassemble1(cx, script, regs.pc, + PTRDIFF(regs.pc, script->code, jsbytecode), + JS_FALSE, tracefp); + nuses = js_CodeSpec[op].nuses; + if (nuses) { + for (n = -nuses; n < 0; n++) { + char *bytes = js_DecompileValueGenerator(cx, n, regs.sp[n], + NULL); + if (bytes) { + fprintf(tracefp, "%s %s", + (n == -nuses) ? " inputs:" : ",", + bytes); + JS_free(cx, bytes); + } } + fprintf(tracefp, " @ %d\n", regs.sp - fp->spbase); + } + } +#endif /* DEBUG */ + + if (interruptHandler) { + switch (interruptHandler(cx, script, regs.pc, &rval, + cx->debugHooks->interruptHandlerData)) { + case JSTRAP_ERROR: + goto error; + case JSTRAP_CONTINUE: + break; + case JSTRAP_RETURN: + fp->rval = rval; + ok = JS_TRUE; + goto forced_return; + case JSTRAP_THROW: + cx->throwing = JS_TRUE; + cx->exception = rval; + goto error; + default:; } LOAD_INTERRUPT_HANDLER(cx); + } -#if JS_THREADED_INTERP - JS_EXTENSION_(goto *normalJumpTable[op]); -#else - switchOp = op; - goto do_switch; -#endif - } + switch (op) { - /* No-ops for ease of decompilation. */ - ADD_EMPTY_CASE(JSOP_NOP) - ADD_EMPTY_CASE(JSOP_GROUP) - ADD_EMPTY_CASE(JSOP_CONDSWITCH) - ADD_EMPTY_CASE(JSOP_TRY) - ADD_EMPTY_CASE(JSOP_FINALLY) -#if JS_HAS_XML_SUPPORT - ADD_EMPTY_CASE(JSOP_STARTXML) - ADD_EMPTY_CASE(JSOP_STARTXMLEXPR) -#endif - END_EMPTY_CASES +#endif /* !JS_THREADED_INTERP */ - /* ADD_EMPTY_CASE is not used here as JSOP_LINENO_LENGTH == 3. */ + EMPTY_CASE(JSOP_NOP) + + EMPTY_CASE(JSOP_GROUP) + + /* EMPTY_CASE is not used here as JSOP_LINENO_LENGTH == 3. */ BEGIN_CASE(JSOP_LINENO) END_CASE(JSOP_LINENO) @@ -2897,6 +2810,12 @@ js_Interpret(JSContext *cx) #endif END_CASE(JSOP_POPN) + BEGIN_CASE(JSOP_SWAP) + rtmp = regs.sp[-1]; + regs.sp[-1] = regs.sp[-2]; + regs.sp[-2] = rtmp; + END_CASE(JSOP_SWAP) + BEGIN_CASE(JSOP_SETRVAL) BEGIN_CASE(JSOP_POPV) ASSERT_NOT_THROWING(cx); @@ -4220,6 +4139,7 @@ js_Interpret(JSContext *cx) i = 0; COMPUTE_THIS(cx, fp, obj); PUSH(JSVAL_NULL); + len = JSOP_GETTHISPROP_LENGTH; goto do_getprop_with_obj; #undef COMPUTE_THIS @@ -4229,6 +4149,7 @@ js_Interpret(JSContext *cx) slot = GET_ARGNO(regs.pc); JS_ASSERT(slot < fp->fun->nargs); PUSH_OPND(fp->argv[slot]); + len = JSOP_GETARGPROP_LENGTH; goto do_getprop_body; BEGIN_CASE(JSOP_GETVARPROP) @@ -4236,6 +4157,7 @@ js_Interpret(JSContext *cx) slot = GET_VARNO(regs.pc); JS_ASSERT(slot < fp->fun->u.i.nvars); PUSH_OPND(fp->vars[slot]); + len = JSOP_GETVARPROP_LENGTH; goto do_getprop_body; BEGIN_CASE(JSOP_GETLOCALPROP) @@ -4243,11 +4165,13 @@ js_Interpret(JSContext *cx) slot = GET_UINT16(regs.pc); JS_ASSERT(slot < script->depth); PUSH_OPND(fp->spbase[slot]); + len = JSOP_GETLOCALPROP_LENGTH; goto do_getprop_body; BEGIN_CASE(JSOP_GETPROP) BEGIN_CASE(JSOP_GETXPROP) i = 0; + len = JSOP_GETPROP_LENGTH; do_getprop_body: lval = FETCH_OPND(-1); @@ -4293,8 +4217,6 @@ js_Interpret(JSContext *cx) } while (0); STORE_OPND(-1, rval); - JS_ASSERT(JSOP_GETPROP_LENGTH + i == js_CodeSpec[op].length); - len = JSOP_GETPROP_LENGTH + i; END_VARLEN_CASE BEGIN_CASE(JSOP_LENGTH) @@ -4319,7 +4241,8 @@ js_Interpret(JSContext *cx) goto error; } } else { - i = -2; + i = -1; + len = JSOP_LENGTH_LENGTH; goto do_getprop_with_lval; } END_CASE(JSOP_LENGTH) @@ -5073,12 +4996,12 @@ js_Interpret(JSContext *cx) goto error; if (!prop) { /* Kludge to allow (typeof foo == "undefined") tests. */ + len = JSOP_NAME_LENGTH; endpc = script->code + script->length; - for (pc2 = regs.pc + JSOP_NAME_LENGTH; pc2 < endpc; pc2++) { + for (pc2 = regs.pc + len; pc2 < endpc; pc2++) { op2 = (JSOp)*pc2; if (op2 == JSOP_TYPEOF) { PUSH_OPND(JSVAL_VOID); - len = JSOP_NAME_LENGTH; DO_NEXT_OP(len); } if (op2 != JSOP_GROUP) @@ -5415,6 +5338,8 @@ js_Interpret(JSContext *cx) : GET_JUMPX_OFFSET(pc2); END_VARLEN_CASE + EMPTY_CASE(JSOP_CONDSWITCH) + #if JS_HAS_EXPORT_IMPORT BEGIN_CASE(JSOP_EXPORTALL) obj = fp->varobj; @@ -5489,13 +5414,15 @@ js_Interpret(JSContext *cx) #endif /* JS_HAS_EXPORT_IMPORT */ BEGIN_CASE(JSOP_TRAP) - { - JSTrapStatus status; - - status = JS_HandleTrap(cx, script, regs.pc, &rval); - switch (status) { + switch (JS_HandleTrap(cx, script, regs.pc, &rval)) { case JSTRAP_ERROR: goto error; + case JSTRAP_CONTINUE: + JS_ASSERT(JSVAL_IS_INT(rval)); + op = (JSOp) JSVAL_TO_INT(rval); + JS_ASSERT((uintN)op < (uintN)JSOP_LIMIT); + LOAD_INTERRUPT_HANDLER(cx); + DO_OP(); case JSTRAP_RETURN: fp->rval = rval; ok = JS_TRUE; @@ -5505,15 +5432,9 @@ js_Interpret(JSContext *cx) cx->exception = rval; goto error; default:; - break; } - JS_ASSERT(status == JSTRAP_CONTINUE); LOAD_INTERRUPT_HANDLER(cx); - JS_ASSERT(JSVAL_IS_INT(rval)); - op = (JSOp) JSVAL_TO_INT(rval); - JS_ASSERT((uintN)op < (uintN)JSOP_LIMIT); - DO_OP(); - } + END_CASE(JSOP_TRAP) BEGIN_CASE(JSOP_ARGUMENTS) if (!js_GetArgsValue(cx, fp, &rval)) @@ -6251,7 +6172,7 @@ js_Interpret(JSContext *cx) goto error; } regs.sp -= 2; - END_CASE(JSOP_INITELEM) + END_CASE(JSOP_INITELEM); #if JS_HAS_SHARP_VARS BEGIN_CASE(JSOP_DEFSHARP) @@ -6298,11 +6219,15 @@ js_Interpret(JSContext *cx) END_CASE(JSOP_USESHARP) #endif /* JS_HAS_SHARP_VARS */ + /* No-ops for ease of decompilation and jit'ing. */ + EMPTY_CASE(JSOP_TRY) + EMPTY_CASE(JSOP_FINALLY) + BEGIN_CASE(JSOP_GOSUB) PUSH(JSVAL_FALSE); i = PTRDIFF(regs.pc, script->main, jsbytecode) + JSOP_GOSUB_LENGTH; - PUSH(INT_TO_JSVAL(i)); len = GET_JUMP_OFFSET(regs.pc); + PUSH(INT_TO_JSVAL(i)); END_VARLEN_CASE BEGIN_CASE(JSOP_GOSUBX) @@ -6557,6 +6482,9 @@ js_Interpret(JSContext *cx) regs.sp--; END_CASE(JSOP_ENDFILTER); + EMPTY_CASE(JSOP_STARTXML) + EMPTY_CASE(JSOP_STARTXMLEXPR) + BEGIN_CASE(JSOP_TOXML) rval = FETCH_OPND(-1); obj = js_ValueToXMLObject(cx, rval); @@ -6856,6 +6784,48 @@ js_Interpret(JSContext *cx) #if !JS_THREADED_INTERP } /* switch (op) */ + + advance_pc: + regs.pc += len; + +#ifdef DEBUG + if (tracefp) { + intN ndefs, n; + jsval *siter; + + /* + * op may be invalid here when a catch or finally handler jumps to + * advance_pc. + */ + op = (JSOp) regs.pc[-len]; + ndefs = js_CodeSpec[op].ndefs; + if (ndefs) { + if (op == JSOP_FORELEM && regs.sp[-1] == JSVAL_FALSE) + --ndefs; + for (n = -ndefs; n < 0; n++) { + char *bytes = js_DecompileValueGenerator(cx, n, regs.sp[n], + NULL); + if (bytes) { + fprintf(tracefp, "%s %s", + (n == -ndefs) ? " output:" : ",", + bytes); + JS_free(cx, bytes); + } + } + fprintf(tracefp, " @ %d\n", regs.sp - fp->spbase); + } + fprintf(tracefp, " stack: "); + for (siter = fp->spbase; siter < regs.sp; siter++) { + str = js_ValueToString(cx, *siter); + if (!str) + fputs("", tracefp); + else + js_FileEscapedString(tracefp, str, 0); + fputc(' ', tracefp); + } + fputc('\n', tracefp); + } +#endif /* DEBUG */ } #endif /* !JS_THREADED_INTERP */ diff --git a/js/src/jsinterp.h b/js/src/jsinterp.h index 3f8bdfe9bba7..7fb54660a749 100644 --- a/js/src/jsinterp.h +++ b/js/src/jsinterp.h @@ -507,13 +507,6 @@ js_OnUnknownMethod(JSContext *cx, jsval *vp); extern JSBool js_DoIncDec(JSContext *cx, const JSCodeSpec *cs, jsval *vp, jsval *vp2); -/* - * Opcode tracing helper. When len is not 0, cx->fp->regs->pc[-len] gives the - * previous opcode. - */ -extern void -js_TraceOpcode(JSContext *cx, jsint len); - /* * JS_OPMETER helper functions. */ diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index e8ac435e8daa..a9540166152c 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -88,8 +88,6 @@ #include "jsdtracef.h" #endif -#include "jsautooplen.h" - #ifdef JS_THREADSAFE #define NATIVE_DROP_PROPERTY js_DropProperty diff --git a/js/src/jsopcode.cpp b/js/src/jsopcode.cpp index 91e0f9e0fa7f..cf0accc147d5 100644 --- a/js/src/jsopcode.cpp +++ b/js/src/jsopcode.cpp @@ -75,14 +75,6 @@ # include "jsnum.h" #endif -#include "jsautooplen.h" - -/* Verify JSOP_XXX_LENGTH constant definitions. */ -#define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \ - JS_STATIC_ASSERT(op##_LENGTH == length); -#include "jsopcode.tbl" -#undef OPDEF - static const char js_incop_strs[][3] = {"++", "--"}; const JSCodeSpec js_CodeSpec[] = { @@ -2160,6 +2152,14 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) todo = -2; break; + case JSOP_SWAP: + /* + * We don't generate this opcode currently, and previously we + * did not need to decompile it. If old, serialized bytecode + * uses it still, we should fall through and set todo = -2. + */ + /* FALL THROUGH */ + case JSOP_GOSUB: case JSOP_GOSUBX: /* @@ -4993,7 +4993,8 @@ DecompileExpression(JSContext *cx, JSScript *script, JSFunction *fun, /* None of these stack-writing ops generates novel values. */ JS_ASSERT(op != JSOP_CASE && op != JSOP_CASEX && - op != JSOP_DUP && op != JSOP_DUP2); + op != JSOP_DUP && op != JSOP_DUP2 && + op != JSOP_SWAP); /* * |this| could convert to a very long object initialiser, so cite it by @@ -5273,6 +5274,13 @@ ReconstructPCStack(JSContext *cx, JSScript *script, jsbytecode *pc, pcstack[pcdepth + 3] = pcstack[pcdepth + 1]; break; + case JSOP_SWAP: + JS_ASSERT(ndefs == 2); + pc2 = pcstack[pcdepth]; + pcstack[pcdepth] = pcstack[pcdepth + 1]; + pcstack[pcdepth + 1] = pc2; + break; + case JSOP_LEAVEBLOCKEXPR: /* * The decompiler wants to see [leaveblockexpr] on pcstack, not diff --git a/js/src/jsopcode.h b/js/src/jsopcode.h index 831b95fa9401..9e185e4c3b07 100644 --- a/js/src/jsopcode.h +++ b/js/src/jsopcode.h @@ -60,6 +60,14 @@ typedef enum JSOp { JSOP_LIMIT } JSOp; +typedef enum JSOpLength { +#define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \ + op##_LENGTH = length, +#include "jsopcode.tbl" +#undef OPDEF + JSOP_LIMIT_LENGTH +} JSOpLength; + /* * JS bytecode formats. */ diff --git a/js/src/jsopcode.tbl b/js/src/jsopcode.tbl index f9ea46a03a5d..7806e08e018f 100644 --- a/js/src/jsopcode.tbl +++ b/js/src/jsopcode.tbl @@ -97,7 +97,7 @@ /* legend: op val name image len use def prec format */ /* Longstanding JavaScript bytecodes. */ -OPDEF(JSOP_INTERRUPT, 0, "interrupt", NULL, 1, 0, 0, 0, JOF_BYTE) +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, 2, JOF_BYTE) OPDEF(JSOP_ENTERWITH, 3, "enterwith", NULL, 1, 1, 1, 0, JOF_BYTE|JOF_PARENHEAD) @@ -331,9 +331,9 @@ OPDEF(JSOP_TRY, 133,"try", NULL, 1, 0, 0, 0, JOF_BYTE) OPDEF(JSOP_FINALLY, 134,"finally", NULL, 1, 0, 0, 0, JOF_BYTE) /* - * Generic nop for the decompiler. + * Swap the top two stack elements. */ -OPDEF(JSOP_NOP, 135,"nop", NULL, 1, 0, 0, 0, JOF_BYTE) +OPDEF(JSOP_SWAP, 135,"swap", NULL, 1, 2, 2, 0, JOF_BYTE) /* * Bytecodes that avoid making an arguments object in most cases: diff --git a/js/src/jsxdrapi.h b/js/src/jsxdrapi.h index 68a45432af94..3026b49ee215 100644 --- a/js/src/jsxdrapi.h +++ b/js/src/jsxdrapi.h @@ -202,7 +202,7 @@ JS_XDRFindClassById(JSXDRState *xdr, uint32 id); * before deserialization of bytecode. If the saved version does not match * the current version, abort deserialization and invalidate the file. */ -#define JSXDR_BYTECODE_VERSION (0xb973c0de - 26) +#define JSXDR_BYTECODE_VERSION (0xb973c0de - 25) /* * Library-private functions. diff --git a/js/src/liveconnect/nsCLiveconnect.cpp b/js/src/liveconnect/nsCLiveconnect.cpp index 3c0c344fcfc2..4adfc740142b 100644 --- a/js/src/liveconnect/nsCLiveconnect.cpp +++ b/js/src/liveconnect/nsCLiveconnect.cpp @@ -192,8 +192,8 @@ AutoPushJSContext::AutoPushJSContext(nsISupports* aSecuritySupports, mFrame.callee = JS_GetFunctionObject(fun); mFrame.scopeChain = JS_GetParent(cx, mFrame.callee); mFrame.down = cx->fp; - mRegs.pc = script->code + script->length - 1; - JS_ASSERT(static_cast(*mRegs.pc) == JSOP_STOP); + mRegs.pc = script->code + script->length + - JSOP_STOP_LENGTH; mRegs.sp = NULL; mFrame.regs = &mRegs; cx->fp = &mFrame; diff --git a/js/src/rules.mk b/js/src/rules.mk index ad80ad0f449a..4ab596f23a69 100644 --- a/js/src/rules.mk +++ b/js/src/rules.mk @@ -185,9 +185,11 @@ endif clean: rm -rf $(OBJS) $(GARBAGE) + @cd fdlibm; $(MAKE) -f Makefile.ref clean clobber: rm -rf $(OBJS) $(TARGETS) $(DEPENDENCIES) + @cd fdlibm; $(MAKE) -f Makefile.ref clobber tar: tar cvf $(TARNAME) $(TARFILES) From 79c9e309643fd32f10b48532ce3ea0e4ecaa2ec2 Mon Sep 17 00:00:00 2001 From: Igor Bukanov Date: Fri, 20 Jun 2008 11:55:49 +0200 Subject: [PATCH 35/66] [Bug 433382] More efficient interpreter switch when computed goto is not available. r=brendan --- js/src/Makefile.in | 17 +- js/src/Makefile.ref | 34 +-- js/src/jsdbgapi.cpp | 2 + js/src/jsemit.cpp | 2 + js/src/jsinterp.cpp | 416 ++++++++++++++------------ js/src/jsinterp.h | 7 + js/src/jsobj.cpp | 2 + js/src/jsopcode.cpp | 26 +- js/src/jsopcode.h | 8 - js/src/jsopcode.tbl | 6 +- js/src/jsoplengen.cpp | 121 ++++++++ js/src/jsxdrapi.h | 2 +- js/src/liveconnect/nsCLiveconnect.cpp | 4 +- js/src/rules.mk | 2 - 14 files changed, 402 insertions(+), 247 deletions(-) create mode 100644 js/src/jsoplengen.cpp diff --git a/js/src/Makefile.in b/js/src/Makefile.in index d0d0e922fe7a..8a4d75809181 100644 --- a/js/src/Makefile.in +++ b/js/src/Makefile.in @@ -242,6 +242,10 @@ JSJAVA_CFLAGS = \ HOST_SIMPLE_PROGRAMS += host_jskwgen$(HOST_BIN_SUFFIX) GARBAGE += jsautokw.h host_jskwgen$(HOST_BIN_SUFFIX) + +HOST_SIMPLE_PROGRAMS += host_jsoplengen$(HOST_BIN_SUFFIX) +GARBAGE += jsautooplen.h host_jsoplengen$(HOST_BIN_SUFFIX) + USE_HOST_CXX = 1 ifdef HAVE_DTRACE @@ -445,18 +449,23 @@ jscpucfg$(HOST_BIN_SUFFIX): jscpucfg.cpp Makefile.in endif endif -# Extra dependancies and rules for keyword switch code -jsscan.$(OBJ_SUFFIX): jsautokw.h jskeyword.tbl - +# Extra dependancies and rules for auto-generated headers host_jskwgen.$(OBJ_SUFFIX): jsconfig.h jskeyword.tbl jsautokw.h: host_jskwgen$(HOST_BIN_SUFFIX) ./host_jskwgen$(HOST_BIN_SUFFIX) $@ +host_jsoplengen.$(OBJ_SUFFIX): jsopcode.tbl + +jsautooplen.h: host_jsoplengen$(HOST_BIN_SUFFIX) + ./host_jsoplengen$(HOST_BIN_SUFFIX) $@ + +# Force auto-header generation before compiling any source that may use them +$(CPPSRCS:%.cpp=%.$(OBJ_SUFFIX)): jsautokw.h jsautooplen.h + ifdef HAVE_DTRACE javascript-trace.h: $(srcdir)/javascript-trace.d dtrace -h -s $(srcdir)/javascript-trace.d -o javascript-trace.h.in sed 's/if _DTRACE_VERSION/ifdef INCLUDE_MOZILLA_DTRACE/' \ javascript-trace.h.in > javascript-trace.h endif - diff --git a/js/src/Makefile.ref b/js/src/Makefile.ref index a6ada0ca6cfa..520e801d71ca 100644 --- a/js/src/Makefile.ref +++ b/js/src/Makefile.ref @@ -277,39 +277,39 @@ nsinstall-target: cd ../../config; $(MAKE) OBJDIR=$(OBJDIR) OBJDIR_NAME=$(OBJDIR) # -# Rules for keyword switch generation +# Automatic header generation # -GARBAGE += $(OBJDIR)/jsautokw.h $(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX) -GARBAGE += $(OBJDIR)/jskwgen.$(OBJ_SUFFIX) +AUTO_HEADERS = $(OBJDIR)/jsautokw.h $(OBJDIR)/jsautooplen.h -$(OBJDIR)/jsscan.$(OBJ_SUFFIX): $(OBJDIR)/jsautokw.h jskeyword.tbl +$(OBJDIR)/jsautokw.h: jskeyword.tbl -$(OBJDIR)/jskwgen.$(OBJ_SUFFIX): jskwgen.cpp jskeyword.tbl +$(OBJDIR)/jsautooplen.h: jsopcode.tbl -$(OBJDIR)/jsautokw.h: $(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX) jskeyword.tbl - $(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX) $@ +GARBAGE += $(AUTO_HEADERS) +GARBAGE += $(AUTO_HEADERS:$(OBJDIR)/jsauto%.h=$(OBJDIR)/js%gen$(HOST_BIN_SUFFIX)) ifdef USE_MSVC -$(OBJDIR)/jskwgen.obj: jskwgen.cpp jskeyword.tbl +GARBAGE += $(AUTO_HEADERS:$(OBJDIR)/jsauto%.h=$(OBJDIR)/js%gen.obj) + +$(AUTO_HEADERS): $(OBJDIR)/jsauto%.h: js%gen.cpp @$(MAKE_OBJDIR) $(CXX) -Fo$(OBJDIR)/ -c $(CFLAGS) $< - -$(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX): $(OBJDIR)/jskwgen.$(OBJ_SUFFIX) - link.exe -out:"$@" $(EXE_LINK_FLAGS) $^ - + link.exe -out:"$(OBJDIR)/js$*gen$(HOST_BIN_SUFFIX)" $(EXE_LINK_FLAGS) $(OBJDIR)/js$*gen.obj + $(OBJDIR)/js$*gen$(HOST_BIN_SUFFIX) $@ else -$(OBJDIR)/jskwgen.o: jskwgen.cpp jskeyword.tbl +$(AUTO_HEADERS): $(OBJDIR)/jsauto%.h: js%gen.cpp @$(MAKE_OBJDIR) - $(CXX) -o $@ -c $(CFLAGS) $< - -$(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX): $(OBJDIR)/jskwgen.$(OBJ_SUFFIX) - $(CXX) -o $@ $(CFLAGS) $(LDFLAGS) $^ + $(CXX) -o $(OBJDIR)/js$*gen$(HOST_BIN_SUFFIX) $(CFLAGS) $(LDFLAGS) $< + $(OBJDIR)/js$*gen$(HOST_BIN_SUFFIX) $@ endif +# force creation of autoheaders before compiling any source that may use them +$(LIB_OBJS) : $(AUTO_HEADERS) + # # JS shell executable # diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index 311d7cc06edd..7309ebbabf53 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -62,6 +62,8 @@ #include "jsscript.h" #include "jsstr.h" +#include "jsautooplen.h" + typedef struct JSTrap { JSCList links; JSScript *script; diff --git a/js/src/jsemit.cpp b/js/src/jsemit.cpp index daff25c9e53a..638ade9eef55 100644 --- a/js/src/jsemit.cpp +++ b/js/src/jsemit.cpp @@ -66,6 +66,8 @@ #include "jsscope.h" #include "jsscript.h" +#include "jsautooplen.h" + /* Allocation chunk counts, must be powers of two in general. */ #define BYTECODE_CHUNK 256 /* code allocation increment */ #define SRCNOTE_CHUNK 64 /* initial srcnote allocation increment */ diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 3c58cabee4b7..9bc14c21e7af 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -77,6 +77,8 @@ #include "jsxml.h" #endif +#include "jsautooplen.h" + #ifdef js_invoke_c__ uint32 @@ -2074,6 +2076,77 @@ js_DoIncDec(JSContext *cx, const JSCodeSpec *cs, jsval *vp, jsval *vp2) return JS_TRUE; } +#ifdef DEBUG + +void +js_TraceOpcode(JSContext *cx, jsint len) +{ + FILE *tracefp; + JSStackFrame *fp; + JSFrameRegs *regs; + JSOp prevop; + intN ndefs, n, nuses; + jsval *siter; + JSString *str; + JSOp op; + + tracefp = (FILE *) cx->tracefp; + JS_ASSERT(tracefp); + fp = cx->fp; + regs = fp->regs; + if (len != 0) { + prevop = (JSOp) regs->pc[-len]; + ndefs = js_CodeSpec[prevop].ndefs; + if (ndefs != 0) { + if (prevop == JSOP_FORELEM && regs->sp[-1] == JSVAL_FALSE) + --ndefs; + for (n = -ndefs; n < 0; n++) { + char *bytes = js_DecompileValueGenerator(cx, n, regs->sp[n], + NULL); + if (bytes) { + fprintf(tracefp, "%s %s", + (n == -ndefs) ? " output:" : ",", + bytes); + JS_free(cx, bytes); + } + } + fprintf(tracefp, " @ %d\n", regs->sp - fp->spbase); + } + fprintf(tracefp, " stack: "); + for (siter = fp->spbase; siter < regs->sp; siter++) { + str = js_ValueToString(cx, *siter); + if (!str) + fputs("", tracefp); + else + js_FileEscapedString(tracefp, str, 0); + fputc(' ', tracefp); + } + fputc('\n', tracefp); + } + + fprintf(tracefp, "%4u: ", js_PCToLineNumber(cx, fp->script, regs->pc)); + js_Disassemble1(cx, fp->script, regs->pc, + PTRDIFF(regs->pc, fp->script->code, jsbytecode), + JS_FALSE, tracefp); + op = (JSOp) *regs->pc; + nuses = js_CodeSpec[op].nuses; + if (nuses != 0) { + for (n = -nuses; n < 0; n++) { + char *bytes = js_DecompileValueGenerator(cx, n, regs->sp[n], + NULL); + if (bytes) { + fprintf(tracefp, "%s %s", + (n == -nuses) ? " inputs:" : ",", + bytes); + JS_free(cx, bytes); + } + } + fprintf(tracefp, " @ %d\n", regs->sp - fp->spbase); + } +} + +#endif /* DEBUG */ + #ifdef JS_OPMETER # include @@ -2425,6 +2498,13 @@ JS_STATIC_ASSERT(!CAN_DO_FAST_INC_DEC(INT_TO_JSVAL(JSVAL_INT_MAX))); # endif #endif + +/* + * Interpreter assumes the following to implement condition-free interrupt + * implementation when !JS_THREADED_INTERP. + */ +JS_STATIC_ASSERT(JSOP_INTERRUPT == 0); + /* * Ensure that the intrepreter switch can close call-bytecode cases in the * same way as non-call bytecodes. @@ -2462,7 +2542,6 @@ js_Interpret(JSContext *cx) JSFrameRegs regs; JSObject *obj, *obj2, *parent; JSBool ok, cond; - JSTrapHandler interruptHandler; jsint len; jsbytecode *endpc, *pc2; JSOp op, op2; @@ -2481,8 +2560,11 @@ js_Interpret(JSContext *cx) JSClass *clasp; JSFunction *fun; JSType type; -#if !JS_THREADED_INTERP && defined DEBUG - FILE *tracefp = NULL; +#if JS_THREADED_INTERP + register const void * const *jumpTable; +#else + register uint32 switchMask; + uintN switchOp; #endif #if JS_HAS_EXPORT_IMPORT JSIdArray *ida; @@ -2502,42 +2584,68 @@ js_Interpret(JSContext *cx) #endif #if JS_THREADED_INTERP - static void *normalJumpTable[] = { + static const void *const normalJumpTable[] = { # define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \ JS_EXTENSION &&L_##op, # include "jsopcode.tbl" # undef OPDEF }; - static void *interruptJumpTable[] = { + static const void *const interruptJumpTable[] = { # define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \ - JS_EXTENSION &&interrupt, + JS_EXTENSION &&L_JSOP_INTERRUPT, # include "jsopcode.tbl" # undef OPDEF }; - register void **jumpTable = normalJumpTable; - METER_OP_INIT(op); /* to nullify first METER_OP_PAIR */ # define DO_OP() JS_EXTENSION_(goto *jumpTable[op]) -# define DO_NEXT_OP(n) do { METER_OP_PAIR(op, regs.pc[n]); \ - op = (JSOp) *(regs.pc += (n)); \ - DO_OP(); } while (0) +# define DO_NEXT_OP(n) JS_BEGIN_MACRO \ + METER_OP_PAIR(op, regs.pc[n]); \ + op = (JSOp) *(regs.pc += (n)); \ + DO_OP(); \ + JS_END_MACRO + # define BEGIN_CASE(OP) L_##OP: # define END_CASE(OP) DO_NEXT_OP(OP##_LENGTH); # define END_VARLEN_CASE DO_NEXT_OP(len); -# define EMPTY_CASE(OP) BEGIN_CASE(OP) op = (JSOp) *++regs.pc; DO_OP(); -#else +# define ADD_EMPTY_CASE(OP) BEGIN_CASE(OP) \ + JS_ASSERT(js_CodeSpec[OP].length == 1); \ + op = (JSOp) *++regs.pc; \ + DO_OP(); + +# define END_EMPTY_CASES + +#else /* !JS_THREADED_INTERP */ + # define DO_OP() goto do_op -# define DO_NEXT_OP(n) goto advance_pc +# define DO_NEXT_OP(n) JS_BEGIN_MACRO \ + JS_ASSERT((n) == len); \ + goto advance_pc; \ + JS_END_MACRO + # define BEGIN_CASE(OP) case OP: -# define END_CASE(OP) break; -# define END_VARLEN_CASE break; -# define EMPTY_CASE(OP) BEGIN_CASE(OP) END_CASE(OP) +# define END_CASE(OP) END_CASE_LEN(OP##_LENGTH) +# define END_CASE_LEN(n) END_CASE_LENX(n) +# define END_CASE_LENX(n) END_CASE_LEN##n + +/* + * To share the code for all len == 1 cases we use the specialized label with + * code that falls through to advance_pc: . + */ +# define END_CASE_LEN1 goto advance_pc_by_one; +# define END_CASE_LEN2 len = 2; goto advance_pc; +# define END_CASE_LEN3 len = 3; goto advance_pc; +# define END_CASE_LEN4 len = 4; goto advance_pc; +# define END_CASE_LEN5 len = 5; goto advance_pc; +# define END_VARLEN_CASE goto advance_pc; +# define ADD_EMPTY_CASE(OP) BEGIN_CASE(OP) +# define END_EMPTY_CASES goto advance_pc_by_one; + #endif - /* Check for too deep a C stack. */ + /* Check for too deep of a native thread stack. */ JS_CHECK_RECURSION(cx, return JS_FALSE); rt = cx->runtime; @@ -2616,18 +2724,15 @@ js_Interpret(JSContext *cx) * the compiler can keep it in a register when it is non-null. */ #if JS_THREADED_INTERP -# define LOAD_JUMP_TABLE() \ - (jumpTable = interruptHandler ? interruptJumpTable : normalJumpTable) +# define LOAD_INTERRUPT_HANDLER(cx) \ + ((void) (jumpTable = (cx)->debugHooks->interruptHandler \ + ? interruptJumpTable \ + : normalJumpTable)) #else -# define LOAD_JUMP_TABLE() ((void) 0) +# define LOAD_INTERRUPT_HANDLER(cx) \ + ((void) (switchMask = (cx)->debugHooks->interruptHandler ? 0 : 255)) #endif -#define LOAD_INTERRUPT_HANDLER(cx) \ - JS_BEGIN_MACRO \ - interruptHandler = (cx)->debugHooks->interruptHandler; \ - LOAD_JUMP_TABLE(); \ - JS_END_MACRO - LOAD_INTERRUPT_HANDLER(cx); /* @@ -2675,107 +2780,89 @@ js_Interpret(JSContext *cx) } } -#if JS_THREADED_INTERP - /* - * This is a loop, but it does not look like a loop. The loop-closing - * jump is distributed throughout interruptJumpTable, and comes back to - * the interrupt label. The dispatch on op is through normalJumpTable. - * The trick is LOAD_INTERRUPT_HANDLER setting jumpTable appropriately. - * - * It is important that "op" be initialized before the interrupt label - * because it is possible for "op" to be specially assigned during the - * normally processing of an opcode while looping (in particular, this - * happens in JSOP_TRAP while debugging). We rely on DO_NEXT_OP to - * correctly manage "op" in all other cases. + * It is important that "op" be initialized before calling DO_OP because + * it is possible for "op" to be specially assigned during the normal + * processing of an opcode while looping. We rely on DO_NEXT_OP to manage + * "op" correctly in all other cases. */ - op = (JSOp) *regs.pc; - if (interruptHandler) { -interrupt: - switch (interruptHandler(cx, script, regs.pc, &rval, - cx->debugHooks->interruptHandlerData)) { - case JSTRAP_ERROR: - goto error; - case JSTRAP_CONTINUE: - break; - case JSTRAP_RETURN: - fp->rval = rval; - ok = JS_TRUE; - goto forced_return; - case JSTRAP_THROW: - cx->throwing = JS_TRUE; - cx->exception = rval; - goto error; - default:; - } - LOAD_INTERRUPT_HANDLER(cx); - } - - JS_ASSERT((uintN)op < (uintN)JSOP_LIMIT); - JS_EXTENSION_(goto *normalJumpTable[op]); - -#else /* !JS_THREADED_INTERP */ + len = 0; + DO_NEXT_OP(len); +#if JS_THREADED_INTERP + /* + * This is a loop, but it does not look like a loop. The loop-closing + * jump is distributed throughout goto *jumpTable[op] inside of DO_OP. + * When interrupts are enabled, jumpTable is set to interruptJumpTable + * where all jumps point to the JSOP_INTERRUPT case. The latter, after + * calling the interrupt handler, dispatches through normalJumpTable to + * continue the normal bytecode processing. + */ +#else for (;;) { + advance_pc_by_one: + JS_ASSERT(js_CodeSpec[op].length == 1); + len = 1; + advance_pc: + regs.pc += len; op = (JSOp) *regs.pc; - do_op: - len = js_CodeSpec[op].length; - #ifdef DEBUG - tracefp = (FILE *) cx->tracefp; - if (tracefp) { - intN nuses, n; - - fprintf(tracefp, "%4u: ", js_PCToLineNumber(cx, script, regs.pc)); - js_Disassemble1(cx, script, regs.pc, - PTRDIFF(regs.pc, script->code, jsbytecode), - JS_FALSE, tracefp); - nuses = js_CodeSpec[op].nuses; - if (nuses) { - for (n = -nuses; n < 0; n++) { - char *bytes = js_DecompileValueGenerator(cx, n, regs.sp[n], - NULL); - if (bytes) { - fprintf(tracefp, "%s %s", - (n == -nuses) ? " inputs:" : ",", - bytes); - JS_free(cx, bytes); - } - } - fprintf(tracefp, " @ %d\n", regs.sp - fp->spbase); - } - } -#endif /* DEBUG */ - - if (interruptHandler) { - switch (interruptHandler(cx, script, regs.pc, &rval, - cx->debugHooks->interruptHandlerData)) { - case JSTRAP_ERROR: - goto error; - case JSTRAP_CONTINUE: - break; - case JSTRAP_RETURN: - fp->rval = rval; - ok = JS_TRUE; - goto forced_return; - case JSTRAP_THROW: - cx->throwing = JS_TRUE; - cx->exception = rval; - goto error; - default:; - } - LOAD_INTERRUPT_HANDLER(cx); - } - - switch (op) { + if (cx->tracefp) + js_TraceOpcode(cx, len); +#endif + do_op: + switchOp = op & switchMask; + do_switch: + switch (switchOp) { #endif /* !JS_THREADED_INTERP */ - EMPTY_CASE(JSOP_NOP) + BEGIN_CASE(JSOP_INTERRUPT) + { + JSTrapHandler handler; - EMPTY_CASE(JSOP_GROUP) + handler = cx->debugHooks->interruptHandler; + if (handler) { + switch (handler(cx, script, regs.pc, &rval, + cx->debugHooks->interruptHandlerData)) { + case JSTRAP_ERROR: + goto error; + case JSTRAP_CONTINUE: + break; + case JSTRAP_RETURN: + fp->rval = rval; + ok = JS_TRUE; + goto forced_return; + case JSTRAP_THROW: + cx->throwing = JS_TRUE; + cx->exception = rval; + goto error; + default:; + } + } + LOAD_INTERRUPT_HANDLER(cx); - /* EMPTY_CASE is not used here as JSOP_LINENO_LENGTH == 3. */ +#if JS_THREADED_INTERP + JS_EXTENSION_(goto *normalJumpTable[op]); +#else + switchOp = op; + goto do_switch; +#endif + } + + /* No-ops for ease of decompilation. */ + ADD_EMPTY_CASE(JSOP_NOP) + ADD_EMPTY_CASE(JSOP_GROUP) + ADD_EMPTY_CASE(JSOP_CONDSWITCH) + ADD_EMPTY_CASE(JSOP_TRY) + ADD_EMPTY_CASE(JSOP_FINALLY) +#if JS_HAS_XML_SUPPORT + ADD_EMPTY_CASE(JSOP_STARTXML) + ADD_EMPTY_CASE(JSOP_STARTXMLEXPR) +#endif + END_EMPTY_CASES + + /* ADD_EMPTY_CASE is not used here as JSOP_LINENO_LENGTH == 3. */ BEGIN_CASE(JSOP_LINENO) END_CASE(JSOP_LINENO) @@ -2810,12 +2897,6 @@ interrupt: #endif END_CASE(JSOP_POPN) - BEGIN_CASE(JSOP_SWAP) - rtmp = regs.sp[-1]; - regs.sp[-1] = regs.sp[-2]; - regs.sp[-2] = rtmp; - END_CASE(JSOP_SWAP) - BEGIN_CASE(JSOP_SETRVAL) BEGIN_CASE(JSOP_POPV) ASSERT_NOT_THROWING(cx); @@ -4139,7 +4220,6 @@ interrupt: i = 0; COMPUTE_THIS(cx, fp, obj); PUSH(JSVAL_NULL); - len = JSOP_GETTHISPROP_LENGTH; goto do_getprop_with_obj; #undef COMPUTE_THIS @@ -4149,7 +4229,6 @@ interrupt: slot = GET_ARGNO(regs.pc); JS_ASSERT(slot < fp->fun->nargs); PUSH_OPND(fp->argv[slot]); - len = JSOP_GETARGPROP_LENGTH; goto do_getprop_body; BEGIN_CASE(JSOP_GETVARPROP) @@ -4157,7 +4236,6 @@ interrupt: slot = GET_VARNO(regs.pc); JS_ASSERT(slot < fp->fun->u.i.nvars); PUSH_OPND(fp->vars[slot]); - len = JSOP_GETVARPROP_LENGTH; goto do_getprop_body; BEGIN_CASE(JSOP_GETLOCALPROP) @@ -4165,13 +4243,11 @@ interrupt: slot = GET_UINT16(regs.pc); JS_ASSERT(slot < script->depth); PUSH_OPND(fp->spbase[slot]); - len = JSOP_GETLOCALPROP_LENGTH; goto do_getprop_body; BEGIN_CASE(JSOP_GETPROP) BEGIN_CASE(JSOP_GETXPROP) i = 0; - len = JSOP_GETPROP_LENGTH; do_getprop_body: lval = FETCH_OPND(-1); @@ -4217,6 +4293,8 @@ interrupt: } while (0); STORE_OPND(-1, rval); + JS_ASSERT(JSOP_GETPROP_LENGTH + i == js_CodeSpec[op].length); + len = JSOP_GETPROP_LENGTH + i; END_VARLEN_CASE BEGIN_CASE(JSOP_LENGTH) @@ -4241,8 +4319,7 @@ interrupt: goto error; } } else { - i = -1; - len = JSOP_LENGTH_LENGTH; + i = -2; goto do_getprop_with_lval; } END_CASE(JSOP_LENGTH) @@ -4996,12 +5073,12 @@ interrupt: goto error; if (!prop) { /* Kludge to allow (typeof foo == "undefined") tests. */ - len = JSOP_NAME_LENGTH; endpc = script->code + script->length; - for (pc2 = regs.pc + len; pc2 < endpc; pc2++) { + for (pc2 = regs.pc + JSOP_NAME_LENGTH; pc2 < endpc; pc2++) { op2 = (JSOp)*pc2; if (op2 == JSOP_TYPEOF) { PUSH_OPND(JSVAL_VOID); + len = JSOP_NAME_LENGTH; DO_NEXT_OP(len); } if (op2 != JSOP_GROUP) @@ -5338,8 +5415,6 @@ interrupt: : GET_JUMPX_OFFSET(pc2); END_VARLEN_CASE - EMPTY_CASE(JSOP_CONDSWITCH) - #if JS_HAS_EXPORT_IMPORT BEGIN_CASE(JSOP_EXPORTALL) obj = fp->varobj; @@ -5414,15 +5489,13 @@ interrupt: #endif /* JS_HAS_EXPORT_IMPORT */ BEGIN_CASE(JSOP_TRAP) - switch (JS_HandleTrap(cx, script, regs.pc, &rval)) { + { + JSTrapStatus status; + + status = JS_HandleTrap(cx, script, regs.pc, &rval); + switch (status) { case JSTRAP_ERROR: goto error; - case JSTRAP_CONTINUE: - JS_ASSERT(JSVAL_IS_INT(rval)); - op = (JSOp) JSVAL_TO_INT(rval); - JS_ASSERT((uintN)op < (uintN)JSOP_LIMIT); - LOAD_INTERRUPT_HANDLER(cx); - DO_OP(); case JSTRAP_RETURN: fp->rval = rval; ok = JS_TRUE; @@ -5432,9 +5505,15 @@ interrupt: cx->exception = rval; goto error; default:; + break; } + JS_ASSERT(status == JSTRAP_CONTINUE); LOAD_INTERRUPT_HANDLER(cx); - END_CASE(JSOP_TRAP) + JS_ASSERT(JSVAL_IS_INT(rval)); + op = (JSOp) JSVAL_TO_INT(rval); + JS_ASSERT((uintN)op < (uintN)JSOP_LIMIT); + DO_OP(); + } BEGIN_CASE(JSOP_ARGUMENTS) if (!js_GetArgsValue(cx, fp, &rval)) @@ -6172,7 +6251,7 @@ interrupt: goto error; } regs.sp -= 2; - END_CASE(JSOP_INITELEM); + END_CASE(JSOP_INITELEM) #if JS_HAS_SHARP_VARS BEGIN_CASE(JSOP_DEFSHARP) @@ -6219,15 +6298,11 @@ interrupt: END_CASE(JSOP_USESHARP) #endif /* JS_HAS_SHARP_VARS */ - /* No-ops for ease of decompilation and jit'ing. */ - EMPTY_CASE(JSOP_TRY) - EMPTY_CASE(JSOP_FINALLY) - BEGIN_CASE(JSOP_GOSUB) PUSH(JSVAL_FALSE); i = PTRDIFF(regs.pc, script->main, jsbytecode) + JSOP_GOSUB_LENGTH; - len = GET_JUMP_OFFSET(regs.pc); PUSH(INT_TO_JSVAL(i)); + len = GET_JUMP_OFFSET(regs.pc); END_VARLEN_CASE BEGIN_CASE(JSOP_GOSUBX) @@ -6482,9 +6557,6 @@ interrupt: regs.sp--; END_CASE(JSOP_ENDFILTER); - EMPTY_CASE(JSOP_STARTXML) - EMPTY_CASE(JSOP_STARTXMLEXPR) - BEGIN_CASE(JSOP_TOXML) rval = FETCH_OPND(-1); obj = js_ValueToXMLObject(cx, rval); @@ -6784,48 +6856,6 @@ interrupt: #if !JS_THREADED_INTERP } /* switch (op) */ - - advance_pc: - regs.pc += len; - -#ifdef DEBUG - if (tracefp) { - intN ndefs, n; - jsval *siter; - - /* - * op may be invalid here when a catch or finally handler jumps to - * advance_pc. - */ - op = (JSOp) regs.pc[-len]; - ndefs = js_CodeSpec[op].ndefs; - if (ndefs) { - if (op == JSOP_FORELEM && regs.sp[-1] == JSVAL_FALSE) - --ndefs; - for (n = -ndefs; n < 0; n++) { - char *bytes = js_DecompileValueGenerator(cx, n, regs.sp[n], - NULL); - if (bytes) { - fprintf(tracefp, "%s %s", - (n == -ndefs) ? " output:" : ",", - bytes); - JS_free(cx, bytes); - } - } - fprintf(tracefp, " @ %d\n", regs.sp - fp->spbase); - } - fprintf(tracefp, " stack: "); - for (siter = fp->spbase; siter < regs.sp; siter++) { - str = js_ValueToString(cx, *siter); - if (!str) - fputs("", tracefp); - else - js_FileEscapedString(tracefp, str, 0); - fputc(' ', tracefp); - } - fputc('\n', tracefp); - } -#endif /* DEBUG */ } #endif /* !JS_THREADED_INTERP */ diff --git a/js/src/jsinterp.h b/js/src/jsinterp.h index 7fb54660a749..3f8bdfe9bba7 100644 --- a/js/src/jsinterp.h +++ b/js/src/jsinterp.h @@ -507,6 +507,13 @@ js_OnUnknownMethod(JSContext *cx, jsval *vp); extern JSBool js_DoIncDec(JSContext *cx, const JSCodeSpec *cs, jsval *vp, jsval *vp2); +/* + * Opcode tracing helper. When len is not 0, cx->fp->regs->pc[-len] gives the + * previous opcode. + */ +extern void +js_TraceOpcode(JSContext *cx, jsint len); + /* * JS_OPMETER helper functions. */ diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index a9540166152c..e8ac435e8daa 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -88,6 +88,8 @@ #include "jsdtracef.h" #endif +#include "jsautooplen.h" + #ifdef JS_THREADSAFE #define NATIVE_DROP_PROPERTY js_DropProperty diff --git a/js/src/jsopcode.cpp b/js/src/jsopcode.cpp index cf0accc147d5..91e0f9e0fa7f 100644 --- a/js/src/jsopcode.cpp +++ b/js/src/jsopcode.cpp @@ -75,6 +75,14 @@ # include "jsnum.h" #endif +#include "jsautooplen.h" + +/* Verify JSOP_XXX_LENGTH constant definitions. */ +#define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \ + JS_STATIC_ASSERT(op##_LENGTH == length); +#include "jsopcode.tbl" +#undef OPDEF + static const char js_incop_strs[][3] = {"++", "--"}; const JSCodeSpec js_CodeSpec[] = { @@ -2152,14 +2160,6 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) todo = -2; break; - case JSOP_SWAP: - /* - * We don't generate this opcode currently, and previously we - * did not need to decompile it. If old, serialized bytecode - * uses it still, we should fall through and set todo = -2. - */ - /* FALL THROUGH */ - case JSOP_GOSUB: case JSOP_GOSUBX: /* @@ -4993,8 +4993,7 @@ DecompileExpression(JSContext *cx, JSScript *script, JSFunction *fun, /* None of these stack-writing ops generates novel values. */ JS_ASSERT(op != JSOP_CASE && op != JSOP_CASEX && - op != JSOP_DUP && op != JSOP_DUP2 && - op != JSOP_SWAP); + op != JSOP_DUP && op != JSOP_DUP2); /* * |this| could convert to a very long object initialiser, so cite it by @@ -5274,13 +5273,6 @@ ReconstructPCStack(JSContext *cx, JSScript *script, jsbytecode *pc, pcstack[pcdepth + 3] = pcstack[pcdepth + 1]; break; - case JSOP_SWAP: - JS_ASSERT(ndefs == 2); - pc2 = pcstack[pcdepth]; - pcstack[pcdepth] = pcstack[pcdepth + 1]; - pcstack[pcdepth + 1] = pc2; - break; - case JSOP_LEAVEBLOCKEXPR: /* * The decompiler wants to see [leaveblockexpr] on pcstack, not diff --git a/js/src/jsopcode.h b/js/src/jsopcode.h index 9e185e4c3b07..831b95fa9401 100644 --- a/js/src/jsopcode.h +++ b/js/src/jsopcode.h @@ -60,14 +60,6 @@ typedef enum JSOp { JSOP_LIMIT } JSOp; -typedef enum JSOpLength { -#define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \ - op##_LENGTH = length, -#include "jsopcode.tbl" -#undef OPDEF - JSOP_LIMIT_LENGTH -} JSOpLength; - /* * JS bytecode formats. */ diff --git a/js/src/jsopcode.tbl b/js/src/jsopcode.tbl index 7806e08e018f..f9ea46a03a5d 100644 --- a/js/src/jsopcode.tbl +++ b/js/src/jsopcode.tbl @@ -97,7 +97,7 @@ /* legend: op val name image len use def prec format */ /* Longstanding JavaScript bytecodes. */ -OPDEF(JSOP_NOP, 0, "nop", NULL, 1, 0, 0, 0, JOF_BYTE) +OPDEF(JSOP_INTERRUPT, 0, "interrupt", 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, 2, JOF_BYTE) OPDEF(JSOP_ENTERWITH, 3, "enterwith", NULL, 1, 1, 1, 0, JOF_BYTE|JOF_PARENHEAD) @@ -331,9 +331,9 @@ OPDEF(JSOP_TRY, 133,"try", NULL, 1, 0, 0, 0, JOF_BYTE) OPDEF(JSOP_FINALLY, 134,"finally", NULL, 1, 0, 0, 0, JOF_BYTE) /* - * Swap the top two stack elements. + * Generic nop for the decompiler. */ -OPDEF(JSOP_SWAP, 135,"swap", NULL, 1, 2, 2, 0, JOF_BYTE) +OPDEF(JSOP_NOP, 135,"nop", NULL, 1, 0, 0, 0, JOF_BYTE) /* * Bytecodes that avoid making an arguments object in most cases: diff --git a/js/src/jsoplengen.cpp b/js/src/jsoplengen.cpp new file mode 100644 index 000000000000..ecebc06ed803 --- /dev/null +++ b/js/src/jsoplengen.cpp @@ -0,0 +1,121 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set sw=4 ts=8 et tw=80: + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * 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 String Switch Generator for JavaScript Keywords, + * released 2005-12-09. + * + * The Initial Developer of the Original Code is + * Igor Bukanov. + * Portions created by the Initial Developer are Copyright (C) 2005-2006 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include +#include +#include + +static const struct { + const char *name; + int length; +} pairs[] = { +#define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \ + { #op, length } , +#include "jsopcode.tbl" +#undef OPDEF +}; + +int +main(int argc, char **argv) +{ + FILE *fp; + size_t maxNameWidth, i, nameWidth, tabStop; + int lengthGap; + + static const char prefix[] = "#define "; + static const char suffix[] = "_LENGTH"; + static const size_t tabWidth = 8; + static const size_t prefixWidth = sizeof(prefix) - 1; + static const size_t suffixWidth = sizeof(suffix) - 1; + + if (argc != 2) { + fputs("Bad usage\n", stderr); + return EXIT_FAILURE; + } + + fp = fopen(argv[1], "w"); + if (!fp) { + perror("fopen"); + return EXIT_FAILURE; + } + fputs("/*\n" + " * Automatically generated header with JS opcode length constants.\n" + " *\n" + " * Do not edit it, alter jsopcode.tbl instead.\n" + " */\n", + fp); + + /* + * Print + * + * #define name_LENGTH length + * + * with all length values aligned on the same column. The column is at the + * second character position after a tab-stop with the first position + * reserved for the minus sign of variable-length opcodes. + */ + maxNameWidth = 0; + for (i = 0; i != sizeof pairs / sizeof pairs[0]; ++i) { + nameWidth = strlen(pairs[i].name); + if (maxNameWidth < nameWidth) + maxNameWidth = nameWidth; + } + + tabStop = prefixWidth + maxNameWidth + suffixWidth + 1; + tabStop = (tabStop + tabWidth - 1) / tabWidth * tabWidth; + for (i = 0; i != sizeof pairs / sizeof pairs[0]; ++i) { + lengthGap = (int) (tabStop - prefixWidth - strlen(pairs[i].name) - + suffixWidth); + fprintf(fp, "%s%s%s%*c%2d\n", + prefix, pairs[i].name, suffix, lengthGap, ' ', + pairs[i].length); + if (ferror(fp)) { + perror("fclose"); + exit(EXIT_FAILURE); + } + } + + if (fclose(fp)) { + perror("fclose"); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/js/src/jsxdrapi.h b/js/src/jsxdrapi.h index 3026b49ee215..68a45432af94 100644 --- a/js/src/jsxdrapi.h +++ b/js/src/jsxdrapi.h @@ -202,7 +202,7 @@ JS_XDRFindClassById(JSXDRState *xdr, uint32 id); * before deserialization of bytecode. If the saved version does not match * the current version, abort deserialization and invalidate the file. */ -#define JSXDR_BYTECODE_VERSION (0xb973c0de - 25) +#define JSXDR_BYTECODE_VERSION (0xb973c0de - 26) /* * Library-private functions. diff --git a/js/src/liveconnect/nsCLiveconnect.cpp b/js/src/liveconnect/nsCLiveconnect.cpp index 4adfc740142b..3c0c344fcfc2 100644 --- a/js/src/liveconnect/nsCLiveconnect.cpp +++ b/js/src/liveconnect/nsCLiveconnect.cpp @@ -192,8 +192,8 @@ AutoPushJSContext::AutoPushJSContext(nsISupports* aSecuritySupports, mFrame.callee = JS_GetFunctionObject(fun); mFrame.scopeChain = JS_GetParent(cx, mFrame.callee); mFrame.down = cx->fp; - mRegs.pc = script->code + script->length - - JSOP_STOP_LENGTH; + mRegs.pc = script->code + script->length - 1; + JS_ASSERT(static_cast(*mRegs.pc) == JSOP_STOP); mRegs.sp = NULL; mFrame.regs = &mRegs; cx->fp = &mFrame; diff --git a/js/src/rules.mk b/js/src/rules.mk index 4ab596f23a69..ad80ad0f449a 100644 --- a/js/src/rules.mk +++ b/js/src/rules.mk @@ -185,11 +185,9 @@ endif clean: rm -rf $(OBJS) $(GARBAGE) - @cd fdlibm; $(MAKE) -f Makefile.ref clean clobber: rm -rf $(OBJS) $(TARGETS) $(DEPENDENCIES) - @cd fdlibm; $(MAKE) -f Makefile.ref clobber tar: tar cvf $(TARNAME) $(TARFILES) From b7ef2c1d5e283e0b9cdf618f5672f8607565f9ce Mon Sep 17 00:00:00 2001 From: Alexander Surkov Date: Fri, 20 Jun 2008 21:19:23 +0800 Subject: [PATCH 36/66] =?UTF-8?q?Bug=20438325=20=E2=80=93=20Link=20with=20?= =?UTF-8?q?title=20and=20an=20image=20that=20has=20neither=20alt=20nor=20t?= =?UTF-8?q?itle=20doesn't=20get=20an=20accessible=20name?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- accessible/src/html/nsHTMLLinkAccessible.cpp | 11 +- .../test_nsIAccessibleHyperLink.html | 105 +++++++++++++++++- 2 files changed, 113 insertions(+), 3 deletions(-) diff --git a/accessible/src/html/nsHTMLLinkAccessible.cpp b/accessible/src/html/nsHTMLLinkAccessible.cpp index 9b340efe1438..bd42e37c3527 100644 --- a/accessible/src/html/nsHTMLLinkAccessible.cpp +++ b/accessible/src/html/nsHTMLLinkAccessible.cpp @@ -66,7 +66,16 @@ nsHTMLLinkAccessible::GetName(nsAString& aName) return NS_ERROR_FAILURE; nsCOMPtr content(do_QueryInterface(mDOMNode)); - return AppendFlatStringFromSubtree(content, &aName); + nsresult rv = AppendFlatStringFromSubtree(content, &aName); + NS_ENSURE_SUCCESS(rv, rv); + + if (aName.IsEmpty()) { + // Probably an image without alt or title inside, try to get the name on + // the link by usual way. + return GetHTMLName(aName, PR_FALSE); + } + + return NS_OK; } NS_IMETHODIMP diff --git a/accessible/tests/mochitest/test_nsIAccessibleHyperLink.html b/accessible/tests/mochitest/test_nsIAccessibleHyperLink.html index c0f2ef876e92..b807764ab2db 100644 --- a/accessible/tests/mochitest/test_nsIAccessibleHyperLink.html +++ b/accessible/tests/mochitest/test_nsIAccessibleHyperLink.html @@ -240,7 +240,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=418368 } testThis("emptyLink", EmptyHLAcc, Components.interfaces.nsIAccessibleRole.ROLE_LINK, 1, - "", true, 98, 99); + null, true, 98, 99); testStates("emptyLink", EmptyHLAcc, (state_focusable | state_linked), (ext_state_horizontal), (0)); @@ -332,8 +332,88 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=418368 try { linksMapAcc = gAccRetrieval.getAccessibleFor(linksMapElement); } catch(e) { } - + ok(linksMapAcc, "no accessible for map grouping links!"); + + ////////////////////////////////////////////////////////////////////////// + // Link with title attribute, no name from the subtree (bug 438325). + var id = "linkWithTitleNoNameFromSubtree"; + var linkElement = document.getElementById(id); + var linkAcc; + try { + linkAcc = gAccRetrieval.getAccessibleFor(linkElement). + QueryInterface(Components.interfaces.nsIAccessibleHyperLink); + } catch(e) { + ok(linkAcc, "no interface for link with ID " + id + "!"); + } + testThis(id, linkAcc, + Components.interfaces.nsIAccessibleRole.ROLE_LINK, 1, + "Link with title", true, 354, 355); + testStates(id, linkAcc, + (state_linked), + (ext_state_horizontal), 0); + testAction(id, linkAcc, "jump"); + + ////////////////////////////////////////////////////////////////////////// + // Link with title attribute, name from the subtree - onsreen name + // (bug 438325). + id = "linkWithTitleNameFromSubtree"; + linkElement = document.getElementById(id); + linkAcc; + try { + linkAcc = gAccRetrieval.getAccessibleFor(linkElement). + QueryInterface(Components.interfaces.nsIAccessibleHyperLink); + } catch(e) { + ok(linkAcc, "no interface for link with ID " + id + "!"); + } + testThis(id, linkAcc, + Components.interfaces.nsIAccessibleRole.ROLE_LINK, 1, + "the name from subtree", true, 403, 404); + testStates(id, linkAcc, + (state_linked), + (ext_state_horizontal), 0); + testAction(id, linkAcc, "jump"); + + ////////////////////////////////////////////////////////////////////////// + // Link with title attribute, name from the nested html:img (bug 438325). + id = "linkWithTitleNameFromImg"; + linkElement = document.getElementById(id); + linkAcc; + try { + linkAcc = gAccRetrieval.getAccessibleFor(linkElement). + QueryInterface(Components.interfaces.nsIAccessibleHyperLink); + } catch(e) { + ok(linkAcc, "no interface for link with ID " + id + "!"); + } + testThis(id, linkAcc, + Components.interfaces.nsIAccessibleRole.ROLE_LINK, 1, + "The title for link", true, 458, 459); + testStates(id, linkAcc, + (state_linked), + (ext_state_horizontal), 0); + testAction(id, linkAcc, "jump"); + + ////////////////////////////////////////////////////////////////////////// + // Link with label, no name from the subtree (bug 438325). + id = "linkWithLabelNoNameFromSubtree"; + linkElement = document.getElementById(id); + linkAcc; + try { + linkAcc = gAccRetrieval.getAccessibleFor(linkElement). + QueryInterface(Components.interfaces.nsIAccessibleHyperLink); + } catch(e) { + ok(linkAcc, "no interface for link with ID " + id + "!"); + } + testThis(id, linkAcc, + Components.interfaces.nsIAccessibleRole.ROLE_LINK, 1, + "Link with label and nested image:", true, 462, 463); + testStates(id, linkAcc, + (state_linked), + (ext_state_horizontal), 0); + testAction(id, linkAcc, "jump"); + + ////////////////////////////////////////////////////////////////////////// + // SimpleTest.finish(); } @@ -373,17 +453,38 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=418368 height="15" usemap="#atoz_map" src="http://www.bbc.co.uk/radio4/images/letters.gif"> +
Empty link:
+
Link with embedded span
Heise Online +
Named anchor, must not have "linked" state for it to be exposed correctly:
This should never be of state_linked +
Link having no attributes, must not have "linked" state:
This should never be of state_linked +
Link with registered 'click' event:
This should have state_linked +
Link with title attribute (no name from subtree):
+ + +
Link with title attribute (name from subtree):
+ the name from subtree + +
Link with title attribute (name from nested image):
+ The title for link + +

+ +
Map that is used to group links (www.w3.org/TR/WCAG10-HTML-TECHS/#group-bypass), also see the bug 431615:
From 8451913ec704e28623e907805b0b20b1721af37b Mon Sep 17 00:00:00 2001 From: Jason Evans Date: Fri, 20 Jun 2008 10:29:43 -0700 Subject: [PATCH 37/66] Bug 431743: Upstream jemalloc fixes, r=benjamin Incorporate upstream jemalloc fixes from FreeBSD: * Detect overflow for huge allocations via sbrk(2). * Fix deadlock for base (internal) allocations in OOM case. * Fix bitmap vector initialization for small allocation runs. --- memory/jemalloc/jemalloc.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/memory/jemalloc/jemalloc.c b/memory/jemalloc/jemalloc.c index 616495b44ead..ea26b3683e1d 100644 --- a/memory/jemalloc/jemalloc.c +++ b/memory/jemalloc/jemalloc.c @@ -263,7 +263,7 @@ typedef unsigned long long uintmax_t; # define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var)) #endif #ifndef MOZ_MEMORY -__FBSDID("$FreeBSD: src/lib/libc/stdlib/malloc.c,v 1.162 2008/02/06 02:59:54 jasone Exp $"); +__FBSDID("$FreeBSD: head/lib/libc/stdlib/malloc.c 179704 2008-06-10 15:46:18Z jasone $"); #include "libc_private.h" #ifdef MALLOC_DEBUG # define _LOCK_DEBUG @@ -1758,8 +1758,10 @@ base_alloc(size_t size) malloc_mutex_lock(&base_mtx); /* Make sure there's enough space for the allocation. */ if ((uintptr_t)base_next_addr + csize > (uintptr_t)base_past_addr) { - if (base_pages_alloc(csize)) + if (base_pages_alloc(csize)) { + malloc_mutex_unlock(&base_mtx); return (NULL); + } } /* Allocate. */ ret = base_next_addr; @@ -2128,6 +2130,13 @@ static void * chunk_alloc_dss(size_t size) { + /* + * sbrk() uses a signed increment argument, so take care not to + * interpret a huge allocation request as a negative increment. + */ + if ((intptr_t)size < 0) + return (NULL); + malloc_mutex_lock(&dss_mtx); if (dss_prev != (void *)-1) { intptr_t incr; @@ -3399,10 +3408,12 @@ arena_bin_nonfull_run_get(arena_t *arena, arena_bin_t *bin) /* Initialize run internals. */ run->bin = bin; - for (i = 0; i < bin->regs_mask_nelms; i++) + for (i = 0; i < bin->regs_mask_nelms - 1; i++) run->regs_mask[i] = UINT_MAX; remainder = bin->nregs & ((1U << (SIZEOF_INT_2POW + 3)) - 1); - if (remainder != 0) { + if (remainder == 0) + run->regs_mask[i] = UINT_MAX; + else { /* The last element has spare bits that need to be unset. */ run->regs_mask[i] = (UINT_MAX >> ((1U << (SIZEOF_INT_2POW + 3)) - remainder)); From 9f1fc45c673e71d0779dbf33cdbc8d638d1298e9 Mon Sep 17 00:00:00 2001 From: Jason Evans Date: Fri, 20 Jun 2008 10:34:41 -0700 Subject: [PATCH 38/66] Bug 432894: X related valgrind | jemalloc - startup errors, r=bclary,r=benjamin Fix bugs in jemalloc's valgrind support. --- memory/jemalloc/jemalloc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/memory/jemalloc/jemalloc.c b/memory/jemalloc/jemalloc.c index ea26b3683e1d..a9c62e06806f 100644 --- a/memory/jemalloc/jemalloc.c +++ b/memory/jemalloc/jemalloc.c @@ -2963,8 +2963,14 @@ arena_run_split(arena_t *arena, arena_run_t *run, size_t size, bool small, if (zero) { if ((chunk->map[run_ind + i] & CHUNK_MAP_UNTOUCHED) == 0) { + VALGRIND_MALLOCLIKE_BLOCK((void *)((uintptr_t) + chunk + ((run_ind + i) << pagesize_2pow)), + pagesize, 0, false); memset((void *)((uintptr_t)chunk + ((run_ind + i) << pagesize_2pow)), 0, pagesize); + VALGRIND_FREELIKE_BLOCK((void *)((uintptr_t) + chunk + ((run_ind + i) << pagesize_2pow)), + 0); /* CHUNK_MAP_UNTOUCHED is cleared below. */ } } @@ -3403,7 +3409,7 @@ arena_bin_nonfull_run_get(arena_t *arena, arena_bin_t *bin) return (NULL); VALGRIND_MALLOCLIKE_BLOCK(run, sizeof(arena_run_t) + (sizeof(unsigned) * - bin->regs_mask_nelms - 1), 0, false); + (bin->regs_mask_nelms - 1)), 0, false); /* Initialize run internals. */ run->bin = bin; From 16e8825a75b0fc18ae37c75e6871c4fc949d2399 Mon Sep 17 00:00:00 2001 From: Jason Evans Date: Fri, 20 Jun 2008 10:34:42 -0700 Subject: [PATCH 39/66] Bug 422960: Add jemalloc_stats() and jemalloc.h, r=benjamin --- js/src/Makefile.in | 6 + js/src/jsgc.cpp | 12 +- memory/jemalloc/Makefile.in | 9 +- memory/jemalloc/jemalloc.c | 229 +++++++++++++++++++++++++----------- memory/jemalloc/jemalloc.h | 57 +++++++++ 5 files changed, 234 insertions(+), 79 deletions(-) create mode 100644 memory/jemalloc/jemalloc.h diff --git a/js/src/Makefile.in b/js/src/Makefile.in index 8a4d75809181..8cb0aa45b15c 100644 --- a/js/src/Makefile.in +++ b/js/src/Makefile.in @@ -359,6 +359,12 @@ LDFLAGS += -lposix4 -ldl -lnsl -lsocket endif endif +ifdef MOZ_MEMORY +ifeq ($(OS_ARCH),Darwin) +LDFLAGS += -ljemalloc +endif +endif + # Allow building jsinterp.c with special optimization flags ifdef INTERP_OPTIMIZER jsinterp.$(OBJ_SUFFIX): MODULE_OPTIMIZE_FLAGS=$(INTERP_OPTIMIZER) diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index f0149547a5ff..0327543731f5 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -88,14 +88,12 @@ #endif /* - * jemalloc provides posix_memalign but the function has to be explicitly - * declared on Windows. + * jemalloc provides posix_memalign. */ -#if HAS_POSIX_MEMALIGN && MOZ_MEMORY_WINDOWS -JS_BEGIN_EXTERN_C -extern int -posix_memalign(void **memptr, size_t alignment, size_t size); -JS_END_EXTERN_C +#ifdef MOZ_MEMORY +extern "C" { +#include "../../memory/jemalloc/jemalloc.h" +} #endif /* diff --git a/memory/jemalloc/Makefile.in b/memory/jemalloc/Makefile.in index 2fe0335ad3df..474d9429ab90 100644 --- a/memory/jemalloc/Makefile.in +++ b/memory/jemalloc/Makefile.in @@ -45,6 +45,10 @@ include $(DEPTH)/config/autoconf.mk MODULE = jemalloc +# jemalloc.c properly uses 'static', so don't burden it with manually exposing +# symbols. +VISIBILITY_FLAGS= + ifeq (WINNT,$(OS_TARGET)) # Two options for Windows, either you build the CRT from source, # or you use a pre-built DLL. @@ -68,8 +72,9 @@ $(CRT_OBJ_DIR)/jemalloc.c: $(srcdir)/crtsp1.diff $(CRT_OBJ_DIR) $(srcdir)/ed.exe $(CRT_OBJ_DIR)/build/intel/mozcrt19.dll: \ - $(CRT_OBJ_DIR)/jemalloc.c $(srcdir)/jemalloc.c $(srcdir)/tree.h - cp $(srcdir)/jemalloc.c $(srcdir)/tree.h $(CRT_OBJ_DIR) + $(CRT_OBJ_DIR)/jemalloc.c $(srcdir)/jemalloc.c $(srcdir)/jemalloc.h \ + $(srcdir)/tree.h + cp $(srcdir)/jemalloc.c $(srcdir)/jemalloc.h $(srcdir)/tree.h $(CRT_OBJ_DIR) # this pretty much sucks, but nmake and make don't play well together $(PYTHON) $(srcdir)/build-crt.py $(CRT_OBJ_DIR) #XXX: these don't link right for some reason diff --git a/memory/jemalloc/jemalloc.c b/memory/jemalloc/jemalloc.c index a9c62e06806f..52286bb1feca 100644 --- a/memory/jemalloc/jemalloc.c +++ b/memory/jemalloc/jemalloc.c @@ -103,6 +103,12 @@ # define MALLOC_PRODUCTION #endif +/* + * MALLOC_STATS enables statistics calculation, and is required for + * jemalloc_stats(). + */ +#define MALLOC_STATS + #ifndef MALLOC_PRODUCTION /* * MALLOC_DEBUG enables assertions and other sanity checks, and disables @@ -110,9 +116,6 @@ */ # define MALLOC_DEBUG - /* MALLOC_STATS enables statistics calculation. */ -# define MALLOC_STATS - /* Memory filling (junk/zero). */ # define MALLOC_FILL @@ -203,7 +206,6 @@ #pragma warning( disable: 4267 4996 4146 ) -#define bool BOOL #define false FALSE #define true TRUE #define inline __inline @@ -336,6 +338,8 @@ __FBSDID("$FreeBSD: head/lib/libc/stdlib/malloc.c 179704 2008-06-10 15:46:18Z ja #endif +#include "jemalloc.h" + #ifdef MOZ_MEMORY_DARWIN static const bool __isthreaded = true; #endif @@ -364,12 +368,6 @@ static const bool __isthreaded = true; # define inline #endif -#ifdef __GNUC__ -#define VISIBLE __attribute__((visibility("default"))) -#else -#define VISIBLE -#endif - /* Size of stack-allocated buffer passed to strerror_r(). */ #define STRERROR_BUF 64 @@ -1119,7 +1117,7 @@ static void wrtmessage(const char *p1, const char *p2, const char *p3, #ifdef MALLOC_STATS #ifdef MOZ_MEMORY_DARWIN /* Avoid namespace collision with OS X's malloc APIs. */ -#define malloc_printf xmalloc_printf +#define malloc_printf moz_malloc_printf #endif static void malloc_printf(const char *format, ...); #endif @@ -5735,14 +5733,28 @@ malloc_shutdown() * Begin malloc(3)-compatible functions. */ -VISIBLE +/* + * Inline the standard malloc functions if they are being subsumed by Darwin's + * zone infrastructure. + */ #ifdef MOZ_MEMORY_DARWIN -inline void * -moz_malloc(size_t size) +# define ZONE_INLINE inline #else +# define ZONE_INLINE +#endif + +/* Mangle standard interfaces on Darwin, in order to avoid linking problems. */ +#ifdef MOZ_MEMORY_DARWIN +#define malloc(a) moz_malloc(a) +#define valloc(a) moz_valloc(a) +#define calloc(a, b) moz_calloc(a, b) +#define realloc(a, b) moz_realloc(a, b) +#define free(a) moz_free(a) +#endif + +ZONE_INLINE void * malloc(size_t size) -#endif { void *ret; @@ -5783,26 +5795,19 @@ RETURN: return (ret); } -#ifdef MOZ_MEMORY_DARWIN -VISIBLE -inline void * -moz_memalign(size_t alignment, size_t size) -#elif (defined(MOZ_MEMORY_SOLARIS)) +#ifdef MOZ_MEMORY_SOLARIS # ifdef __SUNPRO_C void * memalign(size_t alignment, size_t size); #pragma no_inline(memalign) -# elif (defined(__GNU_C__) +# elif (defined(__GNU_C__)) __attribute__((noinline)) # endif -VISIBLE +#else +inline +#endif void * memalign(size_t alignment, size_t size) -#else -VISIBLE -inline void * -memalign(size_t alignment, size_t size) -#endif { void *ret; @@ -5828,14 +5833,9 @@ RETURN: return (ret); } -VISIBLE -#ifdef MOZ_MEMORY_DARWIN -inline int -moz_posix_memalign(void **memptr, size_t alignment, size_t size) -#else +ZONE_INLINE int posix_memalign(void **memptr, size_t alignment, size_t size) -#endif { void *result; @@ -5864,14 +5864,9 @@ posix_memalign(void **memptr, size_t alignment, size_t size) return (0); } -VISIBLE -#ifdef MOZ_MEMORY_DARWIN -inline void * -moz_valloc(size_t size) -#else +ZONE_INLINE void * valloc(size_t size) -#endif { #ifdef MOZ_MEMORY_DARWIN return (moz_memalign(pagesize, size)); @@ -5880,14 +5875,9 @@ valloc(size_t size) #endif } -VISIBLE -#ifdef MOZ_MEMORY_DARWIN -inline void * -moz_calloc(size_t num, size_t size) -#else +ZONE_INLINE void * calloc(size_t num, size_t size) -#endif { void *ret; size_t num_size; @@ -5941,14 +5931,9 @@ RETURN: return (ret); } -VISIBLE -#ifdef MOZ_MEMORY_DARWIN -inline void * -moz_realloc(void *ptr, size_t size) -#else +ZONE_INLINE void * realloc(void *ptr, size_t size) -#endif { void *ret; @@ -6009,14 +5994,9 @@ RETURN: return (ret); } -VISIBLE -#ifdef MOZ_MEMORY_DARWIN -inline void -moz_free(void *ptr) -#else +ZONE_INLINE void free(void *ptr) -#endif { UTRACE(ptr, 0, 0); @@ -6035,14 +6015,8 @@ free(void *ptr) * Begin non-standard functions. */ -VISIBLE -#ifdef MOZ_MEMORY_DARWIN -inline size_t -moz_malloc_usable_size(const void *ptr) -#else size_t malloc_usable_size(const void *ptr) -#endif { #ifdef MALLOC_VALIDATE @@ -6054,6 +6028,121 @@ malloc_usable_size(const void *ptr) #endif } +void +jemalloc_stats(jemalloc_stats_t *stats) +{ + size_t i; + + assert(stats != NULL); + + /* + * Gather runtime settings. + */ + stats->opt_abort = opt_abort; + stats->opt_dss = +#ifdef MALLOC_DSS + opt_dss ? true : +#endif + false; + stats->opt_junk = +#ifdef MALLOC_FILL + opt_junk ? true : +#endif + false; + stats->opt_mmap = +#ifdef MALLOC_DSS + opt_mmap == false ? false : +#endif + true; + stats->opt_utrace = +#ifdef MALLOC_UTRACE + opt_utrace ? true : +#endif + false; + stats->opt_sysv = +#ifdef MALLOC_SYSV + opt_sysv ? true : +#endif + false; + stats->opt_xmalloc = +#ifdef MALLOC_XMALLOC + opt_xmalloc ? true : +#endif + false; + stats->opt_zero = +#ifdef MALLOC_FILL + opt_zero ? true : +#endif + false; + stats->narenas = narenas; + stats->balance_threshold = +#ifdef MALLOC_BALANCE + opt_balance_threshold +#else + SIZE_T_MAX +#endif + ; + stats->quantum = quantum; + stats->small_max = small_max; + stats->large_max = arena_maxclass; + stats->chunksize = chunksize; + stats->dirty_max = opt_dirty_max; + + /* + * Gather current memory usage statistics. + */ + stats->mapped = 0; + stats->committed = 0; + stats->allocated = 0; + stats->dirty = 0; + + /* Get huge mapped/allocated. */ + malloc_mutex_lock(&huge_mtx); + stats->mapped += stats_chunks.curchunks * chunksize; +#ifdef MALLOC_DECOMMIT + stats->committed += huge_allocated; +#endif + stats->allocated += huge_allocated; + malloc_mutex_unlock(&huge_mtx); + + /* Get base mapped. */ + malloc_mutex_lock(&base_mtx); + stats->mapped += base_mapped; +#ifdef MALLOC_DECOMMIT + stats->committed += base_mapped; +#endif + malloc_mutex_unlock(&base_mtx); + + /* Iterate over arenas and their chunks. */ + for (i = 0; i < narenas; i++) { + arena_t *arena = arenas[i]; + if (arena != NULL) { + arena_chunk_t *chunk; + + malloc_spin_lock(&arena->lock); + stats->allocated += arena->stats.allocated_small; + stats->allocated += arena->stats.allocated_large; +#ifdef MALLOC_DECOMMIT + RB_FOREACH(chunk, arena_chunk_tree_s, &arena->chunks) { + size_t j; + + for (j = 0; j < chunk_npages; j++) { + if ((chunk->map[j] & + CHUNK_MAP_DECOMMITTED) == 0) + stats->committed += pagesize; + } + } +#endif + stats->dirty += (arena->ndirty << pagesize_2pow); + malloc_spin_unlock(&arena->lock); + } + } + +#ifndef MALLOC_DECOMMIT + stats->committed = stats->mapped; +#endif +} + #ifdef MOZ_MEMORY_WINDOWS void* _recalloc(void *ptr, size_t count, size_t size) @@ -6187,14 +6276,14 @@ static void * zone_malloc(malloc_zone_t *zone, size_t size) { - return (moz_malloc(size)); + return (malloc(size)); } static void * zone_calloc(malloc_zone_t *zone, size_t num, size_t size) { - return (moz_calloc(num, size)); + return (calloc(num, size)); } static void * @@ -6202,7 +6291,7 @@ zone_valloc(malloc_zone_t *zone, size_t size) { void *ret = NULL; /* Assignment avoids useless compiler warning. */ - moz_posix_memalign(&ret, pagesize, size); + posix_memalign(&ret, pagesize, size); return (ret); } @@ -6211,14 +6300,14 @@ static void zone_free(malloc_zone_t *zone, void *ptr) { - moz_free(ptr); + free(ptr); } static void * zone_realloc(malloc_zone_t *zone, void *ptr, size_t size) { - return (moz_realloc(ptr, size)); + return (realloc(ptr, size)); } static void * @@ -6241,10 +6330,10 @@ zone_good_size(malloc_zone_t *zone, size_t size) * how large it could have been without moving up to the next size * class. */ - p = moz_malloc(size); + p = malloc(size); if (p != NULL) { ret = isalloc(p); - moz_free(p); + free(p); } else ret = size; diff --git a/memory/jemalloc/jemalloc.h b/memory/jemalloc/jemalloc.h new file mode 100644 index 000000000000..da92f2fbd981 --- /dev/null +++ b/memory/jemalloc/jemalloc.h @@ -0,0 +1,57 @@ +#ifndef MOZ_MEMORY_WINDOWS +# include +#else +# include +# ifndef bool +# define bool BOOL +# endif +#endif + +extern const char *_malloc_options; + +/* + * jemalloc_stats() is not a stable interface. When using jemalloc_stats_t, be + * sure that the compiled results of jemalloc.c are in sync with this header + * file. + */ +typedef struct { + /* + * Run-time configuration settings. + */ + bool opt_abort; /* abort(3) on error? */ + bool opt_dss; /* Use sbrk(2) to map memory? */ + bool opt_junk; /* Fill allocated/free memory with 0xa5/0x5a? */ + bool opt_mmap; /* Use mmap(2) to map memory? */ + bool opt_utrace; /* Trace all allocation events? */ + bool opt_sysv; /* SysV semantics? */ + bool opt_xmalloc; /* abort(3) on OOM? */ + bool opt_zero; /* Fill allocated memory with 0x0? */ + size_t narenas; /* Number of arenas. */ + size_t balance_threshold; /* Arena contention rebalance threshold. */ + size_t quantum; /* Allocation quantum. */ + size_t small_max; /* Max quantum-spaced allocation size. */ + size_t large_max; /* Max sub-chunksize allocation size. */ + size_t chunksize; /* Size of each virtual memory mapping. */ + size_t dirty_max; /* Max dirty pages per arena. */ + + /* + * Current memory usage statistics. + */ + size_t mapped; /* Bytes mapped (not necessarily committed). */ + size_t committed; /* Bytes committed (readable/writable). */ + size_t allocated; /* Bytes allocted (in use by application). */ + size_t dirty; /* Bytes dirty (committed unused pages). */ +} jemalloc_stats_t; + +#ifndef MOZ_MEMORY_DARWIN +void *malloc(size_t size); +void *valloc(size_t size); +void *calloc(size_t num, size_t size); +void *realloc(void *ptr, size_t size); +void free(void *ptr); +#endif + +int posix_memalign(void **memptr, size_t alignment, size_t size); +void *memalign(size_t alignment, size_t size); +size_t malloc_usable_size(const void *ptr); +void jemalloc_stats(jemalloc_stats_t *stats); From ce9c15f840ec7c0471e9c610207817d61f4395b1 Mon Sep 17 00:00:00 2001 From: Jason Evans Date: Fri, 20 Jun 2008 10:34:42 -0700 Subject: [PATCH 40/66] Bug 431221: Disable glib slice allocator, r=benjamin Disable glib's slice sub-allocator[1], which is implemented as a zone allocator layered on top of malloc. Since jemalloc is itself a zone allocator, the extra abstraction level forces segregation of equal-sized objects that could otherwise be packed together. [1] http://library.gnome.org/devel/glib/stable/glib-Memory-Slices.html --- toolkit/xre/nsAppRunner.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index 36615cfacb0b..847e20dae677 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -2775,6 +2775,12 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData) #endif #if defined(MOZ_WIDGET_GTK2) +#ifdef MOZ_MEMORY + // Disable the slice allocator, since jemalloc already uses similar layout + // algorithms, and using a sub-allocator tends to increase fragmentation. + // This must be done before g_thread_init() is called. + g_slice_set_config(G_SLICE_CONFIG_ALWAYS_MALLOC, 1); +#endif g_thread_init(NULL); // setup for private colormap. Ideally we'd like to do this // in nsAppShell::Create, but we need to get in before gtk From 4fcf85466361e46e2bf6e9e044460d654ad40517 Mon Sep 17 00:00:00 2001 From: Jason Evans Date: Fri, 20 Jun 2008 10:34:42 -0700 Subject: [PATCH 41/66] Bug 431735: Use rb.h instead of tree.h, r=benjamin Use rb.h instead of tree.h for red-black trees, in order to reduce memory overhead. --- memory/jemalloc/Makefile.in | 7 +- memory/jemalloc/jemalloc.c | 273 +++++----- memory/jemalloc/rb.h | 982 ++++++++++++++++++++++++++++++++++++ memory/jemalloc/tree.h | 743 --------------------------- 4 files changed, 1120 insertions(+), 885 deletions(-) create mode 100644 memory/jemalloc/rb.h delete mode 100644 memory/jemalloc/tree.h diff --git a/memory/jemalloc/Makefile.in b/memory/jemalloc/Makefile.in index 474d9429ab90..ae5e7118a33c 100644 --- a/memory/jemalloc/Makefile.in +++ b/memory/jemalloc/Makefile.in @@ -73,8 +73,8 @@ $(CRT_OBJ_DIR)/jemalloc.c: $(srcdir)/crtsp1.diff $(CRT_OBJ_DIR)/build/intel/mozcrt19.dll: \ $(CRT_OBJ_DIR)/jemalloc.c $(srcdir)/jemalloc.c $(srcdir)/jemalloc.h \ - $(srcdir)/tree.h - cp $(srcdir)/jemalloc.c $(srcdir)/jemalloc.h $(srcdir)/tree.h $(CRT_OBJ_DIR) + $(srcdir)/rb.h + cp $(srcdir)/jemalloc.c $(srcdir)/jemalloc.h $(srcdir)/rb.h $(CRT_OBJ_DIR) # this pretty much sucks, but nmake and make don't play well together $(PYTHON) $(srcdir)/build-crt.py $(CRT_OBJ_DIR) #XXX: these don't link right for some reason @@ -99,6 +99,9 @@ LIBRARY_NAME = jemalloc # Build jemalloc as a shared lib. This is mandatory for Darwin, since a library # init function is used on that platform. FORCE_SHARED_LIB= 1 +# Make C99 variable-length arrays and inline declarations compile without +# warnings. +OS_CFLAGS += -std=c99 -fgnu89-inline CSRCS = \ jemalloc.c \ diff --git a/memory/jemalloc/jemalloc.c b/memory/jemalloc/jemalloc.c index 52286bb1feca..367e3316e4a1 100644 --- a/memory/jemalloc/jemalloc.c +++ b/memory/jemalloc/jemalloc.c @@ -46,7 +46,8 @@ * Allocation requests are rounded up to the nearest size class, and no record * of the original request size is maintained. Allocations are broken into * categories according to size class. Assuming runtime defaults, 4 kB pages - * and a 16 byte quantum, the size classes in each category are as follows: + * and a 16 byte quantum on a 32-bit system, the size classes in each category + * are as follows: * * |=====================================| * | Category | Subcategory | Size | @@ -70,9 +71,9 @@ * | | 8 kB | * | | 12 kB | * | | ... | + * | | 1008 kB | * | | 1012 kB | * | | 1016 kB | - * | | 1020 kB | * |=====================================| * | Huge | 1 MB | * | | 2 MB | @@ -202,7 +203,6 @@ #include #include #include -#include "tree.h" #pragma warning( disable: 4267 4996 4146 ) @@ -253,6 +253,7 @@ typedef unsigned char uint8_t; typedef unsigned uint32_t; typedef unsigned long long uint64_t; typedef unsigned long long uintmax_t; +typedef long ssize_t; #define MALLOC_DECOMMIT #endif @@ -286,10 +287,6 @@ __FBSDID("$FreeBSD: head/lib/libc/stdlib/malloc.c 179704 2008-06-10 15:46:18Z ja #ifndef MOZ_MEMORY_SOLARIS #include #endif -#include "tree.h" -#ifndef MOZ_MEMORY -#include -#endif #include #ifndef MOZ_MEMORY #include /* Must come after several other sys/ includes. */ @@ -359,6 +356,12 @@ static const bool __isthreaded = true; #include #endif +#ifdef MOZ_MEMORY_WINDOWS + /* MSVC++ does not support C99 variable-length arrays. */ +# define RB_NO_C99_VARARRAYS +#endif +#include "rb.h" + #ifdef MALLOC_DEBUG /* Disable inlining to make debugging easier. */ #ifdef inline @@ -676,10 +679,10 @@ struct chunk_stats_s { typedef struct extent_node_s extent_node_t; struct extent_node_s { /* Linkage for the size/address-ordered tree. */ - RB_ENTRY(extent_node_s) link_szad; + rb_node(extent_node_t) link_szad; /* Linkage for the address-ordered tree. */ - RB_ENTRY(extent_node_s) link_ad; + rb_node(extent_node_t) link_ad; /* Pointer to the extent that this tree node is responsible for. */ void *addr; @@ -687,10 +690,7 @@ struct extent_node_s { /* Total region size. */ size_t size; }; -typedef struct extent_tree_szad_s extent_tree_szad_t; -RB_HEAD(extent_tree_szad_s, extent_node_s); -typedef struct extent_tree_ad_s extent_tree_ad_t; -RB_HEAD(extent_tree_ad_s, extent_node_s); +typedef rb_tree(extent_node_t) extent_tree_t; /******************************************************************************/ /* @@ -721,8 +721,8 @@ struct arena_chunk_s { /* Arena that owns the chunk. */ arena_t *arena; - /* Linkage for the arena's chunk tree. */ - RB_ENTRY(arena_chunk_s) link; + /* Linkage for the arena's chunks_all tree. */ + rb_node(arena_chunk_t) link_all; /* * Number of pages in use. This is maintained in order to make @@ -737,7 +737,7 @@ struct arena_chunk_s { * Tree of extent nodes that are embedded in the arena chunk header * page(s). These nodes are used by arena_chunk_node_alloc(). */ - extent_tree_ad_t nodes; + extent_tree_t nodes; extent_node_t *nodes_past; /* @@ -747,13 +747,12 @@ struct arena_chunk_s { */ arena_chunk_map_t map[1]; /* Dynamically sized. */ }; -typedef struct arena_chunk_tree_s arena_chunk_tree_t; -RB_HEAD(arena_chunk_tree_s, arena_chunk_s); +typedef rb_tree(arena_chunk_t) arena_chunk_tree_t; typedef struct arena_run_s arena_run_t; struct arena_run_s { /* Linkage for run trees. */ - RB_ENTRY(arena_run_s) link; + rb_node(arena_run_t) link; #ifdef MALLOC_DEBUG uint32_t magic; @@ -772,8 +771,7 @@ struct arena_run_s { /* Bitmask of in-use regions (0: in use, 1: free). */ unsigned regs_mask[1]; /* Dynamically sized. */ }; -typedef struct arena_run_tree_s arena_run_tree_t; -RB_HEAD(arena_run_tree_s, arena_run_s); +typedef rb_tree(arena_run_t) arena_run_tree_t; struct arena_bin_s { /* @@ -829,10 +827,8 @@ struct arena_s { arena_stats_t stats; #endif - /* - * Tree of chunks this arena manages. - */ - arena_chunk_tree_t chunks; + /* Tree of all chunks this arena manages. */ + arena_chunk_tree_t chunks_all; /* * In order to avoid rapid chunk allocation/deallocation when an arena @@ -859,11 +855,11 @@ struct arena_s { * using one set of nodes, since one is needed for first-best-fit run * allocation, and the other is needed for coalescing. */ - extent_tree_szad_t runs_avail_szad; - extent_tree_ad_t runs_avail_ad; + extent_tree_t runs_avail_szad; + extent_tree_t runs_avail_ad; /* Tree of this arena's allocated (in-use) runs. */ - extent_tree_ad_t runs_alloced_ad; + extent_tree_t runs_alloced_ad; #ifdef MALLOC_BALANCE /* @@ -940,7 +936,7 @@ static size_t arena_maxclass; /* Max size class for arenas. */ static malloc_mutex_t huge_mtx; /* Tree of chunks that are stand-alone huge allocations. */ -static extent_tree_ad_t huge; +static extent_tree_t huge; #ifdef MALLOC_DSS /* @@ -961,8 +957,8 @@ static void *dss_max; * address space. Depending on function, different tree orderings are needed, * which is why there are two trees with the same contents. */ -static extent_tree_szad_t dss_chunks_szad; -static extent_tree_ad_t dss_chunks_ad; +static extent_tree_t dss_chunks_szad; +static extent_tree_t dss_chunks_ad; #endif #ifdef MALLOC_STATS @@ -1971,9 +1967,9 @@ extent_szad_comp(extent_node_t *a, extent_node_t *b) return (ret); } -/* Generate red-black tree code for size/address-ordered extents. */ -RB_GENERATE_STATIC(extent_tree_szad_s, extent_node_s, link_szad, - extent_szad_comp) +/* Wrap red-black tree macros in functions. */ +rb_wrap(static, extent_tree_szad_, extent_tree_t, extent_node_t, + link_szad, extent_szad_comp) static inline int extent_ad_comp(extent_node_t *a, extent_node_t *b) @@ -1984,8 +1980,9 @@ extent_ad_comp(extent_node_t *a, extent_node_t *b) return ((a_addr > b_addr) - (a_addr < b_addr)); } -/* Generate red-black tree code for address-ordered extents. */ -RB_GENERATE_STATIC(extent_tree_ad_s, extent_node_s, link_ad, extent_ad_comp) +/* Wrap red-black tree macros in functions. */ +rb_wrap(static, extent_tree_ad_, extent_tree_t, extent_node_t, link_ad, + extent_ad_comp) /* * End extent tree code. @@ -2185,14 +2182,14 @@ chunk_recycle_dss(size_t size, bool zero) key.addr = NULL; key.size = size; malloc_mutex_lock(&dss_mtx); - node = RB_NFIND(extent_tree_szad_s, &dss_chunks_szad, &key); + node = extent_tree_szad_nsearch(&dss_chunks_szad, &key); if (node != NULL) { void *ret = node->addr; /* Remove node from the tree. */ - RB_REMOVE(extent_tree_szad_s, &dss_chunks_szad, node); + extent_tree_szad_remove(&dss_chunks_szad, node); if (node->size == size) { - RB_REMOVE(extent_tree_ad_s, &dss_chunks_ad, node); + extent_tree_ad_remove(&dss_chunks_ad, node); base_node_dealloc(node); } else { /* @@ -2203,7 +2200,7 @@ chunk_recycle_dss(size_t size, bool zero) assert(node->size > size); node->addr = (void *)((uintptr_t)node->addr + size); node->size -= size; - RB_INSERT(extent_tree_szad_s, &dss_chunks_szad, node); + extent_tree_szad_insert(&dss_chunks_szad, node); } malloc_mutex_unlock(&dss_mtx); @@ -2397,7 +2394,7 @@ chunk_dealloc_dss_record(void *chunk, size_t size) extent_node_t *node, *prev, key; key.addr = (void *)((uintptr_t)chunk + size); - node = RB_NFIND(extent_tree_ad_s, &dss_chunks_ad, &key); + node = extent_tree_ad_nsearch(&dss_chunks_ad, &key); /* Try to coalesce forward. */ if (node != NULL && node->addr == key.addr) { /* @@ -2405,10 +2402,10 @@ chunk_dealloc_dss_record(void *chunk, size_t size) * not change the position within dss_chunks_ad, so only * remove/insert from/into dss_chunks_szad. */ - RB_REMOVE(extent_tree_szad_s, &dss_chunks_szad, node); + extent_tree_szad_remove(&dss_chunks_szad, node); node->addr = chunk; node->size += size; - RB_INSERT(extent_tree_szad_s, &dss_chunks_szad, node); + extent_tree_szad_insert(&dss_chunks_szad, node); } else { /* * Coalescing forward failed, so insert a new node. Drop @@ -2422,12 +2419,12 @@ chunk_dealloc_dss_record(void *chunk, size_t size) return (NULL); node->addr = chunk; node->size = size; - RB_INSERT(extent_tree_ad_s, &dss_chunks_ad, node); - RB_INSERT(extent_tree_szad_s, &dss_chunks_szad, node); + extent_tree_ad_insert(&dss_chunks_ad, node); + extent_tree_szad_insert(&dss_chunks_szad, node); } /* Try to coalesce backward. */ - prev = RB_PREV(extent_tree_ad_s, &dss_chunks_ad, node); + prev = extent_tree_ad_prev(&dss_chunks_ad, node); if (prev != NULL && (void *)((uintptr_t)prev->addr + prev->size) == chunk) { /* @@ -2435,13 +2432,13 @@ chunk_dealloc_dss_record(void *chunk, size_t size) * not change the position within dss_chunks_ad, so only * remove/insert node from/into dss_chunks_szad. */ - RB_REMOVE(extent_tree_szad_s, &dss_chunks_szad, prev); - RB_REMOVE(extent_tree_ad_s, &dss_chunks_ad, prev); + extent_tree_szad_remove(&dss_chunks_szad, prev); + extent_tree_ad_remove(&dss_chunks_ad, prev); - RB_REMOVE(extent_tree_szad_s, &dss_chunks_szad, node); + extent_tree_szad_remove(&dss_chunks_szad, node); node->addr = prev->addr; node->size += prev->size; - RB_INSERT(extent_tree_szad_s, &dss_chunks_szad, node); + extent_tree_szad_insert(&dss_chunks_szad, node); base_node_dealloc(prev); } @@ -2481,10 +2478,8 @@ chunk_dealloc_dss(void *chunk, size_t size) dss_max = (void *)((intptr_t)dss_prev - (intptr_t)size); if (node != NULL) { - RB_REMOVE(extent_tree_szad_s, &dss_chunks_szad, - node); - RB_REMOVE(extent_tree_ad_s, &dss_chunks_ad, - node); + extent_tree_szad_remove(&dss_chunks_szad, node); + extent_tree_ad_remove(&dss_chunks_ad, node); base_node_dealloc(node); } malloc_mutex_unlock(&dss_mtx); @@ -2638,12 +2633,7 @@ choose_arena_hard(void) assert(__isthreaded); #ifdef MALLOC_BALANCE - /* - * Seed the PRNG used for arena load balancing. We can get away with - * using the same seed here as for the lazy_free PRNG without - * introducing autocorrelation because the PRNG parameters are - * distinct. - */ + /* Seed the PRNG used for arena load balancing. */ SPRN(balance, (uint32_t)(uintptr_t)(_pthread_self())); #endif @@ -2690,8 +2680,9 @@ arena_chunk_comp(arena_chunk_t *a, arena_chunk_t *b) return ((a_chunk > b_chunk) - (a_chunk < b_chunk)); } -/* Generate red-black tree code for arena chunks. */ -RB_GENERATE_STATIC(arena_chunk_tree_s, arena_chunk_s, link, arena_chunk_comp) +/* Wrap red-black tree macros in functions. */ +rb_wrap(static, arena_chunk_tree_all_, arena_chunk_tree_t, + arena_chunk_t, link_all, arena_chunk_comp) static inline int arena_run_comp(arena_run_t *a, arena_run_t *b) @@ -2705,17 +2696,18 @@ arena_run_comp(arena_run_t *a, arena_run_t *b) return ((a_run > b_run) - (a_run < b_run)); } -/* Generate red-black tree code for arena runs. */ -RB_GENERATE_STATIC(arena_run_tree_s, arena_run_s, link, arena_run_comp) +/* Wrap red-black tree macros in functions. */ +rb_wrap(static, arena_run_tree_, arena_run_tree_t, arena_run_t, link, + arena_run_comp) static extent_node_t * arena_chunk_node_alloc(arena_chunk_t *chunk) { extent_node_t *ret; - ret = RB_MIN(extent_tree_ad_s, &chunk->nodes); + ret = extent_tree_ad_first(&chunk->nodes); if (ret != NULL) - RB_REMOVE(extent_tree_ad_s, &chunk->nodes, ret); + extent_tree_ad_remove(&chunk->nodes, ret); else { ret = chunk->nodes_past; chunk->nodes_past = (extent_node_t *) @@ -2733,7 +2725,7 @@ arena_chunk_node_dealloc(arena_chunk_t *chunk, extent_node_t *node) { node->addr = (void *)node; - RB_INSERT(extent_tree_ad_s, &chunk->nodes, node); + extent_tree_ad_insert(&chunk->nodes, node); } static inline void * @@ -2912,10 +2904,10 @@ arena_run_split(arena_t *arena, arena_run_t *run, size_t size, bool small, nodeA = arena_chunk_node_alloc(chunk); nodeA->addr = run; nodeA->size = size; - RB_INSERT(extent_tree_ad_s, &arena->runs_alloced_ad, nodeA); + extent_tree_ad_insert(&arena->runs_alloced_ad, nodeA); key.addr = run; - nodeB = RB_FIND(extent_tree_ad_s, &arena->runs_avail_ad, &key); + nodeB = extent_tree_ad_search(&arena->runs_avail_ad, &key); assert(nodeB != NULL); run_ind = (unsigned)(((uintptr_t)run - (uintptr_t)chunk) @@ -2987,7 +2979,7 @@ arena_run_split(arena_t *arena, arena_run_t *run, size_t size, bool small, } /* Keep track of trailing unused pages for later use. */ - RB_REMOVE(extent_tree_szad_s, &arena->runs_avail_szad, nodeB); + extent_tree_szad_remove(&arena->runs_avail_szad, nodeB); if (rem_pages > 0) { /* * Update nodeB in runs_avail_*. Its position within @@ -2995,10 +2987,10 @@ arena_run_split(arena_t *arena, arena_run_t *run, size_t size, bool small, */ nodeB->addr = (void *)((uintptr_t)nodeB->addr + size); nodeB->size -= size; - RB_INSERT(extent_tree_szad_s, &arena->runs_avail_szad, nodeB); + extent_tree_szad_insert(&arena->runs_avail_szad, nodeB); } else { /* Remove nodeB from runs_avail_*. */ - RB_REMOVE(extent_tree_ad_s, &arena->runs_avail_ad, nodeB); + extent_tree_ad_remove(&arena->runs_avail_ad, nodeB); arena_chunk_node_dealloc(chunk, nodeB); } @@ -3026,7 +3018,7 @@ arena_chunk_alloc(arena_t *arena) chunk->arena = arena; - RB_INSERT(arena_chunk_tree_s, &arena->chunks, chunk); + arena_chunk_tree_all_insert(&arena->chunks_all, chunk); /* * Claim that no pages are in use, since the header is merely @@ -3050,7 +3042,7 @@ arena_chunk_alloc(arena_t *arena) arena_chunk_header_npages)); /* Initialize the tree of unused extent nodes. */ - RB_INIT(&chunk->nodes); + extent_tree_ad_new(&chunk->nodes); chunk->nodes_past = (extent_node_t *)QUANTUM_CEILING( (uintptr_t)&chunk->map[chunk_npages]); @@ -3077,8 +3069,8 @@ arena_chunk_alloc(arena_t *arena) node->addr = (void *)((uintptr_t)chunk + (arena_chunk_header_npages << pagesize_2pow)); node->size = chunksize - (arena_chunk_header_npages << pagesize_2pow); - RB_INSERT(extent_tree_szad_s, &arena->runs_avail_szad, node); - RB_INSERT(extent_tree_ad_s, &arena->runs_avail_ad, node); + extent_tree_szad_insert(&arena->runs_avail_szad, node); + extent_tree_ad_insert(&arena->runs_avail_ad, node); return (chunk); } @@ -3089,7 +3081,7 @@ arena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk) extent_node_t *node, key; if (arena->spare != NULL) { - RB_REMOVE(arena_chunk_tree_s, &chunk->arena->chunks, + arena_chunk_tree_all_remove(&chunk->arena->chunks_all, arena->spare); arena->ndirty -= arena->spare->ndirty; VALGRIND_FREELIKE_BLOCK(arena->spare, 0); @@ -3107,10 +3099,10 @@ arena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk) */ key.addr = (void *)((uintptr_t)chunk + (arena_chunk_header_npages << pagesize_2pow)); - node = RB_FIND(extent_tree_ad_s, &arena->runs_avail_ad, &key); + node = extent_tree_ad_search(&arena->runs_avail_ad, &key); assert(node != NULL); - RB_REMOVE(extent_tree_szad_s, &arena->runs_avail_szad, node); - RB_REMOVE(extent_tree_ad_s, &arena->runs_avail_ad, node); + extent_tree_szad_remove(&arena->runs_avail_szad, node); + extent_tree_ad_remove(&arena->runs_avail_ad, node); arena_chunk_node_dealloc(chunk, node); arena->spare = chunk; @@ -3130,7 +3122,7 @@ arena_run_alloc(arena_t *arena, size_t size, bool small, bool zero) /* Search the arena's chunks for the lowest best fit. */ key.addr = NULL; key.size = size; - node = RB_NFIND(extent_tree_szad_s, &arena->runs_avail_szad, &key); + node = extent_tree_szad_nsearch(&arena->runs_avail_szad, &key); if (node != NULL) { run = (arena_run_t *)node->addr; arena_run_split(arena, run, size, small, zero); @@ -3158,9 +3150,9 @@ arena_purge(arena_t *arena) size_t ndirty; ndirty = 0; - RB_FOREACH(chunk, arena_chunk_tree_s, &arena->chunks) { + rb_foreach_begin(arena_chunk_t, link_all, &arena->chunks_all, chunk) { ndirty += chunk->ndirty; - } + } rb_foreach_end(arena_chunk_t, link_all, &arena->chunks_all, chunk) assert(ndirty == arena->ndirty); #endif assert(arena->ndirty > opt_dirty_max); @@ -3173,7 +3165,8 @@ arena_purge(arena_t *arena) * Iterate downward through chunks until enough dirty memory has been * purged. */ - RB_FOREACH_REVERSE(chunk, arena_chunk_tree_s, &arena->chunks) { + rb_foreach_reverse_begin(arena_chunk_t, link_all, &arena->chunks_all, + chunk) { if (chunk->ndirty > 0) { size_t i; @@ -3224,7 +3217,8 @@ arena_purge(arena_t *arena) } } } - } + } rb_foreach_reverse_end(arena_chunk_t, link_all, &arena->chunks_all, + chunk) } static void @@ -3236,9 +3230,9 @@ arena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty) /* Remove run from runs_alloced_ad. */ key.addr = run; - nodeB = RB_FIND(extent_tree_ad_s, &arena->runs_alloced_ad, &key); + nodeB = extent_tree_ad_search(&arena->runs_alloced_ad, &key); assert(nodeB != NULL); - RB_REMOVE(extent_tree_ad_s, &arena->runs_alloced_ad, nodeB); + extent_tree_ad_remove(&arena->runs_alloced_ad, nodeB); size = nodeB->size; chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run); @@ -3276,29 +3270,29 @@ arena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty) /* Try to coalesce forward. */ key.addr = (void *)((uintptr_t)run + size); - nodeC = RB_NFIND(extent_tree_ad_s, &arena->runs_avail_ad, &key); + nodeC = extent_tree_ad_nsearch(&arena->runs_avail_ad, &key); if (nodeC != NULL && nodeC->addr == key.addr) { /* * Coalesce forward. This does not change the position within * runs_avail_ad, so only remove/insert from/into * runs_avail_szad. */ - RB_REMOVE(extent_tree_szad_s, &arena->runs_avail_szad, nodeC); + extent_tree_szad_remove(&arena->runs_avail_szad, nodeC); nodeC->addr = (void *)run; nodeC->size += size; - RB_INSERT(extent_tree_szad_s, &arena->runs_avail_szad, nodeC); + extent_tree_szad_insert(&arena->runs_avail_szad, nodeC); arena_chunk_node_dealloc(chunk, nodeB); nodeB = nodeC; } else { /* * Coalescing forward failed, so insert nodeB into runs_avail_*. */ - RB_INSERT(extent_tree_szad_s, &arena->runs_avail_szad, nodeB); - RB_INSERT(extent_tree_ad_s, &arena->runs_avail_ad, nodeB); + extent_tree_szad_insert(&arena->runs_avail_szad, nodeB); + extent_tree_ad_insert(&arena->runs_avail_ad, nodeB); } /* Try to coalesce backward. */ - nodeA = RB_PREV(extent_tree_ad_s, &arena->runs_avail_ad, nodeB); + nodeA = extent_tree_ad_prev(&arena->runs_avail_ad, nodeB); if (nodeA != NULL && (void *)((uintptr_t)nodeA->addr + nodeA->size) == (void *)run) { /* @@ -3306,13 +3300,13 @@ arena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty) * position within runs_avail_ad, so only remove/insert * from/into runs_avail_szad. */ - RB_REMOVE(extent_tree_szad_s, &arena->runs_avail_szad, nodeA); - RB_REMOVE(extent_tree_ad_s, &arena->runs_avail_ad, nodeA); + extent_tree_szad_remove(&arena->runs_avail_szad, nodeA); + extent_tree_ad_remove(&arena->runs_avail_ad, nodeA); - RB_REMOVE(extent_tree_szad_s, &arena->runs_avail_szad, nodeB); + extent_tree_szad_remove(&arena->runs_avail_szad, nodeB); nodeB->addr = nodeA->addr; nodeB->size += nodeA->size; - RB_INSERT(extent_tree_szad_s, &arena->runs_avail_szad, nodeB); + extent_tree_szad_insert(&arena->runs_avail_szad, nodeB); arena_chunk_node_dealloc(chunk, nodeA); } @@ -3350,7 +3344,7 @@ arena_run_trim_head(arena_t *arena, arena_chunk_t *chunk, extent_node_t *nodeB, nodeA = arena_chunk_node_alloc(chunk); nodeA->addr = (void *)run; nodeA->size = oldsize - newsize; - RB_INSERT(extent_tree_ad_s, &arena->runs_alloced_ad, nodeA); + extent_tree_ad_insert(&arena->runs_alloced_ad, nodeA); arena_run_dalloc(arena, (arena_run_t *)run, false); } @@ -3378,7 +3372,7 @@ arena_run_trim_tail(arena_t *arena, arena_chunk_t *chunk, extent_node_t *nodeA, nodeB = arena_chunk_node_alloc(chunk); nodeB->addr = (void *)((uintptr_t)run + newsize); nodeB->size = oldsize - newsize; - RB_INSERT(extent_tree_ad_s, &arena->runs_alloced_ad, nodeB); + extent_tree_ad_insert(&arena->runs_alloced_ad, nodeB); arena_run_dalloc(arena, (arena_run_t *)((uintptr_t)run + newsize), dirty); @@ -3391,9 +3385,10 @@ arena_bin_nonfull_run_get(arena_t *arena, arena_bin_t *bin) unsigned i, remainder; /* Look for a usable run. */ - if ((run = RB_MIN(arena_run_tree_s, &bin->runs)) != NULL) { + run = arena_run_tree_first(&bin->runs); + if (run != NULL) { /* run is guaranteed to have available space. */ - RB_REMOVE(arena_run_tree_s, &bin->runs, run); + arena_run_tree_remove(&bin->runs, run); #ifdef MALLOC_STATS bin->stats.reruns++; #endif @@ -3786,7 +3781,7 @@ arena_palloc(arena_t *arena, size_t alignment, size_t size, size_t alloc_size) * does not change. */ key.addr = ret; - node = RB_FIND(extent_tree_ad_s, &arena->runs_alloced_ad, &key); + node = extent_tree_ad_search(&arena->runs_alloced_ad, &key); assert(node != NULL); arena_run_trim_tail(arena, chunk, node, ret, alloc_size, size, @@ -3799,7 +3794,7 @@ arena_palloc(arena_t *arena, size_t alignment, size_t size, size_t alloc_size) * does not change. */ key.addr = ret; - node = RB_FIND(extent_tree_ad_s, &arena->runs_alloced_ad, &key); + node = extent_tree_ad_search(&arena->runs_alloced_ad, &key); assert(node != NULL); leadsize = alignment - offset; @@ -3962,7 +3957,7 @@ arena_salloc(const void *ptr) arena = chunk->arena; malloc_spin_lock(&arena->lock); key.addr = (void *)ptr; - node = RB_FIND(extent_tree_ad_s, &arena->runs_alloced_ad, &key); + node = extent_tree_ad_search(&arena->runs_alloced_ad, &key); assert(node != NULL); ret = node->size; malloc_spin_unlock(&arena->lock); @@ -4016,8 +4011,8 @@ isalloc_validate(const void *ptr) if (arena != NULL) { /* Make sure ptr is within a chunk. */ malloc_spin_lock(&arena->lock); - if (RB_FIND(arena_chunk_tree_s, &arena->chunks, - chunk) == chunk) { + if (arena_chunk_tree_all_search( + &arena->chunks_all, chunk) == chunk) { malloc_spin_unlock(&arena->lock); /* * We only lock in arena_salloc() for @@ -4041,7 +4036,7 @@ isalloc_validate(const void *ptr) /* Chunk. */ key.addr = (void *)chunk; malloc_mutex_lock(&huge_mtx); - node = RB_FIND(extent_tree_ad_s, &huge, &key); + node = extent_tree_ad_search(&huge, &key); if (node != NULL) ret = node->size; else @@ -4075,7 +4070,7 @@ isalloc(const void *ptr) /* Extract from tree of huge allocations. */ key.addr = __DECONST(void *, ptr); - node = RB_FIND(extent_tree_ad_s, &huge, &key); + node = extent_tree_ad_search(&huge, &key); assert(node != NULL); ret = node->size; @@ -4119,7 +4114,7 @@ arena_dalloc_small(arena_t *arena, arena_chunk_t *chunk, void *ptr, * run only contains one region, then it never gets * inserted into the non-full runs tree. */ - RB_REMOVE(arena_run_tree_s, &bin->runs, run); + arena_run_tree_remove(&bin->runs, run); } #ifdef MALLOC_DEBUG run->magic = 0; @@ -4140,12 +4135,11 @@ arena_dalloc_small(arena_t *arena, arena_chunk_t *chunk, void *ptr, /* Switch runcur. */ if (bin->runcur->nfree > 0) { /* Insert runcur. */ - RB_INSERT(arena_run_tree_s, &bin->runs, - bin->runcur); + arena_run_tree_insert(&bin->runs, bin->runcur); } bin->runcur = run; } else - RB_INSERT(arena_run_tree_s, &bin->runs, run); + arena_run_tree_insert(&bin->runs, run); } #ifdef MALLOC_STATS arena->stats.allocated_small -= size; @@ -4169,8 +4163,7 @@ arena_dalloc_large(arena_t *arena, arena_chunk_t *chunk, void *ptr) size_t size; key.addr = ptr; - node = RB_FIND(extent_tree_ad_s, - &arena->runs_alloced_ad, &key); + node = extent_tree_ad_search(&arena->runs_alloced_ad, &key); assert(node != NULL); size = node->size; #ifdef MALLOC_FILL @@ -4249,7 +4242,7 @@ arena_ralloc_large_shrink(arena_t *arena, arena_chunk_t *chunk, void *ptr, #else malloc_spin_lock(&arena->lock); #endif - node = RB_FIND(extent_tree_ad_s, &arena->runs_alloced_ad, &key); + node = extent_tree_ad_search(&arena->runs_alloced_ad, &key); assert(node != NULL); arena_run_trim_tail(arena, chunk, node, (arena_run_t *)ptr, oldsize, size, true); @@ -4273,7 +4266,7 @@ arena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk, void *ptr, #else malloc_spin_lock(&arena->lock); #endif - nodeC = RB_FIND(extent_tree_ad_s, &arena->runs_avail_ad, &key); + nodeC = extent_tree_ad_search(&arena->runs_avail_ad, &key); if (nodeC != NULL && oldsize + nodeC->size >= size) { extent_node_t *nodeA, *nodeB; @@ -4288,18 +4281,16 @@ arena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk, void *ptr, oldsize, false, false); key.addr = ptr; - nodeA = RB_FIND(extent_tree_ad_s, &arena->runs_alloced_ad, - &key); + nodeA = extent_tree_ad_search(&arena->runs_alloced_ad, &key); assert(nodeA != NULL); key.addr = (void *)((uintptr_t)ptr + oldsize); - nodeB = RB_FIND(extent_tree_ad_s, &arena->runs_alloced_ad, - &key); + nodeB = extent_tree_ad_search(&arena->runs_alloced_ad, &key); assert(nodeB != NULL); nodeA->size += nodeB->size; - RB_REMOVE(extent_tree_ad_s, &arena->runs_alloced_ad, nodeB); + extent_tree_ad_remove(&arena->runs_alloced_ad, nodeB); arena_chunk_node_dealloc(chunk, nodeB); #ifdef MALLOC_STATS @@ -4470,14 +4461,14 @@ arena_new(arena_t *arena) #endif /* Initialize chunks. */ - RB_INIT(&arena->chunks); + arena_chunk_tree_all_new(&arena->chunks_all); arena->spare = NULL; arena->ndirty = 0; - RB_INIT(&arena->runs_avail_szad); - RB_INIT(&arena->runs_avail_ad); - RB_INIT(&arena->runs_alloced_ad); + extent_tree_szad_new(&arena->runs_avail_szad); + extent_tree_ad_new(&arena->runs_avail_ad); + extent_tree_ad_new(&arena->runs_alloced_ad); #ifdef MALLOC_BALANCE arena->contention = 0; @@ -4490,7 +4481,7 @@ arena_new(arena_t *arena) for (i = 0; i < ntbins; i++) { bin = &arena->bins[i]; bin->runcur = NULL; - RB_INIT(&bin->runs); + arena_run_tree_new(&bin->runs); bin->reg_size = (1U << (TINY_MIN_2POW + i)); @@ -4505,7 +4496,7 @@ arena_new(arena_t *arena) for (; i < ntbins + nqbins; i++) { bin = &arena->bins[i]; bin->runcur = NULL; - RB_INIT(&bin->runs); + arena_run_tree_new(&bin->runs); bin->reg_size = quantum * (i - ntbins + 1); @@ -4521,7 +4512,7 @@ arena_new(arena_t *arena) for (; i < ntbins + nqbins + nsbins; i++) { bin = &arena->bins[i]; bin->runcur = NULL; - RB_INIT(&bin->runs); + arena_run_tree_new(&bin->runs); bin->reg_size = (small_max << (i - (ntbins + nqbins) + 1)); @@ -4615,7 +4606,7 @@ huge_malloc(size_t size, bool zero) #endif malloc_mutex_lock(&huge_mtx); - RB_INSERT(extent_tree_ad_s, &huge, node); + extent_tree_ad_insert(&huge, node); #ifdef MALLOC_STATS huge_nmalloc++; # ifdef MALLOC_DECOMMIT @@ -4758,7 +4749,7 @@ huge_palloc(size_t alignment, size_t size) #endif malloc_mutex_lock(&huge_mtx); - RB_INSERT(extent_tree_ad_s, &huge, node); + extent_tree_ad_insert(&huge, node); #ifdef MALLOC_STATS huge_nmalloc++; # ifdef MALLOC_DECOMMIT @@ -4829,7 +4820,7 @@ huge_ralloc(void *ptr, size_t size, size_t oldsize) /* Update recorded size. */ malloc_mutex_lock(&huge_mtx); key.addr = __DECONST(void *, ptr); - node = RB_FIND(extent_tree_ad_s, &huge, &key); + node = extent_tree_ad_search(&huge, &key); assert(node != NULL); assert(node->size == oldsize); # ifdef MALLOC_STATS @@ -4846,7 +4837,7 @@ huge_ralloc(void *ptr, size_t size, size_t oldsize) /* Update recorded size. */ malloc_mutex_lock(&huge_mtx); key.addr = __DECONST(void *, ptr); - node = RB_FIND(extent_tree_ad_s, &huge, &key); + node = extent_tree_ad_search(&huge, &key); assert(node != NULL); assert(node->size == oldsize); # ifdef MALLOC_STATS @@ -4894,10 +4885,10 @@ huge_dalloc(void *ptr) /* Extract from tree of huge allocations. */ key.addr = ptr; - node = RB_FIND(extent_tree_ad_s, &huge, &key); + node = extent_tree_ad_search(&huge, &key); assert(node != NULL); assert(node->addr == ptr); - RB_REMOVE(extent_tree_ad_s, &huge, node); + extent_tree_ad_remove(&huge, node); #ifdef MALLOC_STATS huge_ndalloc++; @@ -5563,14 +5554,14 @@ MALLOC_OUT: /* Initialize chunks data. */ malloc_mutex_init(&huge_mtx); - RB_INIT(&huge); + extent_tree_ad_new(&huge); #ifdef MALLOC_DSS malloc_mutex_init(&dss_mtx); dss_base = sbrk(0); dss_prev = dss_base; dss_max = dss_base; - RB_INIT(&dss_chunks_szad); - RB_INIT(&dss_chunks_ad); + extent_tree_szad_new(&dss_chunks_szad); + extent_tree_ad_new(&dss_chunks_ad); #endif #ifdef MALLOC_STATS huge_nmalloc = 0; @@ -5700,7 +5691,7 @@ MALLOC_OUT: /* * Seed here for the initial thread, since choose_arena_hard() is only - * called for other threads. The seed values don't really matter. + * called for other threads. The seed value doesn't really matter. */ #ifdef MALLOC_BALANCE SPRN(balance, 42); @@ -6123,7 +6114,8 @@ jemalloc_stats(jemalloc_stats_t *stats) stats->allocated += arena->stats.allocated_small; stats->allocated += arena->stats.allocated_large; #ifdef MALLOC_DECOMMIT - RB_FOREACH(chunk, arena_chunk_tree_s, &arena->chunks) { + rb_foreach_begin(arena_chunk_t, link_all, + &arena->chunks_all, chunk) { size_t j; for (j = 0; j < chunk_npages; j++) { @@ -6131,7 +6123,8 @@ jemalloc_stats(jemalloc_stats_t *stats) CHUNK_MAP_DECOMMITTED) == 0) stats->committed += pagesize; } - } + } rb_foreach_end(arena_chunk_t, link_all, + &arena->chunks_all, chunk) #endif stats->dirty += (arena->ndirty << pagesize_2pow); malloc_spin_unlock(&arena->lock); diff --git a/memory/jemalloc/rb.h b/memory/jemalloc/rb.h new file mode 100644 index 000000000000..43d8569d0052 --- /dev/null +++ b/memory/jemalloc/rb.h @@ -0,0 +1,982 @@ +/****************************************************************************** + * + * Copyright (C) 2008 Jason Evans . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice(s), this list of conditions and the following disclaimer + * unmodified other than the allowable addition of one or more + * copyright notices. + * 2. Redistributions in binary form must reproduce the above copyright + * notice(s), this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + * + * cpp macro implementation of left-leaning red-black trees. + * + * Usage: + * + * (Optional.) + * #define SIZEOF_PTR ... + * #define SIZEOF_PTR_2POW ... + * #define RB_NO_C99_VARARRAYS + * + * (Optional, see assert(3).) + * #define NDEBUG + * + * (Required.) + * #include + * #include + * ... + * + * All operations are done non-recursively. Parent pointers are not used, and + * color bits are stored in the least significant bit of right-child pointers, + * thus making node linkage as compact as is possible for red-black trees. + * + * Some macros use a comparison function pointer, which is expected to have the + * following prototype: + * + * int (a_cmp *)(a_type *a_node, a_type *a_other); + * ^^^^^^ + * or a_key + * + * Interpretation of comparision function return values: + * + * -1 : a_node < a_other + * 0 : a_node == a_other + * 1 : a_node > a_other + * + * In all cases, the a_node or a_key macro argument is the first argument to the + * comparison function, which makes it possible to write comparison functions + * that treat the first argument specially. + * + ******************************************************************************/ + +#ifndef RB_H_ +#define RB_H_ + +#if 0 +#include +__FBSDID("$FreeBSD: head/lib/libc/stdlib/rb.h 178995 2008-05-14 18:33:13Z jasone $"); +#endif + +/* Node structure. */ +#define rb_node(a_type) \ +struct { \ + a_type *rbn_left; \ + a_type *rbn_right_red; \ +} + +/* Root structure. */ +#define rb_tree(a_type) \ +struct { \ + a_type *rbt_root; \ + a_type rbt_nil; \ +} + +/* Left accessors. */ +#define rbp_left_get(a_type, a_field, a_node) \ + ((a_node)->a_field.rbn_left) +#define rbp_left_set(a_type, a_field, a_node, a_left) do { \ + (a_node)->a_field.rbn_left = a_left; \ +} while (0) + +/* Right accessors. */ +#define rbp_right_get(a_type, a_field, a_node) \ + ((a_type *) (((intptr_t) (a_node)->a_field.rbn_right_red) \ + & ((ssize_t)-2))) +#define rbp_right_set(a_type, a_field, a_node, a_right) do { \ + (a_node)->a_field.rbn_right_red = (a_type *) (((uintptr_t) a_right) \ + | (((uintptr_t) (a_node)->a_field.rbn_right_red) & ((size_t)1))); \ +} while (0) + +/* Color accessors. */ +#define rbp_red_get(a_type, a_field, a_node) \ + ((bool) (((uintptr_t) (a_node)->a_field.rbn_right_red) \ + & ((size_t)1))) +#define rbp_color_set(a_type, a_field, a_node, a_red) do { \ + (a_node)->a_field.rbn_right_red = (a_type *) ((((intptr_t) \ + (a_node)->a_field.rbn_right_red) & ((ssize_t)-2)) \ + | ((ssize_t)a_red)); \ +} while (0) +#define rbp_red_set(a_type, a_field, a_node) do { \ + (a_node)->a_field.rbn_right_red = (a_type *) (((uintptr_t) \ + (a_node)->a_field.rbn_right_red) | ((size_t)1)); \ +} while (0) +#define rbp_black_set(a_type, a_field, a_node) do { \ + (a_node)->a_field.rbn_right_red = (a_type *) (((intptr_t) \ + (a_node)->a_field.rbn_right_red) & ((ssize_t)-2)); \ +} while (0) + +/* Node initializer. */ +#define rbp_node_new(a_type, a_field, a_tree, a_node) do { \ + rbp_left_set(a_type, a_field, (a_node), &(a_tree)->rbt_nil); \ + rbp_right_set(a_type, a_field, (a_node), &(a_tree)->rbt_nil); \ + rbp_red_set(a_type, a_field, (a_node)); \ +} while (0) + +/* Tree initializer. */ +#define rb_new(a_type, a_field, a_tree) do { \ + (a_tree)->rbt_root = &(a_tree)->rbt_nil; \ + rbp_node_new(a_type, a_field, a_tree, &(a_tree)->rbt_nil); \ + rbp_black_set(a_type, a_field, &(a_tree)->rbt_nil); \ +} while (0) + +/* Tree operations. */ +#define rbp_black_height(a_type, a_field, a_tree, r_height) do { \ + a_type *rbp_bh_t; \ + for (rbp_bh_t = (a_tree)->rbt_root, (r_height) = 0; \ + rbp_bh_t != &(a_tree)->rbt_nil; \ + rbp_bh_t = rbp_left_get(a_type, a_field, rbp_bh_t)) { \ + if (rbp_red_get(a_type, a_field, rbp_bh_t) == false) { \ + (r_height)++; \ + } \ + } \ +} while (0) + +#define rbp_first(a_type, a_field, a_tree, a_root, r_node) do { \ + for ((r_node) = (a_root); \ + rbp_left_get(a_type, a_field, (r_node)) != &(a_tree)->rbt_nil; \ + (r_node) = rbp_left_get(a_type, a_field, (r_node))) { \ + } \ +} while (0) + +#define rbp_last(a_type, a_field, a_tree, a_root, r_node) do { \ + for ((r_node) = (a_root); \ + rbp_right_get(a_type, a_field, (r_node)) != &(a_tree)->rbt_nil; \ + (r_node) = rbp_right_get(a_type, a_field, (r_node))) { \ + } \ +} while (0) + +#define rbp_next(a_type, a_field, a_cmp, a_tree, a_node, r_node) do { \ + if (rbp_right_get(a_type, a_field, (a_node)) \ + != &(a_tree)->rbt_nil) { \ + rbp_first(a_type, a_field, a_tree, rbp_right_get(a_type, \ + a_field, (a_node)), (r_node)); \ + } else { \ + a_type *rbp_n_t = (a_tree)->rbt_root; \ + assert(rbp_n_t != &(a_tree)->rbt_nil); \ + (r_node) = &(a_tree)->rbt_nil; \ + while (true) { \ + int rbp_n_cmp = (a_cmp)((a_node), rbp_n_t); \ + if (rbp_n_cmp < 0) { \ + (r_node) = rbp_n_t; \ + rbp_n_t = rbp_left_get(a_type, a_field, rbp_n_t); \ + } else if (rbp_n_cmp > 0) { \ + rbp_n_t = rbp_right_get(a_type, a_field, rbp_n_t); \ + } else { \ + break; \ + } \ + assert(rbp_n_t != &(a_tree)->rbt_nil); \ + } \ + } \ +} while (0) + +#define rbp_prev(a_type, a_field, a_cmp, a_tree, a_node, r_node) do { \ + if (rbp_left_get(a_type, a_field, (a_node)) != &(a_tree)->rbt_nil) {\ + rbp_last(a_type, a_field, a_tree, rbp_left_get(a_type, \ + a_field, (a_node)), (r_node)); \ + } else { \ + a_type *rbp_p_t = (a_tree)->rbt_root; \ + assert(rbp_p_t != &(a_tree)->rbt_nil); \ + (r_node) = &(a_tree)->rbt_nil; \ + while (true) { \ + int rbp_p_cmp = (a_cmp)((a_node), rbp_p_t); \ + if (rbp_p_cmp < 0) { \ + rbp_p_t = rbp_left_get(a_type, a_field, rbp_p_t); \ + } else if (rbp_p_cmp > 0) { \ + (r_node) = rbp_p_t; \ + rbp_p_t = rbp_right_get(a_type, a_field, rbp_p_t); \ + } else { \ + break; \ + } \ + assert(rbp_p_t != &(a_tree)->rbt_nil); \ + } \ + } \ +} while (0) + +#define rb_first(a_type, a_field, a_tree, r_node) do { \ + rbp_first(a_type, a_field, a_tree, (a_tree)->rbt_root, (r_node)); \ + if ((r_node) == &(a_tree)->rbt_nil) { \ + (r_node) = NULL; \ + } \ +} while (0) + +#define rb_last(a_type, a_field, a_tree, r_node) do { \ + rbp_last(a_type, a_field, a_tree, (a_tree)->rbt_root, r_node); \ + if ((r_node) == &(a_tree)->rbt_nil) { \ + (r_node) = NULL; \ + } \ +} while (0) + +#define rb_next(a_type, a_field, a_cmp, a_tree, a_node, r_node) do { \ + rbp_next(a_type, a_field, a_cmp, a_tree, (a_node), (r_node)); \ + if ((r_node) == &(a_tree)->rbt_nil) { \ + (r_node) = NULL; \ + } \ +} while (0) + +#define rb_prev(a_type, a_field, a_cmp, a_tree, a_node, r_node) do { \ + rbp_prev(a_type, a_field, a_cmp, a_tree, (a_node), (r_node)); \ + if ((r_node) == &(a_tree)->rbt_nil) { \ + (r_node) = NULL; \ + } \ +} while (0) + +#define rb_search(a_type, a_field, a_cmp, a_tree, a_key, r_node) do { \ + int rbp_se_cmp; \ + (r_node) = (a_tree)->rbt_root; \ + while ((r_node) != &(a_tree)->rbt_nil \ + && (rbp_se_cmp = (a_cmp)((a_key), (r_node))) != 0) { \ + if (rbp_se_cmp < 0) { \ + (r_node) = rbp_left_get(a_type, a_field, (r_node)); \ + } else { \ + (r_node) = rbp_right_get(a_type, a_field, (r_node)); \ + } \ + } \ + if ((r_node) == &(a_tree)->rbt_nil) { \ + (r_node) = NULL; \ + } \ +} while (0) + +/* + * Find a match if it exists. Otherwise, find the next greater node, if one + * exists. + */ +#define rb_nsearch(a_type, a_field, a_cmp, a_tree, a_key, r_node) do { \ + a_type *rbp_ns_t = (a_tree)->rbt_root; \ + (r_node) = NULL; \ + while (rbp_ns_t != &(a_tree)->rbt_nil) { \ + int rbp_ns_cmp = (a_cmp)((a_key), rbp_ns_t); \ + if (rbp_ns_cmp < 0) { \ + (r_node) = rbp_ns_t; \ + rbp_ns_t = rbp_left_get(a_type, a_field, rbp_ns_t); \ + } else if (rbp_ns_cmp > 0) { \ + rbp_ns_t = rbp_right_get(a_type, a_field, rbp_ns_t); \ + } else { \ + (r_node) = rbp_ns_t; \ + break; \ + } \ + } \ +} while (0) + +/* + * Find a match if it exists. Otherwise, find the previous lesser node, if one + * exists. + */ +#define rb_psearch(a_type, a_field, a_cmp, a_tree, a_key, r_node) do { \ + a_type *rbp_ps_t = (a_tree)->rbt_root; \ + (r_node) = NULL; \ + while (rbp_ps_t != &(a_tree)->rbt_nil) { \ + int rbp_ps_cmp = (a_cmp)((a_key), rbp_ps_t); \ + if (rbp_ps_cmp < 0) { \ + rbp_ps_t = rbp_left_get(a_type, a_field, rbp_ps_t); \ + } else if (rbp_ps_cmp > 0) { \ + (r_node) = rbp_ps_t; \ + rbp_ps_t = rbp_right_get(a_type, a_field, rbp_ps_t); \ + } else { \ + (r_node) = rbp_ps_t; \ + break; \ + } \ + } \ +} while (0) + +#define rbp_rotate_left(a_type, a_field, a_node, r_node) do { \ + (r_node) = rbp_right_get(a_type, a_field, (a_node)); \ + rbp_right_set(a_type, a_field, (a_node), \ + rbp_left_get(a_type, a_field, (r_node))); \ + rbp_left_set(a_type, a_field, (r_node), (a_node)); \ +} while (0) + +#define rbp_rotate_right(a_type, a_field, a_node, r_node) do { \ + (r_node) = rbp_left_get(a_type, a_field, (a_node)); \ + rbp_left_set(a_type, a_field, (a_node), \ + rbp_right_get(a_type, a_field, (r_node))); \ + rbp_right_set(a_type, a_field, (r_node), (a_node)); \ +} while (0) + +#define rbp_lean_left(a_type, a_field, a_node, r_node) do { \ + bool rbp_ll_red; \ + rbp_rotate_left(a_type, a_field, (a_node), (r_node)); \ + rbp_ll_red = rbp_red_get(a_type, a_field, (a_node)); \ + rbp_color_set(a_type, a_field, (r_node), rbp_ll_red); \ + rbp_red_set(a_type, a_field, (a_node)); \ +} while (0) + +#define rbp_lean_right(a_type, a_field, a_node, r_node) do { \ + bool rbp_lr_red; \ + rbp_rotate_right(a_type, a_field, (a_node), (r_node)); \ + rbp_lr_red = rbp_red_get(a_type, a_field, (a_node)); \ + rbp_color_set(a_type, a_field, (r_node), rbp_lr_red); \ + rbp_red_set(a_type, a_field, (a_node)); \ +} while (0) + +#define rbp_move_red_left(a_type, a_field, a_node, r_node) do { \ + a_type *rbp_mrl_t, *rbp_mrl_u; \ + rbp_mrl_t = rbp_left_get(a_type, a_field, (a_node)); \ + rbp_red_set(a_type, a_field, rbp_mrl_t); \ + rbp_mrl_t = rbp_right_get(a_type, a_field, (a_node)); \ + rbp_mrl_u = rbp_left_get(a_type, a_field, rbp_mrl_t); \ + if (rbp_red_get(a_type, a_field, rbp_mrl_u)) { \ + rbp_rotate_right(a_type, a_field, rbp_mrl_t, rbp_mrl_u); \ + rbp_right_set(a_type, a_field, (a_node), rbp_mrl_u); \ + rbp_rotate_left(a_type, a_field, (a_node), (r_node)); \ + rbp_mrl_t = rbp_right_get(a_type, a_field, (a_node)); \ + if (rbp_red_get(a_type, a_field, rbp_mrl_t)) { \ + rbp_black_set(a_type, a_field, rbp_mrl_t); \ + rbp_red_set(a_type, a_field, (a_node)); \ + rbp_rotate_left(a_type, a_field, (a_node), rbp_mrl_t); \ + rbp_left_set(a_type, a_field, (r_node), rbp_mrl_t); \ + } else { \ + rbp_black_set(a_type, a_field, (a_node)); \ + } \ + } else { \ + rbp_red_set(a_type, a_field, (a_node)); \ + rbp_rotate_left(a_type, a_field, (a_node), (r_node)); \ + } \ +} while (0) + +#define rbp_move_red_right(a_type, a_field, a_node, r_node) do { \ + a_type *rbp_mrr_t; \ + rbp_mrr_t = rbp_left_get(a_type, a_field, (a_node)); \ + if (rbp_red_get(a_type, a_field, rbp_mrr_t)) { \ + a_type *rbp_mrr_u, *rbp_mrr_v; \ + rbp_mrr_u = rbp_right_get(a_type, a_field, rbp_mrr_t); \ + rbp_mrr_v = rbp_left_get(a_type, a_field, rbp_mrr_u); \ + if (rbp_red_get(a_type, a_field, rbp_mrr_v)) { \ + rbp_color_set(a_type, a_field, rbp_mrr_u, \ + rbp_red_get(a_type, a_field, (a_node))); \ + rbp_black_set(a_type, a_field, rbp_mrr_v); \ + rbp_rotate_left(a_type, a_field, rbp_mrr_t, rbp_mrr_u); \ + rbp_left_set(a_type, a_field, (a_node), rbp_mrr_u); \ + rbp_rotate_right(a_type, a_field, (a_node), (r_node)); \ + rbp_rotate_left(a_type, a_field, (a_node), rbp_mrr_t); \ + rbp_right_set(a_type, a_field, (r_node), rbp_mrr_t); \ + } else { \ + rbp_color_set(a_type, a_field, rbp_mrr_t, \ + rbp_red_get(a_type, a_field, (a_node))); \ + rbp_red_set(a_type, a_field, rbp_mrr_u); \ + rbp_rotate_right(a_type, a_field, (a_node), (r_node)); \ + rbp_rotate_left(a_type, a_field, (a_node), rbp_mrr_t); \ + rbp_right_set(a_type, a_field, (r_node), rbp_mrr_t); \ + } \ + rbp_red_set(a_type, a_field, (a_node)); \ + } else { \ + rbp_red_set(a_type, a_field, rbp_mrr_t); \ + rbp_mrr_t = rbp_left_get(a_type, a_field, rbp_mrr_t); \ + if (rbp_red_get(a_type, a_field, rbp_mrr_t)) { \ + rbp_black_set(a_type, a_field, rbp_mrr_t); \ + rbp_rotate_right(a_type, a_field, (a_node), (r_node)); \ + rbp_rotate_left(a_type, a_field, (a_node), rbp_mrr_t); \ + rbp_right_set(a_type, a_field, (r_node), rbp_mrr_t); \ + } else { \ + rbp_rotate_left(a_type, a_field, (a_node), (r_node)); \ + } \ + } \ +} while (0) + +#define rb_insert(a_type, a_field, a_cmp, a_tree, a_node) do { \ + a_type rbp_i_s; \ + a_type *rbp_i_g, *rbp_i_p, *rbp_i_c, *rbp_i_t, *rbp_i_u; \ + int rbp_i_cmp = 0; \ + rbp_i_g = &(a_tree)->rbt_nil; \ + rbp_left_set(a_type, a_field, &rbp_i_s, (a_tree)->rbt_root); \ + rbp_right_set(a_type, a_field, &rbp_i_s, &(a_tree)->rbt_nil); \ + rbp_black_set(a_type, a_field, &rbp_i_s); \ + rbp_i_p = &rbp_i_s; \ + rbp_i_c = (a_tree)->rbt_root; \ + /* Iteratively search down the tree for the insertion point, */\ + /* splitting 4-nodes as they are encountered. At the end of each */\ + /* iteration, rbp_i_g->rbp_i_p->rbp_i_c is a 3-level path down */\ + /* the tree, assuming a sufficiently deep tree. */\ + while (rbp_i_c != &(a_tree)->rbt_nil) { \ + rbp_i_t = rbp_left_get(a_type, a_field, rbp_i_c); \ + rbp_i_u = rbp_left_get(a_type, a_field, rbp_i_t); \ + if (rbp_red_get(a_type, a_field, rbp_i_t) \ + && rbp_red_get(a_type, a_field, rbp_i_u)) { \ + /* rbp_i_c is the top of a logical 4-node, so split it. */\ + /* This iteration does not move down the tree, due to the */\ + /* disruptiveness of node splitting. */\ + /* */\ + /* Rotate right. */\ + rbp_rotate_right(a_type, a_field, rbp_i_c, rbp_i_t); \ + /* Pass red links up one level. */\ + rbp_i_u = rbp_left_get(a_type, a_field, rbp_i_t); \ + rbp_black_set(a_type, a_field, rbp_i_u); \ + if (rbp_left_get(a_type, a_field, rbp_i_p) == rbp_i_c) { \ + rbp_left_set(a_type, a_field, rbp_i_p, rbp_i_t); \ + rbp_i_c = rbp_i_t; \ + } else { \ + /* rbp_i_c was the right child of rbp_i_p, so rotate */\ + /* left in order to maintain the left-leaning */\ + /* invariant. */\ + assert(rbp_right_get(a_type, a_field, rbp_i_p) \ + == rbp_i_c); \ + rbp_right_set(a_type, a_field, rbp_i_p, rbp_i_t); \ + rbp_lean_left(a_type, a_field, rbp_i_p, rbp_i_u); \ + if (rbp_left_get(a_type, a_field, rbp_i_g) == rbp_i_p) {\ + rbp_left_set(a_type, a_field, rbp_i_g, rbp_i_u); \ + } else { \ + assert(rbp_right_get(a_type, a_field, rbp_i_g) \ + == rbp_i_p); \ + rbp_right_set(a_type, a_field, rbp_i_g, rbp_i_u); \ + } \ + rbp_i_p = rbp_i_u; \ + rbp_i_cmp = (a_cmp)((a_node), rbp_i_p); \ + if (rbp_i_cmp < 0) { \ + rbp_i_c = rbp_left_get(a_type, a_field, rbp_i_p); \ + } else { \ + assert(rbp_i_cmp > 0); \ + rbp_i_c = rbp_right_get(a_type, a_field, rbp_i_p); \ + } \ + continue; \ + } \ + } \ + rbp_i_g = rbp_i_p; \ + rbp_i_p = rbp_i_c; \ + rbp_i_cmp = (a_cmp)((a_node), rbp_i_c); \ + if (rbp_i_cmp < 0) { \ + rbp_i_c = rbp_left_get(a_type, a_field, rbp_i_c); \ + } else { \ + assert(rbp_i_cmp > 0); \ + rbp_i_c = rbp_right_get(a_type, a_field, rbp_i_c); \ + } \ + } \ + /* rbp_i_p now refers to the node under which to insert. */\ + rbp_node_new(a_type, a_field, a_tree, (a_node)); \ + if (rbp_i_cmp > 0) { \ + rbp_right_set(a_type, a_field, rbp_i_p, (a_node)); \ + rbp_lean_left(a_type, a_field, rbp_i_p, rbp_i_t); \ + if (rbp_left_get(a_type, a_field, rbp_i_g) == rbp_i_p) { \ + rbp_left_set(a_type, a_field, rbp_i_g, rbp_i_t); \ + } else if (rbp_right_get(a_type, a_field, rbp_i_g) == rbp_i_p) {\ + rbp_right_set(a_type, a_field, rbp_i_g, rbp_i_t); \ + } \ + } else { \ + rbp_left_set(a_type, a_field, rbp_i_p, (a_node)); \ + } \ + /* Update the root and make sure that it is black. */\ + (a_tree)->rbt_root = rbp_left_get(a_type, a_field, &rbp_i_s); \ + rbp_black_set(a_type, a_field, (a_tree)->rbt_root); \ +} while (0) + +#define rb_remove(a_type, a_field, a_cmp, a_tree, a_node) do { \ + a_type rbp_r_s; \ + a_type *rbp_r_p, *rbp_r_c, *rbp_r_xp, *rbp_r_t, *rbp_r_u; \ + int rbp_r_cmp; \ + rbp_left_set(a_type, a_field, &rbp_r_s, (a_tree)->rbt_root); \ + rbp_right_set(a_type, a_field, &rbp_r_s, &(a_tree)->rbt_nil); \ + rbp_black_set(a_type, a_field, &rbp_r_s); \ + rbp_r_p = &rbp_r_s; \ + rbp_r_c = (a_tree)->rbt_root; \ + rbp_r_xp = &(a_tree)->rbt_nil; \ + /* Iterate down the tree, but always transform 2-nodes to 3- or */\ + /* 4-nodes in order to maintain the invariant that the current */\ + /* node is not a 2-node. This allows simple deletion once a leaf */\ + /* is reached. Handle the root specially though, since there may */\ + /* be no way to convert it from a 2-node to a 3-node. */\ + rbp_r_cmp = (a_cmp)((a_node), rbp_r_c); \ + if (rbp_r_cmp < 0) { \ + rbp_r_t = rbp_left_get(a_type, a_field, rbp_r_c); \ + rbp_r_u = rbp_left_get(a_type, a_field, rbp_r_t); \ + if (rbp_red_get(a_type, a_field, rbp_r_t) == false \ + && rbp_red_get(a_type, a_field, rbp_r_u) == false) { \ + /* Apply standard transform to prepare for left move. */\ + rbp_move_red_left(a_type, a_field, rbp_r_c, rbp_r_t); \ + rbp_black_set(a_type, a_field, rbp_r_t); \ + rbp_left_set(a_type, a_field, rbp_r_p, rbp_r_t); \ + rbp_r_c = rbp_r_t; \ + } else { \ + /* Move left. */\ + rbp_r_p = rbp_r_c; \ + rbp_r_c = rbp_left_get(a_type, a_field, rbp_r_c); \ + } \ + } else { \ + if (rbp_r_cmp == 0) { \ + assert((a_node) == rbp_r_c); \ + if (rbp_right_get(a_type, a_field, rbp_r_c) \ + == &(a_tree)->rbt_nil) { \ + /* Delete root node (which is also a leaf node). */\ + if (rbp_left_get(a_type, a_field, rbp_r_c) \ + != &(a_tree)->rbt_nil) { \ + rbp_lean_right(a_type, a_field, rbp_r_c, rbp_r_t); \ + rbp_right_set(a_type, a_field, rbp_r_t, \ + &(a_tree)->rbt_nil); \ + } else { \ + rbp_r_t = &(a_tree)->rbt_nil; \ + } \ + rbp_left_set(a_type, a_field, rbp_r_p, rbp_r_t); \ + } else { \ + /* This is the node we want to delete, but we will */\ + /* instead swap it with its successor and delete the */\ + /* successor. Record enough information to do the */\ + /* swap later. rbp_r_xp is the a_node's parent. */\ + rbp_r_xp = rbp_r_p; \ + rbp_r_cmp = 1; /* Note that deletion is incomplete. */\ + } \ + } \ + if (rbp_r_cmp == 1) { \ + if (rbp_red_get(a_type, a_field, rbp_left_get(a_type, \ + a_field, rbp_right_get(a_type, a_field, rbp_r_c))) \ + == false) { \ + rbp_r_t = rbp_left_get(a_type, a_field, rbp_r_c); \ + if (rbp_red_get(a_type, a_field, rbp_r_t)) { \ + /* Standard transform. */\ + rbp_move_red_right(a_type, a_field, rbp_r_c, \ + rbp_r_t); \ + } else { \ + /* Root-specific transform. */\ + rbp_red_set(a_type, a_field, rbp_r_c); \ + rbp_r_u = rbp_left_get(a_type, a_field, rbp_r_t); \ + if (rbp_red_get(a_type, a_field, rbp_r_u)) { \ + rbp_black_set(a_type, a_field, rbp_r_u); \ + rbp_rotate_right(a_type, a_field, rbp_r_c, \ + rbp_r_t); \ + rbp_rotate_left(a_type, a_field, rbp_r_c, \ + rbp_r_u); \ + rbp_right_set(a_type, a_field, rbp_r_t, \ + rbp_r_u); \ + } else { \ + rbp_red_set(a_type, a_field, rbp_r_t); \ + rbp_rotate_left(a_type, a_field, rbp_r_c, \ + rbp_r_t); \ + } \ + } \ + rbp_left_set(a_type, a_field, rbp_r_p, rbp_r_t); \ + rbp_r_c = rbp_r_t; \ + } else { \ + /* Move right. */\ + rbp_r_p = rbp_r_c; \ + rbp_r_c = rbp_right_get(a_type, a_field, rbp_r_c); \ + } \ + } \ + } \ + if (rbp_r_cmp != 0) { \ + while (true) { \ + assert(rbp_r_p != &(a_tree)->rbt_nil); \ + rbp_r_cmp = (a_cmp)((a_node), rbp_r_c); \ + if (rbp_r_cmp < 0) { \ + rbp_r_t = rbp_left_get(a_type, a_field, rbp_r_c); \ + if (rbp_r_t == &(a_tree)->rbt_nil) { \ + /* rbp_r_c now refers to the successor node to */\ + /* relocate, and rbp_r_xp/a_node refer to the */\ + /* context for the relocation. */\ + if (rbp_left_get(a_type, a_field, rbp_r_xp) \ + == (a_node)) { \ + rbp_left_set(a_type, a_field, rbp_r_xp, \ + rbp_r_c); \ + } else { \ + assert(rbp_right_get(a_type, a_field, \ + rbp_r_xp) == (a_node)); \ + rbp_right_set(a_type, a_field, rbp_r_xp, \ + rbp_r_c); \ + } \ + rbp_left_set(a_type, a_field, rbp_r_c, \ + rbp_left_get(a_type, a_field, (a_node))); \ + rbp_right_set(a_type, a_field, rbp_r_c, \ + rbp_right_get(a_type, a_field, (a_node))); \ + rbp_color_set(a_type, a_field, rbp_r_c, \ + rbp_red_get(a_type, a_field, (a_node))); \ + if (rbp_left_get(a_type, a_field, rbp_r_p) \ + == rbp_r_c) { \ + rbp_left_set(a_type, a_field, rbp_r_p, \ + &(a_tree)->rbt_nil); \ + } else { \ + assert(rbp_right_get(a_type, a_field, rbp_r_p) \ + == rbp_r_c); \ + rbp_right_set(a_type, a_field, rbp_r_p, \ + &(a_tree)->rbt_nil); \ + } \ + break; \ + } \ + rbp_r_u = rbp_left_get(a_type, a_field, rbp_r_t); \ + if (rbp_red_get(a_type, a_field, rbp_r_t) == false \ + && rbp_red_get(a_type, a_field, rbp_r_u) == false) { \ + rbp_move_red_left(a_type, a_field, rbp_r_c, \ + rbp_r_t); \ + if (rbp_left_get(a_type, a_field, rbp_r_p) \ + == rbp_r_c) { \ + rbp_left_set(a_type, a_field, rbp_r_p, rbp_r_t);\ + } else { \ + rbp_right_set(a_type, a_field, rbp_r_p, \ + rbp_r_t); \ + } \ + rbp_r_c = rbp_r_t; \ + } else { \ + rbp_r_p = rbp_r_c; \ + rbp_r_c = rbp_left_get(a_type, a_field, rbp_r_c); \ + } \ + } else { \ + /* Check whether to delete this node (it has to be */\ + /* the correct node and a leaf node). */\ + if (rbp_r_cmp == 0) { \ + assert((a_node) == rbp_r_c); \ + if (rbp_right_get(a_type, a_field, rbp_r_c) \ + == &(a_tree)->rbt_nil) { \ + /* Delete leaf node. */\ + if (rbp_left_get(a_type, a_field, rbp_r_c) \ + != &(a_tree)->rbt_nil) { \ + rbp_lean_right(a_type, a_field, rbp_r_c, \ + rbp_r_t); \ + rbp_right_set(a_type, a_field, rbp_r_t, \ + &(a_tree)->rbt_nil); \ + } else { \ + rbp_r_t = &(a_tree)->rbt_nil; \ + } \ + if (rbp_left_get(a_type, a_field, rbp_r_p) \ + == rbp_r_c) { \ + rbp_left_set(a_type, a_field, rbp_r_p, \ + rbp_r_t); \ + } else { \ + rbp_right_set(a_type, a_field, rbp_r_p, \ + rbp_r_t); \ + } \ + break; \ + } else { \ + /* This is the node we want to delete, but we */\ + /* will instead swap it with its successor */\ + /* and delete the successor. Record enough */\ + /* information to do the swap later. */\ + /* rbp_r_xp is a_node's parent. */\ + rbp_r_xp = rbp_r_p; \ + } \ + } \ + rbp_r_t = rbp_right_get(a_type, a_field, rbp_r_c); \ + rbp_r_u = rbp_left_get(a_type, a_field, rbp_r_t); \ + if (rbp_red_get(a_type, a_field, rbp_r_u) == false) { \ + rbp_move_red_right(a_type, a_field, rbp_r_c, \ + rbp_r_t); \ + if (rbp_left_get(a_type, a_field, rbp_r_p) \ + == rbp_r_c) { \ + rbp_left_set(a_type, a_field, rbp_r_p, rbp_r_t);\ + } else { \ + rbp_right_set(a_type, a_field, rbp_r_p, \ + rbp_r_t); \ + } \ + rbp_r_c = rbp_r_t; \ + } else { \ + rbp_r_p = rbp_r_c; \ + rbp_r_c = rbp_right_get(a_type, a_field, rbp_r_c); \ + } \ + } \ + } \ + } \ + /* Update root. */\ + (a_tree)->rbt_root = rbp_left_get(a_type, a_field, &rbp_r_s); \ +} while (0) + +/* + * The rb_wrap() macro provides a convenient way to wrap functions around the + * cpp macros. The main benefits of wrapping are that 1) repeated macro + * expansion can cause code bloat, especially for rb_{insert,remove)(), and + * 2) type, linkage, comparison functions, etc. need not be specified at every + * call point. + */ + +#define rb_wrap(a_attr, a_prefix, a_tree_type, a_type, a_field, a_cmp) \ +a_attr void \ +a_prefix##new(a_tree_type *tree) { \ + rb_new(a_type, a_field, tree); \ +} \ +a_attr a_type * \ +a_prefix##first(a_tree_type *tree) { \ + a_type *ret; \ + rb_first(a_type, a_field, tree, ret); \ + return (ret); \ +} \ +a_attr a_type * \ +a_prefix##last(a_tree_type *tree) { \ + a_type *ret; \ + rb_last(a_type, a_field, tree, ret); \ + return (ret); \ +} \ +a_attr a_type * \ +a_prefix##next(a_tree_type *tree, a_type *node) { \ + a_type *ret; \ + rb_next(a_type, a_field, a_cmp, tree, node, ret); \ + return (ret); \ +} \ +a_attr a_type * \ +a_prefix##prev(a_tree_type *tree, a_type *node) { \ + a_type *ret; \ + rb_prev(a_type, a_field, a_cmp, tree, node, ret); \ + return (ret); \ +} \ +a_attr a_type * \ +a_prefix##search(a_tree_type *tree, a_type *key) { \ + a_type *ret; \ + rb_search(a_type, a_field, a_cmp, tree, key, ret); \ + return (ret); \ +} \ +a_attr a_type * \ +a_prefix##nsearch(a_tree_type *tree, a_type *key) { \ + a_type *ret; \ + rb_nsearch(a_type, a_field, a_cmp, tree, key, ret); \ + return (ret); \ +} \ +a_attr a_type * \ +a_prefix##psearch(a_tree_type *tree, a_type *key) { \ + a_type *ret; \ + rb_psearch(a_type, a_field, a_cmp, tree, key, ret); \ + return (ret); \ +} \ +a_attr void \ +a_prefix##insert(a_tree_type *tree, a_type *node) { \ + rb_insert(a_type, a_field, a_cmp, tree, node); \ +} \ +a_attr void \ +a_prefix##remove(a_tree_type *tree, a_type *node) { \ + rb_remove(a_type, a_field, a_cmp, tree, node); \ +} + +/* + * The iterators simulate recursion via an array of pointers that store the + * current path. This is critical to performance, since a series of calls to + * rb_{next,prev}() would require time proportional to (n lg n), whereas this + * implementation only requires time proportional to (n). + * + * Since the iterators cache a path down the tree, any tree modification may + * cause the cached path to become invalid. In order to continue iteration, + * use something like the following sequence: + * + * { + * a_type *node, *tnode; + * + * rb_foreach_begin(a_type, a_field, a_tree, node) { + * ... + * rb_next(a_type, a_field, a_cmp, a_tree, node, tnode); + * rb_remove(a_type, a_field, a_cmp, a_tree, node); + * rb_foreach_next(a_type, a_field, a_cmp, a_tree, tnode); + * ... + * } rb_foreach_end(a_type, a_field, a_tree, node) + * } + * + * Note that this idiom is not advised if every iteration modifies the tree, + * since in that case there is no algorithmic complexity improvement over a + * series of rb_{next,prev}() calls, thus making the setup overhead wasted + * effort. + */ + +#ifdef RB_NO_C99_VARARRAYS + /* + * Avoid using variable-length arrays, at the cost of using more stack space. + * Size the path arrays such that they are always large enough, even if a + * tree consumes all of memory. Since each node must contain a minimum of + * two pointers, there can never be more nodes than: + * + * 1 << ((SIZEOF_PTR<<3) - (SIZEOF_PTR_2POW+1)) + * + * Since the depth of a tree is limited to 3*lg(#nodes), the maximum depth + * is: + * + * (3 * ((SIZEOF_PTR<<3) - (SIZEOF_PTR_2POW+1))) + * + * This works out to a maximum depth of 87 and 180 for 32- and 64-bit + * systems, respectively (approximatly 348 and 1440 bytes, respectively). + */ +# define rbp_compute_f_height(a_type, a_field, a_tree) +# define rbp_f_height (3 * ((SIZEOF_PTR<<3) - (SIZEOF_PTR_2POW+1))) +# define rbp_compute_fr_height(a_type, a_field, a_tree) +# define rbp_fr_height (3 * ((SIZEOF_PTR<<3) - (SIZEOF_PTR_2POW+1))) +#else +# define rbp_compute_f_height(a_type, a_field, a_tree) \ + /* Compute the maximum possible tree depth (3X the black height). */\ + unsigned rbp_f_height; \ + rbp_black_height(a_type, a_field, a_tree, rbp_f_height); \ + rbp_f_height *= 3; +# define rbp_compute_fr_height(a_type, a_field, a_tree) \ + /* Compute the maximum possible tree depth (3X the black height). */\ + unsigned rbp_fr_height; \ + rbp_black_height(a_type, a_field, a_tree, rbp_fr_height); \ + rbp_fr_height *= 3; +#endif + +#define rb_foreach_begin(a_type, a_field, a_tree, a_var) { \ + rbp_compute_f_height(a_type, a_field, a_tree) \ + { \ + /* Initialize the path to contain the left spine. */\ + a_type *rbp_f_path[rbp_f_height]; \ + a_type *rbp_f_node; \ + bool rbp_f_synced = false; \ + unsigned rbp_f_depth = 0; \ + if ((a_tree)->rbt_root != &(a_tree)->rbt_nil) { \ + rbp_f_path[rbp_f_depth] = (a_tree)->rbt_root; \ + rbp_f_depth++; \ + while ((rbp_f_node = rbp_left_get(a_type, a_field, \ + rbp_f_path[rbp_f_depth-1])) != &(a_tree)->rbt_nil) { \ + rbp_f_path[rbp_f_depth] = rbp_f_node; \ + rbp_f_depth++; \ + } \ + } \ + /* While the path is non-empty, iterate. */\ + while (rbp_f_depth > 0) { \ + (a_var) = rbp_f_path[rbp_f_depth-1]; + +/* Only use if modifying the tree during iteration. */ +#define rb_foreach_next(a_type, a_field, a_cmp, a_tree, a_node) \ + /* Re-initialize the path to contain the path to a_node. */\ + rbp_f_depth = 0; \ + if (a_node != NULL) { \ + if ((a_tree)->rbt_root != &(a_tree)->rbt_nil) { \ + rbp_f_path[rbp_f_depth] = (a_tree)->rbt_root; \ + rbp_f_depth++; \ + rbp_f_node = rbp_f_path[0]; \ + while (true) { \ + int rbp_f_cmp = (a_cmp)((a_node), \ + rbp_f_path[rbp_f_depth-1]); \ + if (rbp_f_cmp < 0) { \ + rbp_f_node = rbp_left_get(a_type, a_field, \ + rbp_f_path[rbp_f_depth-1]); \ + } else if (rbp_f_cmp > 0) { \ + rbp_f_node = rbp_right_get(a_type, a_field, \ + rbp_f_path[rbp_f_depth-1]); \ + } else { \ + break; \ + } \ + assert(rbp_f_node != &(a_tree)->rbt_nil); \ + rbp_f_path[rbp_f_depth] = rbp_f_node; \ + rbp_f_depth++; \ + } \ + } \ + } \ + rbp_f_synced = true; + +#define rb_foreach_end(a_type, a_field, a_tree, a_var) \ + if (rbp_f_synced) { \ + rbp_f_synced = false; \ + continue; \ + } \ + /* Find the successor. */\ + if ((rbp_f_node = rbp_right_get(a_type, a_field, \ + rbp_f_path[rbp_f_depth-1])) != &(a_tree)->rbt_nil) { \ + /* The successor is the left-most node in the right */\ + /* subtree. */\ + rbp_f_path[rbp_f_depth] = rbp_f_node; \ + rbp_f_depth++; \ + while ((rbp_f_node = rbp_left_get(a_type, a_field, \ + rbp_f_path[rbp_f_depth-1])) != &(a_tree)->rbt_nil) { \ + rbp_f_path[rbp_f_depth] = rbp_f_node; \ + rbp_f_depth++; \ + } \ + } else { \ + /* The successor is above the current node. Unwind */\ + /* until a left-leaning edge is removed from the */\ + /* path, or the path is empty. */\ + for (rbp_f_depth--; rbp_f_depth > 0; rbp_f_depth--) { \ + if (rbp_left_get(a_type, a_field, \ + rbp_f_path[rbp_f_depth-1]) \ + == rbp_f_path[rbp_f_depth]) { \ + break; \ + } \ + } \ + } \ + } \ + } \ +} + +#define rb_foreach_reverse_begin(a_type, a_field, a_tree, a_var) { \ + rbp_compute_fr_height(a_type, a_field, a_tree) \ + { \ + /* Initialize the path to contain the right spine. */\ + a_type *rbp_fr_path[rbp_fr_height]; \ + a_type *rbp_fr_node; \ + bool rbp_fr_synced = false; \ + unsigned rbp_fr_depth = 0; \ + if ((a_tree)->rbt_root != &(a_tree)->rbt_nil) { \ + rbp_fr_path[rbp_fr_depth] = (a_tree)->rbt_root; \ + rbp_fr_depth++; \ + while ((rbp_fr_node = rbp_right_get(a_type, a_field, \ + rbp_fr_path[rbp_fr_depth-1])) != &(a_tree)->rbt_nil) { \ + rbp_fr_path[rbp_fr_depth] = rbp_fr_node; \ + rbp_fr_depth++; \ + } \ + } \ + /* While the path is non-empty, iterate. */\ + while (rbp_fr_depth > 0) { \ + (a_var) = rbp_fr_path[rbp_fr_depth-1]; + +/* Only use if modifying the tree during iteration. */ +#define rb_foreach_reverse_prev(a_type, a_field, a_cmp, a_tree, a_node) \ + /* Re-initialize the path to contain the path to a_node. */\ + rbp_fr_depth = 0; \ + if (a_node != NULL) { \ + if ((a_tree)->rbt_root != &(a_tree)->rbt_nil) { \ + rbp_fr_path[rbp_fr_depth] = (a_tree)->rbt_root; \ + rbp_fr_depth++; \ + rbp_fr_node = rbp_fr_path[0]; \ + while (true) { \ + int rbp_fr_cmp = (a_cmp)((a_node), \ + rbp_fr_path[rbp_fr_depth-1]); \ + if (rbp_fr_cmp < 0) { \ + rbp_fr_node = rbp_left_get(a_type, a_field, \ + rbp_fr_path[rbp_fr_depth-1]); \ + } else if (rbp_fr_cmp > 0) { \ + rbp_fr_node = rbp_right_get(a_type, a_field,\ + rbp_fr_path[rbp_fr_depth-1]); \ + } else { \ + break; \ + } \ + assert(rbp_fr_node != &(a_tree)->rbt_nil); \ + rbp_fr_path[rbp_fr_depth] = rbp_fr_node; \ + rbp_fr_depth++; \ + } \ + } \ + } \ + rbp_fr_synced = true; + +#define rb_foreach_reverse_end(a_type, a_field, a_tree, a_var) \ + if (rbp_fr_synced) { \ + rbp_fr_synced = false; \ + continue; \ + } \ + if (rbp_fr_depth == 0) { \ + /* rb_foreach_reverse_sync() was called with a NULL */\ + /* a_node. */\ + break; \ + } \ + /* Find the predecessor. */\ + if ((rbp_fr_node = rbp_left_get(a_type, a_field, \ + rbp_fr_path[rbp_fr_depth-1])) != &(a_tree)->rbt_nil) { \ + /* The predecessor is the right-most node in the left */\ + /* subtree. */\ + rbp_fr_path[rbp_fr_depth] = rbp_fr_node; \ + rbp_fr_depth++; \ + while ((rbp_fr_node = rbp_right_get(a_type, a_field, \ + rbp_fr_path[rbp_fr_depth-1])) != &(a_tree)->rbt_nil) {\ + rbp_fr_path[rbp_fr_depth] = rbp_fr_node; \ + rbp_fr_depth++; \ + } \ + } else { \ + /* The predecessor is above the current node. Unwind */\ + /* until a right-leaning edge is removed from the */\ + /* path, or the path is empty. */\ + for (rbp_fr_depth--; rbp_fr_depth > 0; rbp_fr_depth--) {\ + if (rbp_right_get(a_type, a_field, \ + rbp_fr_path[rbp_fr_depth-1]) \ + == rbp_fr_path[rbp_fr_depth]) { \ + break; \ + } \ + } \ + } \ + } \ + } \ +} + +#endif /* RB_H_ */ diff --git a/memory/jemalloc/tree.h b/memory/jemalloc/tree.h deleted file mode 100644 index c9ef3894fe72..000000000000 --- a/memory/jemalloc/tree.h +++ /dev/null @@ -1,743 +0,0 @@ -/* $NetBSD: tree.h,v 1.8 2004/03/28 19:38:30 provos Exp $ */ -/* $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $ */ -/* $FreeBSD: src/sys/sys/tree.h,v 1.7 2007/12/28 07:03:26 jasone Exp $ */ - -/*- - * Copyright 2002 Niels Provos - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SYS_TREE_H_ -#define _SYS_TREE_H_ - -/* - * This file defines data structures for different types of trees: - * splay trees and red-black trees. - * - * A splay tree is a self-organizing data structure. Every operation - * on the tree causes a splay to happen. The splay moves the requested - * node to the root of the tree and partly rebalances it. - * - * This has the benefit that request locality causes faster lookups as - * the requested nodes move to the top of the tree. On the other hand, - * every lookup causes memory writes. - * - * The Balance Theorem bounds the total access time for m operations - * and n inserts on an initially empty tree as O((m + n)lg n). The - * amortized cost for a sequence of m accesses to a splay tree is O(lg n); - * - * A red-black tree is a binary search tree with the node color as an - * extra attribute. It fulfills a set of conditions: - * - every search path from the root to a leaf consists of the - * same number of black nodes, - * - each red node (except for the root) has a black parent, - * - each leaf node is black. - * - * Every operation on a red-black tree is bounded as O(lg n). - * The maximum height of a red-black tree is 2lg (n+1). - */ - -#define SPLAY_HEAD(name, type) \ -struct name { \ - struct type *sph_root; /* root of the tree */ \ -} - -#define SPLAY_INITIALIZER(root) \ - { NULL } - -#define SPLAY_INIT(root) do { \ - (root)->sph_root = NULL; \ -} while (/*CONSTCOND*/ 0) - -#define SPLAY_ENTRY(type) \ -struct { \ - struct type *spe_left; /* left element */ \ - struct type *spe_right; /* right element */ \ -} - -#define SPLAY_LEFT(elm, field) (elm)->field.spe_left -#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right -#define SPLAY_ROOT(head) (head)->sph_root -#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL) - -/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */ -#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \ - SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \ - SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ - (head)->sph_root = tmp; \ -} while (/*CONSTCOND*/ 0) - -#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \ - SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \ - SPLAY_LEFT(tmp, field) = (head)->sph_root; \ - (head)->sph_root = tmp; \ -} while (/*CONSTCOND*/ 0) - -#define SPLAY_LINKLEFT(head, tmp, field) do { \ - SPLAY_LEFT(tmp, field) = (head)->sph_root; \ - tmp = (head)->sph_root; \ - (head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \ -} while (/*CONSTCOND*/ 0) - -#define SPLAY_LINKRIGHT(head, tmp, field) do { \ - SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ - tmp = (head)->sph_root; \ - (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \ -} while (/*CONSTCOND*/ 0) - -#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \ - SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \ - SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\ - SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \ - SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \ -} while (/*CONSTCOND*/ 0) - -/* Generates prototypes and inline functions */ - -#define SPLAY_PROTOTYPE(name, type, field, cmp) \ -void name##_SPLAY(struct name *, struct type *); \ -void name##_SPLAY_MINMAX(struct name *, int); \ -struct type *name##_SPLAY_INSERT(struct name *, struct type *); \ -struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \ - \ -/* Finds the node with the same key as elm */ \ -static __inline struct type * \ -name##_SPLAY_FIND(struct name *head, struct type *elm) \ -{ \ - if (SPLAY_EMPTY(head)) \ - return(NULL); \ - name##_SPLAY(head, elm); \ - if ((cmp)(elm, (head)->sph_root) == 0) \ - return (head->sph_root); \ - return (NULL); \ -} \ - \ -static __inline struct type * \ -name##_SPLAY_NEXT(struct name *head, struct type *elm) \ -{ \ - name##_SPLAY(head, elm); \ - if (SPLAY_RIGHT(elm, field) != NULL) { \ - elm = SPLAY_RIGHT(elm, field); \ - while (SPLAY_LEFT(elm, field) != NULL) { \ - elm = SPLAY_LEFT(elm, field); \ - } \ - } else \ - elm = NULL; \ - return (elm); \ -} \ - \ -static __inline struct type * \ -name##_SPLAY_MIN_MAX(struct name *head, int val) \ -{ \ - name##_SPLAY_MINMAX(head, val); \ - return (SPLAY_ROOT(head)); \ -} - -/* Main splay operation. - * Moves node close to the key of elm to top - */ -#define SPLAY_GENERATE(name, type, field, cmp) \ -struct type * \ -name##_SPLAY_INSERT(struct name *head, struct type *elm) \ -{ \ - if (SPLAY_EMPTY(head)) { \ - SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \ - } else { \ - int __comp; \ - name##_SPLAY(head, elm); \ - __comp = (cmp)(elm, (head)->sph_root); \ - if(__comp < 0) { \ - SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\ - SPLAY_RIGHT(elm, field) = (head)->sph_root; \ - SPLAY_LEFT((head)->sph_root, field) = NULL; \ - } else if (__comp > 0) { \ - SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\ - SPLAY_LEFT(elm, field) = (head)->sph_root; \ - SPLAY_RIGHT((head)->sph_root, field) = NULL; \ - } else \ - return ((head)->sph_root); \ - } \ - (head)->sph_root = (elm); \ - return (NULL); \ -} \ - \ -struct type * \ -name##_SPLAY_REMOVE(struct name *head, struct type *elm) \ -{ \ - struct type *__tmp; \ - if (SPLAY_EMPTY(head)) \ - return (NULL); \ - name##_SPLAY(head, elm); \ - if ((cmp)(elm, (head)->sph_root) == 0) { \ - if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \ - (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\ - } else { \ - __tmp = SPLAY_RIGHT((head)->sph_root, field); \ - (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\ - name##_SPLAY(head, elm); \ - SPLAY_RIGHT((head)->sph_root, field) = __tmp; \ - } \ - return (elm); \ - } \ - return (NULL); \ -} \ - \ -void \ -name##_SPLAY(struct name *head, struct type *elm) \ -{ \ - struct type __node, *__left, *__right, *__tmp; \ - int __comp; \ -\ - SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ - __left = __right = &__node; \ -\ - while ((__comp = (cmp)(elm, (head)->sph_root)) != 0) { \ - if (__comp < 0) { \ - __tmp = SPLAY_LEFT((head)->sph_root, field); \ - if (__tmp == NULL) \ - break; \ - if ((cmp)(elm, __tmp) < 0){ \ - SPLAY_ROTATE_RIGHT(head, __tmp, field); \ - if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ - break; \ - } \ - SPLAY_LINKLEFT(head, __right, field); \ - } else if (__comp > 0) { \ - __tmp = SPLAY_RIGHT((head)->sph_root, field); \ - if (__tmp == NULL) \ - break; \ - if ((cmp)(elm, __tmp) > 0){ \ - SPLAY_ROTATE_LEFT(head, __tmp, field); \ - if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ - break; \ - } \ - SPLAY_LINKRIGHT(head, __left, field); \ - } \ - } \ - SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ -} \ - \ -/* Splay with either the minimum or the maximum element \ - * Used to find minimum or maximum element in tree. \ - */ \ -void name##_SPLAY_MINMAX(struct name *head, int __comp) \ -{ \ - struct type __node, *__left, *__right, *__tmp; \ -\ - SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ - __left = __right = &__node; \ -\ - while (1) { \ - if (__comp < 0) { \ - __tmp = SPLAY_LEFT((head)->sph_root, field); \ - if (__tmp == NULL) \ - break; \ - if (__comp < 0){ \ - SPLAY_ROTATE_RIGHT(head, __tmp, field); \ - if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ - break; \ - } \ - SPLAY_LINKLEFT(head, __right, field); \ - } else if (__comp > 0) { \ - __tmp = SPLAY_RIGHT((head)->sph_root, field); \ - if (__tmp == NULL) \ - break; \ - if (__comp > 0) { \ - SPLAY_ROTATE_LEFT(head, __tmp, field); \ - if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ - break; \ - } \ - SPLAY_LINKRIGHT(head, __left, field); \ - } \ - } \ - SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ -} - -#define SPLAY_NEGINF -1 -#define SPLAY_INF 1 - -#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y) -#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y) -#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y) -#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y) -#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \ - : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF)) -#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \ - : name##_SPLAY_MIN_MAX(x, SPLAY_INF)) - -#define SPLAY_FOREACH(x, name, head) \ - for ((x) = SPLAY_MIN(name, head); \ - (x) != NULL; \ - (x) = SPLAY_NEXT(name, head, x)) - -/* Macros that define a red-black tree */ -#define RB_HEAD(name, type) \ -struct name { \ - struct type *rbh_root; /* root of the tree */ \ -} - -#define RB_INITIALIZER(root) \ - { NULL } - -#define RB_INIT(root) do { \ - (root)->rbh_root = NULL; \ -} while (/*CONSTCOND*/ 0) - -#define RB_BLACK 0 -#define RB_RED 1 -#define RB_ENTRY(type) \ -struct { \ - struct type *rbe_left; /* left element */ \ - struct type *rbe_right; /* right element */ \ - struct type *rbe_parent; /* parent element */ \ - int rbe_color; /* node color */ \ -} - -#define RB_LEFT(elm, field) (elm)->field.rbe_left -#define RB_RIGHT(elm, field) (elm)->field.rbe_right -#define RB_PARENT(elm, field) (elm)->field.rbe_parent -#define RB_COLOR(elm, field) (elm)->field.rbe_color -#define RB_ROOT(head) (head)->rbh_root -#define RB_EMPTY(head) (RB_ROOT(head) == NULL) - -#define RB_SET(elm, parent, field) do { \ - RB_PARENT(elm, field) = parent; \ - RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \ - RB_COLOR(elm, field) = RB_RED; \ -} while (/*CONSTCOND*/ 0) - -#define RB_SET_BLACKRED(black, red, field) do { \ - RB_COLOR(black, field) = RB_BLACK; \ - RB_COLOR(red, field) = RB_RED; \ -} while (/*CONSTCOND*/ 0) - -#ifndef RB_AUGMENT -#define RB_AUGMENT(x) do {} while (0) -#endif - -#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \ - (tmp) = RB_RIGHT(elm, field); \ - if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field)) != NULL) { \ - RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \ - } \ - RB_AUGMENT(elm); \ - if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \ - if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ - RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ - else \ - RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ - } else \ - (head)->rbh_root = (tmp); \ - RB_LEFT(tmp, field) = (elm); \ - RB_PARENT(elm, field) = (tmp); \ - RB_AUGMENT(tmp); \ - if ((RB_PARENT(tmp, field))) \ - RB_AUGMENT(RB_PARENT(tmp, field)); \ -} while (/*CONSTCOND*/ 0) - -#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \ - (tmp) = RB_LEFT(elm, field); \ - if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field)) != NULL) { \ - RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \ - } \ - RB_AUGMENT(elm); \ - if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \ - if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ - RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ - else \ - RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ - } else \ - (head)->rbh_root = (tmp); \ - RB_RIGHT(tmp, field) = (elm); \ - RB_PARENT(elm, field) = (tmp); \ - RB_AUGMENT(tmp); \ - if ((RB_PARENT(tmp, field))) \ - RB_AUGMENT(RB_PARENT(tmp, field)); \ -} while (/*CONSTCOND*/ 0) - -/* Generates prototypes and inline functions */ -#define RB_PROTOTYPE(name, type, field, cmp) \ - RB_PROTOTYPE_INTERNAL(name, type, field, cmp,) -#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \ - RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __unused static) -#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \ -attr void name##_RB_INSERT_COLOR(struct name *, struct type *); \ -attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\ -attr struct type *name##_RB_REMOVE(struct name *, struct type *); \ -attr struct type *name##_RB_INSERT(struct name *, struct type *); \ -attr struct type *name##_RB_FIND(struct name *, struct type *); \ -attr struct type *name##_RB_NFIND(struct name *, struct type *); \ -attr struct type *name##_RB_NEXT(struct type *); \ -attr struct type *name##_RB_PREV(struct type *); \ -attr struct type *name##_RB_MINMAX(struct name *, int); \ - \ - -/* Main rb operation. - * Moves node close to the key of elm to top - */ -#define RB_GENERATE(name, type, field, cmp) \ - RB_GENERATE_INTERNAL(name, type, field, cmp,) -#define RB_GENERATE_STATIC(name, type, field, cmp) \ - RB_GENERATE_INTERNAL(name, type, field, cmp, static) -#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \ -attr void \ -name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \ -{ \ - struct type *parent, *gparent, *tmp; \ - while ((parent = RB_PARENT(elm, field)) != NULL && \ - RB_COLOR(parent, field) == RB_RED) { \ - gparent = RB_PARENT(parent, field); \ - if (parent == RB_LEFT(gparent, field)) { \ - tmp = RB_RIGHT(gparent, field); \ - if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ - RB_COLOR(tmp, field) = RB_BLACK; \ - RB_SET_BLACKRED(parent, gparent, field);\ - elm = gparent; \ - continue; \ - } \ - if (RB_RIGHT(parent, field) == elm) { \ - RB_ROTATE_LEFT(head, parent, tmp, field);\ - tmp = parent; \ - parent = elm; \ - elm = tmp; \ - } \ - RB_SET_BLACKRED(parent, gparent, field); \ - RB_ROTATE_RIGHT(head, gparent, tmp, field); \ - } else { \ - tmp = RB_LEFT(gparent, field); \ - if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ - RB_COLOR(tmp, field) = RB_BLACK; \ - RB_SET_BLACKRED(parent, gparent, field);\ - elm = gparent; \ - continue; \ - } \ - if (RB_LEFT(parent, field) == elm) { \ - RB_ROTATE_RIGHT(head, parent, tmp, field);\ - tmp = parent; \ - parent = elm; \ - elm = tmp; \ - } \ - RB_SET_BLACKRED(parent, gparent, field); \ - RB_ROTATE_LEFT(head, gparent, tmp, field); \ - } \ - } \ - RB_COLOR(head->rbh_root, field) = RB_BLACK; \ -} \ - \ -attr void \ -name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \ -{ \ - struct type *tmp; \ - while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \ - elm != RB_ROOT(head)) { \ - if (RB_LEFT(parent, field) == elm) { \ - tmp = RB_RIGHT(parent, field); \ - if (RB_COLOR(tmp, field) == RB_RED) { \ - RB_SET_BLACKRED(tmp, parent, field); \ - RB_ROTATE_LEFT(head, parent, tmp, field);\ - tmp = RB_RIGHT(parent, field); \ - } \ - if ((RB_LEFT(tmp, field) == NULL || \ - RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ - (RB_RIGHT(tmp, field) == NULL || \ - RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ - RB_COLOR(tmp, field) = RB_RED; \ - elm = parent; \ - parent = RB_PARENT(elm, field); \ - } else { \ - if (RB_RIGHT(tmp, field) == NULL || \ - RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\ - struct type *oleft; \ - if ((oleft = RB_LEFT(tmp, field)) \ - != NULL) \ - RB_COLOR(oleft, field) = RB_BLACK;\ - RB_COLOR(tmp, field) = RB_RED; \ - RB_ROTATE_RIGHT(head, tmp, oleft, field);\ - tmp = RB_RIGHT(parent, field); \ - } \ - RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ - RB_COLOR(parent, field) = RB_BLACK; \ - if (RB_RIGHT(tmp, field)) \ - RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\ - RB_ROTATE_LEFT(head, parent, tmp, field);\ - elm = RB_ROOT(head); \ - break; \ - } \ - } else { \ - tmp = RB_LEFT(parent, field); \ - if (RB_COLOR(tmp, field) == RB_RED) { \ - RB_SET_BLACKRED(tmp, parent, field); \ - RB_ROTATE_RIGHT(head, parent, tmp, field);\ - tmp = RB_LEFT(parent, field); \ - } \ - if ((RB_LEFT(tmp, field) == NULL || \ - RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ - (RB_RIGHT(tmp, field) == NULL || \ - RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ - RB_COLOR(tmp, field) = RB_RED; \ - elm = parent; \ - parent = RB_PARENT(elm, field); \ - } else { \ - if (RB_LEFT(tmp, field) == NULL || \ - RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\ - struct type *oright; \ - if ((oright = RB_RIGHT(tmp, field)) \ - != NULL) \ - RB_COLOR(oright, field) = RB_BLACK;\ - RB_COLOR(tmp, field) = RB_RED; \ - RB_ROTATE_LEFT(head, tmp, oright, field);\ - tmp = RB_LEFT(parent, field); \ - } \ - RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ - RB_COLOR(parent, field) = RB_BLACK; \ - if (RB_LEFT(tmp, field)) \ - RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\ - RB_ROTATE_RIGHT(head, parent, tmp, field);\ - elm = RB_ROOT(head); \ - break; \ - } \ - } \ - } \ - if (elm) \ - RB_COLOR(elm, field) = RB_BLACK; \ -} \ - \ -attr struct type * \ -name##_RB_REMOVE(struct name *head, struct type *elm) \ -{ \ - struct type *child, *parent, *old = elm; \ - int color; \ - if (RB_LEFT(elm, field) == NULL) \ - child = RB_RIGHT(elm, field); \ - else if (RB_RIGHT(elm, field) == NULL) \ - child = RB_LEFT(elm, field); \ - else { \ - struct type *left; \ - elm = RB_RIGHT(elm, field); \ - while ((left = RB_LEFT(elm, field)) != NULL) \ - elm = left; \ - child = RB_RIGHT(elm, field); \ - parent = RB_PARENT(elm, field); \ - color = RB_COLOR(elm, field); \ - if (child) \ - RB_PARENT(child, field) = parent; \ - if (parent) { \ - if (RB_LEFT(parent, field) == elm) \ - RB_LEFT(parent, field) = child; \ - else \ - RB_RIGHT(parent, field) = child; \ - RB_AUGMENT(parent); \ - } else \ - RB_ROOT(head) = child; \ - if (RB_PARENT(elm, field) == old) \ - parent = elm; \ - (elm)->field = (old)->field; \ - if (RB_PARENT(old, field)) { \ - if (RB_LEFT(RB_PARENT(old, field), field) == old)\ - RB_LEFT(RB_PARENT(old, field), field) = elm;\ - else \ - RB_RIGHT(RB_PARENT(old, field), field) = elm;\ - RB_AUGMENT(RB_PARENT(old, field)); \ - } else \ - RB_ROOT(head) = elm; \ - RB_PARENT(RB_LEFT(old, field), field) = elm; \ - if (RB_RIGHT(old, field)) \ - RB_PARENT(RB_RIGHT(old, field), field) = elm; \ - if (parent) { \ - left = parent; \ - do { \ - RB_AUGMENT(left); \ - } while ((left = RB_PARENT(left, field)) != NULL); \ - } \ - goto color; \ - } \ - parent = RB_PARENT(elm, field); \ - color = RB_COLOR(elm, field); \ - if (child) \ - RB_PARENT(child, field) = parent; \ - if (parent) { \ - if (RB_LEFT(parent, field) == elm) \ - RB_LEFT(parent, field) = child; \ - else \ - RB_RIGHT(parent, field) = child; \ - RB_AUGMENT(parent); \ - } else \ - RB_ROOT(head) = child; \ -color: \ - if (color == RB_BLACK) \ - name##_RB_REMOVE_COLOR(head, parent, child); \ - return (old); \ -} \ - \ -/* Inserts a node into the RB tree */ \ -attr struct type * \ -name##_RB_INSERT(struct name *head, struct type *elm) \ -{ \ - struct type *tmp; \ - struct type *parent = NULL; \ - int comp = 0; \ - tmp = RB_ROOT(head); \ - while (tmp) { \ - parent = tmp; \ - comp = (cmp)(elm, parent); \ - if (comp < 0) \ - tmp = RB_LEFT(tmp, field); \ - else if (comp > 0) \ - tmp = RB_RIGHT(tmp, field); \ - else \ - return (tmp); \ - } \ - RB_SET(elm, parent, field); \ - if (parent != NULL) { \ - if (comp < 0) \ - RB_LEFT(parent, field) = elm; \ - else \ - RB_RIGHT(parent, field) = elm; \ - RB_AUGMENT(parent); \ - } else \ - RB_ROOT(head) = elm; \ - name##_RB_INSERT_COLOR(head, elm); \ - return (NULL); \ -} \ - \ -/* Finds the node with the same key as elm */ \ -attr struct type * \ -name##_RB_FIND(struct name *head, struct type *elm) \ -{ \ - struct type *tmp = RB_ROOT(head); \ - int comp; \ - while (tmp) { \ - comp = cmp(elm, tmp); \ - if (comp < 0) \ - tmp = RB_LEFT(tmp, field); \ - else if (comp > 0) \ - tmp = RB_RIGHT(tmp, field); \ - else \ - return (tmp); \ - } \ - return (NULL); \ -} \ - \ -/* Finds the first node greater than or equal to the search key */ \ -attr struct type * \ -name##_RB_NFIND(struct name *head, struct type *elm) \ -{ \ - struct type *tmp = RB_ROOT(head); \ - struct type *res = NULL; \ - int comp; \ - while (tmp) { \ - comp = cmp(elm, tmp); \ - if (comp < 0) { \ - res = tmp; \ - tmp = RB_LEFT(tmp, field); \ - } \ - else if (comp > 0) \ - tmp = RB_RIGHT(tmp, field); \ - else \ - return (tmp); \ - } \ - return (res); \ -} \ - \ -/* ARGSUSED */ \ -attr struct type * \ -name##_RB_NEXT(struct type *elm) \ -{ \ - if (RB_RIGHT(elm, field)) { \ - elm = RB_RIGHT(elm, field); \ - while (RB_LEFT(elm, field)) \ - elm = RB_LEFT(elm, field); \ - } else { \ - if (RB_PARENT(elm, field) && \ - (elm == RB_LEFT(RB_PARENT(elm, field), field))) \ - elm = RB_PARENT(elm, field); \ - else { \ - while (RB_PARENT(elm, field) && \ - (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\ - elm = RB_PARENT(elm, field); \ - elm = RB_PARENT(elm, field); \ - } \ - } \ - return (elm); \ -} \ - \ -/* ARGSUSED */ \ -attr struct type * \ -name##_RB_PREV(struct type *elm) \ -{ \ - if (RB_LEFT(elm, field)) { \ - elm = RB_LEFT(elm, field); \ - while (RB_RIGHT(elm, field)) \ - elm = RB_RIGHT(elm, field); \ - } else { \ - if (RB_PARENT(elm, field) && \ - (elm == RB_RIGHT(RB_PARENT(elm, field), field))) \ - elm = RB_PARENT(elm, field); \ - else { \ - while (RB_PARENT(elm, field) && \ - (elm == RB_LEFT(RB_PARENT(elm, field), field)))\ - elm = RB_PARENT(elm, field); \ - elm = RB_PARENT(elm, field); \ - } \ - } \ - return (elm); \ -} \ - \ -attr struct type * \ -name##_RB_MINMAX(struct name *head, int val) \ -{ \ - struct type *tmp = RB_ROOT(head); \ - struct type *parent = NULL; \ - while (tmp) { \ - parent = tmp; \ - if (val < 0) \ - tmp = RB_LEFT(tmp, field); \ - else \ - tmp = RB_RIGHT(tmp, field); \ - } \ - return (parent); \ -} - -#define RB_NEGINF -1 -#define RB_INF 1 - -#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y) -#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y) -#define RB_FIND(name, x, y) name##_RB_FIND(x, y) -#define RB_NFIND(name, x, y) name##_RB_NFIND(x, y) -#define RB_NEXT(name, x, y) name##_RB_NEXT(y) -#define RB_PREV(name, x, y) name##_RB_PREV(y) -#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF) -#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF) - -#define RB_FOREACH(x, name, head) \ - for ((x) = RB_MIN(name, head); \ - (x) != NULL; \ - (x) = name##_RB_NEXT(x)) - -#define RB_FOREACH_REVERSE(x, name, head) \ - for ((x) = RB_MAX(name, head); \ - (x) != NULL; \ - (x) = name##_RB_PREV(x)) - -#endif /* _SYS_TREE_H_ */ From b0d2a38b86b1a1adaf9214158972f75b76e35492 Mon Sep 17 00:00:00 2001 From: Jason Evans Date: Fri, 20 Jun 2008 10:34:42 -0700 Subject: [PATCH 42/66] Bug 431739: Limit dirty page purging, r=benjamin Limit dirty page purging so that it terminates once the number of pages is no more than half the limit. Add a separate tree to track arena chunks that contain dirty pages. This substantially improves worst case allocation performance, since O(lg n) tree search can be used instead of O(n) tree iteration. --- memory/jemalloc/jemalloc.c | 138 ++++++++++++++++++++++++------------- 1 file changed, 89 insertions(+), 49 deletions(-) diff --git a/memory/jemalloc/jemalloc.c b/memory/jemalloc/jemalloc.c index 367e3316e4a1..6d00dbf22be2 100644 --- a/memory/jemalloc/jemalloc.c +++ b/memory/jemalloc/jemalloc.c @@ -449,7 +449,7 @@ static const bool __isthreaded = true; #define CHUNK_2POW_DEFAULT 20 /* Maximum number of dirty pages per arena. */ -#define DIRTY_MAX_DEFAULT (1U << 9) +#define DIRTY_MAX_DEFAULT (1U << 10) /* * Maximum size of L1 cache line. This is used to avoid cache line aliasing, @@ -724,6 +724,9 @@ struct arena_chunk_s { /* Linkage for the arena's chunks_all tree. */ rb_node(arena_chunk_t) link_all; + /* Linkage for the arena's chunks_dirty tree. */ + rb_node(arena_chunk_t) link_dirty; + /* * Number of pages in use. This is maintained in order to make * detection of empty chunks fast. @@ -830,10 +833,22 @@ struct arena_s { /* Tree of all chunks this arena manages. */ arena_chunk_tree_t chunks_all; + /* + * Tree of dirty-page-containing chunks this arena manages. This tree + * is maintained in addition to chunks_all in order to make + * deallocation O(lg d), where 'd' is the size of chunks_dirty. + * + * Without this tree, deallocation would be O(a), where 'a' is the size + * of chunks_all. Since dirty pages are purged in descending memory + * order, it would not be difficult to trigger something approaching + * worst case behavior with a series of large deallocations. + */ + arena_chunk_tree_t chunks_dirty; + /* * In order to avoid rapid chunk allocation/deallocation when an arena * oscillates right on the cusp of needing a new chunk, cache the most - * recently freed chunk. The spare is left in the arena's chunk tree + * recently freed chunk. The spare is left in the arena's chunk trees * until it is deleted. * * There is one spare chunk per arena, rather than one spare total, in @@ -1035,13 +1050,13 @@ static chunk_stats_t stats_chunks; */ const char *_malloc_options #ifdef MOZ_MEMORY_WINDOWS -= "A10n2F" += "A10n" #elif (defined(MOZ_MEMORY_DARWIN)) = "AP10n" #elif (defined(MOZ_MEMORY_LINUX)) -= "A10n2F" += "A10n" #elif (defined(MOZ_MEMORY_SOLARIS)) -= "A10n2F" += "A10n" #endif ; @@ -2683,6 +2698,8 @@ arena_chunk_comp(arena_chunk_t *a, arena_chunk_t *b) /* Wrap red-black tree macros in functions. */ rb_wrap(static, arena_chunk_tree_all_, arena_chunk_tree_t, arena_chunk_t, link_all, arena_chunk_comp) +rb_wrap(static, arena_chunk_tree_dirty_, arena_chunk_tree_t, + arena_chunk_t, link_dirty, arena_chunk_comp) static inline int arena_run_comp(arena_run_t *a, arena_run_t *b) @@ -2896,11 +2913,12 @@ arena_run_split(arena_t *arena, arena_run_t *run, size_t size, bool small, bool zero) { arena_chunk_t *chunk; - size_t run_ind, total_pages, need_pages, rem_pages, i; + size_t old_ndirty, run_ind, total_pages, need_pages, rem_pages, i; extent_node_t *nodeA, *nodeB, key; /* Insert a node into runs_alloced_ad for the first part of the run. */ chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run); + old_ndirty = chunk->ndirty; nodeA = arena_chunk_node_alloc(chunk); nodeA->addr = run; nodeA->size = size; @@ -2995,6 +3013,8 @@ arena_run_split(arena_t *arena, arena_run_t *run, size_t size, bool small, } chunk->pages_used += need_pages; + if (chunk->ndirty == 0 && old_ndirty > 0) + arena_chunk_tree_dirty_remove(&arena->chunks_dirty, chunk); } static arena_chunk_t * @@ -3083,7 +3103,11 @@ arena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk) if (arena->spare != NULL) { arena_chunk_tree_all_remove(&chunk->arena->chunks_all, arena->spare); - arena->ndirty -= arena->spare->ndirty; + if (arena->spare->ndirty > 0) { + arena_chunk_tree_dirty_remove( + &chunk->arena->chunks_dirty, arena->spare); + arena->ndirty -= arena->spare->ndirty; + } VALGRIND_FREELIKE_BLOCK(arena->spare, 0); chunk_dealloc((void *)arena->spare, chunksize); #ifdef MALLOC_STATS @@ -3094,8 +3118,8 @@ arena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk) /* * Remove run from the runs trees, regardless of whether this chunk * will be cached, so that the arena does not use it. Dirty page - * flushing only uses the chunks tree, so leaving this chunk in that - * tree is sufficient for that purpose. + * flushing only uses the chunks_dirty tree, so leaving this chunk in + * the chunks_* trees is sufficient for that purpose. */ key.addr = (void *)((uintptr_t)chunk + (arena_chunk_header_npages << pagesize_2pow)); @@ -3146,6 +3170,7 @@ static void arena_purge(arena_t *arena) { arena_chunk_t *chunk; + size_t i, npages; #ifdef MALLOC_DEBUG size_t ndirty; @@ -3154,6 +3179,13 @@ arena_purge(arena_t *arena) ndirty += chunk->ndirty; } rb_foreach_end(arena_chunk_t, link_all, &arena->chunks_all, chunk) assert(ndirty == arena->ndirty); + + ndirty = 0; + rb_foreach_begin(arena_chunk_t, link_dirty, &arena->chunks_dirty, + chunk) { + ndirty += chunk->ndirty; + } rb_foreach_end(arena_chunk_t, link_dirty, &arena->chunks_dirty, chunk) + assert(ndirty == arena->ndirty); #endif assert(arena->ndirty > opt_dirty_max); @@ -3163,62 +3195,64 @@ arena_purge(arena_t *arena) /* * Iterate downward through chunks until enough dirty memory has been + * purged. Terminate as soon as possible in order to minimize the + * number of system calls, even if a chunk has only been partially * purged. */ - rb_foreach_reverse_begin(arena_chunk_t, link_all, &arena->chunks_all, - chunk) { - if (chunk->ndirty > 0) { - size_t i; + while (arena->ndirty > (opt_dirty_max >> 1)) { + chunk = arena_chunk_tree_dirty_last(&arena->chunks_dirty); + assert(chunk != NULL); - for (i = chunk_npages - 1; i >= - arena_chunk_header_npages; i--) { - if (chunk->map[i] & CHUNK_MAP_DIRTY) { - size_t npages; + for (i = chunk_npages - 1; chunk->ndirty > 0; i--) { + assert(i >= arena_chunk_header_npages); - chunk->map[i] = (CHUNK_MAP_LARGE | + if (chunk->map[i] & CHUNK_MAP_DIRTY) { + chunk->map[i] = (CHUNK_MAP_LARGE | #ifdef MALLOC_DECOMMIT - CHUNK_MAP_DECOMMITTED | + CHUNK_MAP_DECOMMITTED | #endif - CHUNK_MAP_POS_MASK); - chunk->ndirty--; - arena->ndirty--; - /* Find adjacent dirty run(s). */ - for (npages = 1; i > - arena_chunk_header_npages && - (chunk->map[i - 1] & - CHUNK_MAP_DIRTY); npages++) { - i--; - chunk->map[i] = (CHUNK_MAP_LARGE + CHUNK_MAP_POS_MASK); + /* Find adjacent dirty run(s). */ + for (npages = 1; i > arena_chunk_header_npages + && (chunk->map[i - 1] & CHUNK_MAP_DIRTY); + npages++) { + i--; + chunk->map[i] = (CHUNK_MAP_LARGE #ifdef MALLOC_DECOMMIT - | CHUNK_MAP_DECOMMITTED + | CHUNK_MAP_DECOMMITTED #endif - | CHUNK_MAP_POS_MASK); - chunk->ndirty--; - arena->ndirty--; - } + | CHUNK_MAP_POS_MASK); + } + chunk->ndirty -= npages; + arena->ndirty -= npages; #ifdef MALLOC_DECOMMIT - pages_decommit((void *)((uintptr_t) - chunk + (i << pagesize_2pow)), - (npages << pagesize_2pow)); + pages_decommit((void *)((uintptr_t) + chunk + (i << pagesize_2pow)), + (npages << pagesize_2pow)); # ifdef MALLOC_STATS - arena->stats.ndecommit++; - arena->stats.decommitted += npages; + arena->stats.ndecommit++; + arena->stats.decommitted += npages; # endif #else - madvise((void *)((uintptr_t)chunk + (i - << pagesize_2pow)), pagesize * - npages, MADV_FREE); + madvise((void *)((uintptr_t)chunk + (i << + pagesize_2pow)), pagesize * npages, + MADV_FREE); #endif #ifdef MALLOC_STATS - arena->stats.nmadvise++; - arena->stats.purged += npages; + arena->stats.nmadvise++; + arena->stats.purged += npages; #endif - } + if (arena->ndirty <= (opt_dirty_max >> 1)) + break; } } - } rb_foreach_reverse_end(arena_chunk_t, link_all, &arena->chunks_all, - chunk) + + if (chunk->ndirty == 0) { + arena_chunk_tree_dirty_remove(&arena->chunks_dirty, + chunk); + } + } } static void @@ -3252,9 +3286,14 @@ arena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty) assert((chunk->map[run_ind + i] & CHUNK_MAP_DIRTY) == 0); chunk->map[run_ind + i] |= CHUNK_MAP_DIRTY; - chunk->ndirty++; - arena->ndirty++; } + + if (chunk->ndirty == 0) { + arena_chunk_tree_dirty_insert(&arena->chunks_dirty, + chunk); + } + chunk->ndirty += run_pages; + arena->ndirty += run_pages; } #ifdef MALLOC_DEBUG /* Set map elements to a bogus value in order to aid error detection. */ @@ -4462,6 +4501,7 @@ arena_new(arena_t *arena) /* Initialize chunks. */ arena_chunk_tree_all_new(&arena->chunks_all); + arena_chunk_tree_dirty_new(&arena->chunks_dirty); arena->spare = NULL; arena->ndirty = 0; From b3f6c9945bae0845b595e3b0eabd96efac625651 Mon Sep 17 00:00:00 2001 From: Jason Evans Date: Fri, 20 Jun 2008 10:34:42 -0700 Subject: [PATCH 43/66] Bug 432475: Remove _malloc_options abuse, r=benjamin Don't abuse _malloc_options to set platform-specific options, since doing so makes the MALLOC_OPTIONS environment variable less useful. --- memory/jemalloc/jemalloc.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/memory/jemalloc/jemalloc.c b/memory/jemalloc/jemalloc.c index 6d00dbf22be2..178dc8f3d3db 100644 --- a/memory/jemalloc/jemalloc.c +++ b/memory/jemalloc/jemalloc.c @@ -104,6 +104,13 @@ # define MALLOC_PRODUCTION #endif +/* + * Use only one arena by default. Mozilla does not currently make extensive + * use of concurrent allocation, so the increased fragmentation associated with + * multiple arenas is not warranted. + */ +#define MOZ_MEMORY_NARENAS_DEFAULT_ONE + /* * MALLOC_STATS enables statistics calculation, and is required for * jemalloc_stats(). @@ -1048,17 +1055,7 @@ static chunk_stats_t stats_chunks; /* * Runtime configuration options. */ -const char *_malloc_options -#ifdef MOZ_MEMORY_WINDOWS -= "A10n" -#elif (defined(MOZ_MEMORY_DARWIN)) -= "AP10n" -#elif (defined(MOZ_MEMORY_LINUX)) -= "A10n" -#elif (defined(MOZ_MEMORY_SOLARIS)) -= "A10n" -#endif -; +const char *_malloc_options; #ifndef MALLOC_PRODUCTION static bool opt_abort = true; @@ -5625,6 +5622,9 @@ MALLOC_OUT: base_nodes = NULL; malloc_mutex_init(&base_mtx); +#ifdef MOZ_MEMORY_NARENAS_DEFAULT_ONE + narenas = 1; +#else if (ncpus > 1) { /* * For SMP systems, create four times as many arenas as there @@ -5635,6 +5635,7 @@ MALLOC_OUT: /* Determine how many arenas to use. */ narenas = ncpus; +#endif if (opt_narenas_lshift > 0) { if ((narenas << opt_narenas_lshift) > narenas) narenas <<= opt_narenas_lshift; From 666f56f16bbfb844658540bb681ef364e3f10284 Mon Sep 17 00:00:00 2001 From: Jason Evans Date: Fri, 20 Jun 2008 12:00:29 -0700 Subject: [PATCH 44/66] Bug 431735: Fix build failures due to compiler flag incompatibilities, r=ted --- memory/jemalloc/Makefile.in | 3 --- 1 file changed, 3 deletions(-) diff --git a/memory/jemalloc/Makefile.in b/memory/jemalloc/Makefile.in index ae5e7118a33c..47ee60392a8d 100644 --- a/memory/jemalloc/Makefile.in +++ b/memory/jemalloc/Makefile.in @@ -99,9 +99,6 @@ LIBRARY_NAME = jemalloc # Build jemalloc as a shared lib. This is mandatory for Darwin, since a library # init function is used on that platform. FORCE_SHARED_LIB= 1 -# Make C99 variable-length arrays and inline declarations compile without -# warnings. -OS_CFLAGS += -std=c99 -fgnu89-inline CSRCS = \ jemalloc.c \ From 2f1e3248c05d19e010f3ecedd81dcd17aaf869ea Mon Sep 17 00:00:00 2001 From: Brendan Eich Date: Fri, 20 Jun 2008 13:17:51 -0700 Subject: [PATCH 45/66] Fuse branch after relational or equality op (363534, r=igor). --- js/src/jsinterp.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 9bc14c21e7af..aedf08361815 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -2529,6 +2529,10 @@ JS_STATIC_ASSERT(JSOP_DEFFUN_LENGTH == JSOP_CLOSURE_LENGTH); /* See comments in FETCH_SHIFT macro. */ JS_STATIC_ASSERT((JSVAL_TO_INT(JSVAL_VOID) & 31) == 0); +/* See TRY_BRANCH_AFTER_COND. */ +JS_STATIC_ASSERT(JSOP_IFNE_LENGTH == JSOP_IFEQ_LENGTH); +JS_STATIC_ASSERT(JSOP_IFNE == JSOP_IFEQ + 1); + JSBool js_Interpret(JSContext *cx) { @@ -3513,6 +3517,24 @@ js_Interpret(JSContext *cx) BITWISE_OP(&); END_CASE(JSOP_BITAND) +#define TRY_BRANCH_AFTER_COND(cond,spdec) \ + JS_BEGIN_MACRO \ + uintN diff_; \ + JS_ASSERT(js_CodeSpec[op].length == 1); \ + diff_ = (uintN) regs.pc[1] - (uintN) JSOP_IFEQ; \ + if (diff_ <= 1) { \ + regs.sp -= spdec; \ + if (cond == (diff_ != 0)) { \ + ++regs.pc; \ + len = GET_JUMP_OFFSET(regs.pc); \ + CHECK_BRANCH(len); \ + DO_NEXT_OP(len); \ + } \ + len = 1 + JSOP_IFEQ_LENGTH; \ + DO_NEXT_OP(len); \ + } \ + JS_END_MACRO + #define RELATIONAL_OP(OP) \ JS_BEGIN_MACRO \ rval = FETCH_OPND(-1); \ @@ -3543,6 +3565,7 @@ js_Interpret(JSContext *cx) cond = JSDOUBLE_COMPARE(d, OP, d2, JS_FALSE); \ } \ } \ + TRY_BRANCH_AFTER_COND(cond, 2); \ regs.sp--; \ STORE_OPND(-1, BOOLEAN_TO_JSVAL(cond)); \ JS_END_MACRO @@ -3631,6 +3654,7 @@ js_Interpret(JSContext *cx) } \ } \ } \ + TRY_BRANCH_AFTER_COND(cond, 2); \ regs.sp--; \ STORE_OPND(-1, BOOLEAN_TO_JSVAL(cond)); \ JS_END_MACRO @@ -3648,6 +3672,7 @@ js_Interpret(JSContext *cx) rval = FETCH_OPND(-1); \ lval = FETCH_OPND(-2); \ cond = js_StrictlyEqual(cx, lval, rval) OP JS_TRUE; \ + TRY_BRANCH_AFTER_COND(cond, 2); \ regs.sp--; \ STORE_OPND(-1, BOOLEAN_TO_JSVAL(cond)); \ JS_END_MACRO From 21f596da671ae10c07446fdb0e06d68af327696b Mon Sep 17 00:00:00 2001 From: Brendan Eich Date: Fri, 20 Jun 2008 14:25:38 -0700 Subject: [PATCH 46/66] Fix bustage caused by over-aggressive TRY_BRANCH_AFTER_COND in STRICT_EQUALITY_OP (used by JSOP_CASE*). --- js/src/jsinterp.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index aedf08361815..5fda191f0e17 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -3672,7 +3672,6 @@ js_Interpret(JSContext *cx) rval = FETCH_OPND(-1); \ lval = FETCH_OPND(-2); \ cond = js_StrictlyEqual(cx, lval, rval) OP JS_TRUE; \ - TRY_BRANCH_AFTER_COND(cond, 2); \ regs.sp--; \ STORE_OPND(-1, BOOLEAN_TO_JSVAL(cond)); \ JS_END_MACRO From 3ccfeedbe007d72d9618d7e55ab8700eab6155a5 Mon Sep 17 00:00:00 2001 From: "Robert Strong (robert.bugzilla@gmail.com)" Date: Fri, 20 Jun 2008 17:21:21 -0700 Subject: [PATCH 47/66] Bug 395891 - Profile Manager prevents Minefield startup from OS Integration points (links in Mails, etc). patch=Masatoshi Kimura (:emk) r=rob_strong --- toolkit/xre/nsAppRunner.cpp | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index 847e20dae677..67916fdca587 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -524,13 +524,14 @@ CheckArgShell(const char* aArg) } /** - * Spins up Windows DDE when the app needs to restart or the profile manager - * will be displayed during startup and the app has been launched by the Windows - * shell to open an url. This prevents Windows from displaying an error message - * due to the DDE message not being acknowledged. + * Enabled Native App Support to process DDE messages when the app needs to + * restart and the app has been launched by the Windows shell to open an url. + * When aWait is false this will process the DDE events manually. This prevents + * Windows from displaying an error message due to the DDE message not being + * acknowledged. */ static void -ProcessDDE(nsINativeAppSupport* aNative) +ProcessDDE(nsINativeAppSupport* aNative, PRBool aWait) { // When the app is launched by the windows shell the windows shell // expects the app to be available for DDE messages and if it isn't @@ -544,13 +545,15 @@ ProcessDDE(nsINativeAppSupport* aNative) ar = CheckArgShell("requestpending"); if (ar == ARG_FOUND) { aNative->Enable(); // enable win32 DDE responses - nsIThread *thread = NS_GetCurrentThread(); - // This is just a guesstimate based on testing different values. - // If count is 8 or less windows will display an error dialog. - PRInt32 count = 20; - while(--count >= 0) { - NS_ProcessNextEvent(thread); - PR_Sleep(PR_MillisecondsToInterval(1)); + if (aWait) { + nsIThread *thread = NS_GetCurrentThread(); + // This is just a guesstimate based on testing different values. + // If count is 8 or less windows will display an error dialog. + PRInt32 count = 20; + while(--count >= 0) { + NS_ProcessNextEvent(thread); + PR_Sleep(PR_MillisecondsToInterval(1)); + } } } } @@ -1717,7 +1720,9 @@ ShowProfileManager(nsIToolkitProfileService* aProfileSvc, #endif #ifdef XP_WIN - ProcessDDE(aNative); + // we don't have to wait here because profile manager window will pump + // and DDE message will be handled + ProcessDDE(aNative, PR_FALSE); #endif { //extra scoping is needed so we release these components before xpcom shutdown @@ -3207,7 +3212,7 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData) needsRestart = PR_TRUE; #ifdef XP_WIN - ProcessDDE(nativeApp); + ProcessDDE(nativeApp, PR_TRUE); #endif #ifdef XP_MACOSX From 5f1541930166a62d6ae51731c88375e499dfd201 Mon Sep 17 00:00:00 2001 From: Peter Van der Beken Date: Sat, 21 Jun 2008 17:25:29 +0200 Subject: [PATCH 48/66] Bug 423471 - Cycle collection shouldn't fault when traversing script objects of languages that don't participate. r/sr=dbaron. --- xpcom/base/nsCycleCollector.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/xpcom/base/nsCycleCollector.cpp b/xpcom/base/nsCycleCollector.cpp index fa73e0b22f93..c0fcc0ace169 100644 --- a/xpcom/base/nsCycleCollector.cpp +++ b/xpcom/base/nsCycleCollector.cpp @@ -1446,8 +1446,12 @@ GCGraphBuilder::NoteScriptChild(PRUint32 langID, void *child) if (!child) return; - if (langID > nsIProgrammingLanguage::MAX || !mRuntimes[langID]) { - Fault("traversing pointer for unregistered language", child); + if (langID > nsIProgrammingLanguage::MAX) { + Fault("traversing pointer for unknown language", child); + return; + } + + if (!mRuntimes[langID]) { return; } From 12e78301e65a48c61b5a46f133a582745942951c Mon Sep 17 00:00:00 2001 From: Peter Van der Beken Date: Sat, 21 Jun 2008 19:47:46 +0200 Subject: [PATCH 49/66] Address review comment for bug 423471 - Cycle collection shouldn't fault when traversing script objects of languages that don't participate. r/sr=dbaron. --- xpcom/base/nsCycleCollector.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xpcom/base/nsCycleCollector.cpp b/xpcom/base/nsCycleCollector.cpp index c0fcc0ace169..d2f7c4dac269 100644 --- a/xpcom/base/nsCycleCollector.cpp +++ b/xpcom/base/nsCycleCollector.cpp @@ -1452,6 +1452,8 @@ GCGraphBuilder::NoteScriptChild(PRUint32 langID, void *child) } if (!mRuntimes[langID]) { + NS_WARNING("Not collecting cycles involving objects for scripting " + "languages that don't participate in cycle collection."); return; } From ca1503f03fa897cb3c591d53b8b0f4316835d62c Mon Sep 17 00:00:00 2001 From: Simon Montagu Date: Sun, 22 Jun 2008 01:28:42 -0700 Subject: [PATCH 50/66] Unit test for bug 9357 (Autodetection of EUC-KR) --- extensions/universalchardet/tests/Makefile.in | 2 ++ .../universalchardet/tests/bug9357_text.html | 15 +++++++++ .../universalchardet/tests/test_bug9357.html | 31 +++++++++++++++++++ 3 files changed, 48 insertions(+) create mode 100644 extensions/universalchardet/tests/bug9357_text.html create mode 100644 extensions/universalchardet/tests/test_bug9357.html diff --git a/extensions/universalchardet/tests/Makefile.in b/extensions/universalchardet/tests/Makefile.in index 0b9b4b78b81a..3f8daea8b37d 100644 --- a/extensions/universalchardet/tests/Makefile.in +++ b/extensions/universalchardet/tests/Makefile.in @@ -72,6 +72,8 @@ relativesrcdir = extensions/universalchardet/tests _TEST_FILES = \ CharsetDetectionTests.js \ + bug9357_text.html \ + test_bug9357.html \ bug171813_text.html \ test_bug171813.html \ bug306272_text.html \ diff --git a/extensions/universalchardet/tests/bug9357_text.html b/extensions/universalchardet/tests/bug9357_text.html new file mode 100644 index 000000000000..ad8706faf225 --- /dev/null +++ b/extensions/universalchardet/tests/bug9357_text.html @@ -0,0 +1,15 @@ + + + + EUC-KR test + + +

ûϽ ã ϴ.
ãô ų
̸ Ǵ Ǿϴ.
̺Ʈ Ǵ Ǹ ̿Ͻñ ٶϴ

+ + + + + + + + diff --git a/extensions/universalchardet/tests/test_bug9357.html b/extensions/universalchardet/tests/test_bug9357.html new file mode 100644 index 000000000000..aee6822e19ad --- /dev/null +++ b/extensions/universalchardet/tests/test_bug9357.html @@ -0,0 +1,31 @@ + + + + + Test for Bug 9357 + + + + + + +Mozilla Bug 9357 +

+ + +
+
+
+ + + From 7eb028aa396e2f41713a5727883c49c794acd284 Mon Sep 17 00:00:00 2001 From: Robert Longson Date: Sun, 22 Jun 2008 16:45:38 +0100 Subject: [PATCH 51/66] Bug 434041 - text outline does not change thickness on zoom --- layout/svg/base/src/nsSVGGlyphFrame.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/layout/svg/base/src/nsSVGGlyphFrame.cpp b/layout/svg/base/src/nsSVGGlyphFrame.cpp index 6d452d0e7c63..68d9a834340a 100644 --- a/layout/svg/base/src/nsSVGGlyphFrame.cpp +++ b/layout/svg/base/src/nsSVGGlyphFrame.cpp @@ -1308,6 +1308,9 @@ CharacterIterator::SetupForDirectTextRun(gfxContext *aContext, float aScale) aContext->SetMatrix(mInitialMatrix); aContext->Translate(mSource->mPosition); aContext->Scale(aScale, aScale); + // We are scaling the glyphs up/down to the size we want so we need to + // inverse scale the outline widths of those glyphs so they are invariant + aContext->SetLineWidth(aContext->CurrentLineWidth() / aScale); return PR_TRUE; } @@ -1358,6 +1361,9 @@ CharacterIterator::SetupFor(gfxContext *aContext, float aScale) aContext->Rotate(mPositions[mCurrentChar].angle); aContext->Scale(aScale, aScale); } + // We are scaling the glyphs up/down to the size we want so we need to + // inverse scale the outline widths of those glyphs so they are invariant + aContext->SetLineWidth(aContext->CurrentLineWidth() / aScale); } CharacterPosition From 2411ee6bc29ef8de73c5447daa7de77d13f329fb Mon Sep 17 00:00:00 2001 From: Robert Longson Date: Sun, 22 Jun 2008 16:59:48 +0100 Subject: [PATCH 52/66] Bug 438867 - SVG not rendered after html hr element. r+sr=roc --- layout/svg/base/src/nsSVGContainerFrame.cpp | 4 +++- layout/svg/base/src/nsSVGOuterSVGFrame.cpp | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/layout/svg/base/src/nsSVGContainerFrame.cpp b/layout/svg/base/src/nsSVGContainerFrame.cpp index a3dd3c846c54..1f6c8360c390 100644 --- a/layout/svg/base/src/nsSVGContainerFrame.cpp +++ b/layout/svg/base/src/nsSVGContainerFrame.cpp @@ -98,7 +98,9 @@ nsSVGDisplayContainerFrame::Init(nsIContent* aContent, nsIFrame* aParent, nsIFrame* aPrevInFlow) { - AddStateBits(aParent->GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD); + if (!(GetStateBits() & NS_STATE_IS_OUTER_SVG)) { + AddStateBits(aParent->GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD); + } nsresult rv = nsSVGContainerFrameBase::Init(aContent, aParent, aPrevInFlow); return rv; } diff --git a/layout/svg/base/src/nsSVGOuterSVGFrame.cpp b/layout/svg/base/src/nsSVGOuterSVGFrame.cpp index aa424e37669a..9a160f50595d 100644 --- a/layout/svg/base/src/nsSVGOuterSVGFrame.cpp +++ b/layout/svg/base/src/nsSVGOuterSVGFrame.cpp @@ -166,6 +166,8 @@ nsSVGOuterSVGFrame::Init(nsIContent* aContent, nsIFrame* aParent, nsIFrame* aPrevInFlow) { + AddStateBits(NS_STATE_IS_OUTER_SVG); + nsresult rv = nsSVGOuterSVGFrameBase::Init(aContent, aParent, aPrevInFlow); nsIDocument* doc = mContent->GetCurrentDoc(); @@ -184,8 +186,6 @@ nsSVGOuterSVGFrame::Init(nsIContent* aContent, SuspendRedraw(); // UnsuspendRedraw is in DidReflow - AddStateBits(NS_STATE_IS_OUTER_SVG); - return rv; } From fd21ff735eeac3dffe274a4e016d64a759eea9d2 Mon Sep 17 00:00:00 2001 From: Robert Longson Date: Sun, 22 Jun 2008 17:22:07 +0100 Subject: [PATCH 53/66] Bug 438867 - rftest for SVG not rendered after html hr element. --- layout/reftests/svg/dynamic-rect-04.xhtml | 30 +++++++++++++++++++++++ layout/reftests/svg/reftest.list | 1 + 2 files changed, 31 insertions(+) create mode 100644 layout/reftests/svg/dynamic-rect-04.xhtml diff --git a/layout/reftests/svg/dynamic-rect-04.xhtml b/layout/reftests/svg/dynamic-rect-04.xhtml new file mode 100644 index 000000000000..112e327aeeb7 --- /dev/null +++ b/layout/reftests/svg/dynamic-rect-04.xhtml @@ -0,0 +1,30 @@ + + + + +Testcase reference file dynamic svg creation + + + + +
+ + diff --git a/layout/reftests/svg/reftest.list b/layout/reftests/svg/reftest.list index a1c81dfc4475..bdb9806a6bfa 100755 --- a/layout/reftests/svg/reftest.list +++ b/layout/reftests/svg/reftest.list @@ -19,6 +19,7 @@ include moz-only/reftest.list == dynamic-rect-01.svg dynamic-rect-01-ref.svg == dynamic-rect-02.svg dynamic-rect-02-ref.svg == dynamic-rect-03.svg dynamic-rect-03-ref.svg +== dynamic-rect-04.xhtml pass.svg == dynamic-reflow-01.svg dynamic-reflow-01-ref.svg == dynamic-text-01.svg dynamic-text-01-ref.svg == dynamic-text-02.svg dynamic-text-02-ref.svg From 0084a0efef437c3ff951ab589185a660a189f929 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Mon, 23 Jun 2008 10:38:29 +1200 Subject: [PATCH 54/66] Bug 438981. The canonical 'body element' must be the first 'body' child. --- content/html/document/src/nsHTMLDocument.cpp | 39 ++++++++++---------- content/html/document/src/nsHTMLDocument.h | 5 +++ layout/reftests/bugs/438981-1.xhtml | 11 ++++++ layout/reftests/bugs/reftest.list | 1 + 4 files changed, 37 insertions(+), 19 deletions(-) create mode 100644 layout/reftests/bugs/438981-1.xhtml diff --git a/content/html/document/src/nsHTMLDocument.cpp b/content/html/document/src/nsHTMLDocument.cpp index 01a0db7b7925..ac30ca273960 100644 --- a/content/html/document/src/nsHTMLDocument.cpp +++ b/content/html/document/src/nsHTMLDocument.cpp @@ -3575,30 +3575,31 @@ nsHTMLDocument::GetBodyContentExternal() return GetBodyContent(); } +nsIContent* +nsHTMLDocument::GetHtmlContent() +{ + nsIContent* rootContent = GetRootContent(); + if (rootContent && rootContent->Tag() == nsGkAtoms::html && + rootContent->IsNodeOfType(nsINode::eHTML)) + return rootContent; + return nsnull; +} + nsIContent* nsHTMLDocument::GetBodyContent() { - // Loop backwards because any non-elements, such as doctypes and PIs - // are likely to appear before the root element. - PRUint32 i; - for (i = mChildren.ChildCount(); i > 0; --i) { - nsIContent* html = mChildren.ChildAt(i - 1); - if (html->Tag() == nsGkAtoms::html && - html->IsNodeOfType(nsINode::eHTML)) { + nsIContent* html = GetHtmlContent(); + if (!html) + return nsnull; - // Look for body inside html - for (i = html->GetChildCount(); i > 0; --i) { - nsIContent* body = html->GetChildAt(i - 1); - if (body->Tag() == nsGkAtoms::body && - body->IsNodeOfType(nsINode::eHTML)) { - return body; - } - } - - break; - } + // Look for body inside html. This needs to run forwards to find + // the first body element. + for (PRUint32 i = 0; i < html->GetChildCount(); ++i) { + nsIContent* body = html->GetChildAt(i); + if (body->Tag() == nsGkAtoms::body && + body->IsNodeOfType(nsINode::eHTML)) + return body; } - return nsnull; } diff --git a/content/html/document/src/nsHTMLDocument.h b/content/html/document/src/nsHTMLDocument.h index 8c25a4c0ed68..87d3b92c2eaf 100644 --- a/content/html/document/src/nsHTMLDocument.h +++ b/content/html/document/src/nsHTMLDocument.h @@ -248,6 +248,11 @@ protected: static void DocumentWriteTerminationFunc(nsISupports *aRef); + // Get the root element, or return null if there isn't one (e.g. + // if the root isn't ) + nsIContent* GetHtmlContent(); + // Get the canonical element, or return null if there isn't one (e.g. + // if the root isn't or if the isn't there) nsIContent* GetBodyContent(); void GetDomainURI(nsIURI **uri); diff --git a/layout/reftests/bugs/438981-1.xhtml b/layout/reftests/bugs/438981-1.xhtml new file mode 100644 index 000000000000..d6eba7fce939 --- /dev/null +++ b/layout/reftests/bugs/438981-1.xhtml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index da16043d8ed8..22221a97fd41 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -849,5 +849,6 @@ random == 429849-1.html 429849-1-ref.html # bug 432288 == 430813-2.html 430813-2-ref.html == 430813-3.html 430813-3-ref.html == 433640-1.html 433640-1-ref.html +== 438981-1.xhtml about:blank == 439004-1.html 439004-1-ref.html == 439910.html 439910-ref.html From 00c8f1363c12c249f66a7af0eb781f8475ccf979 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Mon, 23 Jun 2008 11:12:40 +1200 Subject: [PATCH 55/66] Bug 344258. Move ID-content map up from nsHTMLDocument to nsDocument to prepare for using it across all document types. r+sr=jst --- content/base/public/nsContentUtils.h | 6 + content/base/src/nsContentUtils.cpp | 31 + content/base/src/nsDocument.cpp | 447 +++++++++- content/base/src/nsDocument.h | 102 +++ content/html/document/src/nsHTMLDocument.cpp | 811 ++----------------- content/html/document/src/nsHTMLDocument.h | 60 +- content/xml/document/src/nsXMLDocument.cpp | 30 - content/xml/document/src/nsXMLDocument.h | 4 - xpcom/glue/nsTHashtable.h | 6 + 9 files changed, 664 insertions(+), 833 deletions(-) diff --git a/content/base/public/nsContentUtils.h b/content/base/public/nsContentUtils.h index 83271cc0215b..6783a1a2f91a 100644 --- a/content/base/public/nsContentUtils.h +++ b/content/base/public/nsContentUtils.h @@ -1210,6 +1210,12 @@ public: */ static PRBool URIIsLocalFile(nsIURI *aURI); + /** + * If aContent is an HTML element with a DOM level 0 'name', then + * return the name. Otherwise return null. + */ + static nsIAtom* IsNamedItem(nsIContent* aContent); + /** * Get the application manifest URI for this context. The manifest URI * is specified in the manifest= attribute of the root element of the diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp index f629321f4c0c..73d93dc59ec3 100644 --- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -151,6 +151,8 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID); #include "nsIScriptObjectPrincipal.h" #include "nsIRunnable.h" #include "nsDOMJSUtils.h" +#include "nsGenericHTMLElement.h" +#include "nsAttrValue.h" #ifdef IBMBIDI #include "nsIBidiKeyboard.h" @@ -4293,3 +4295,32 @@ nsAutoGCRoot::Shutdown() { NS_IF_RELEASE(sJSRuntimeService); } + +nsIAtom* +nsContentUtils::IsNamedItem(nsIContent* aContent) +{ + // Only the content types reflected in Level 0 with a NAME + // attribute are registered. Images, layers and forms always get + // reflected up to the document. Applets and embeds only go + // to the closest container (which could be a form). + nsGenericHTMLElement* elm = nsGenericHTMLElement::FromContent(aContent); + if (!elm) { + return nsnull; + } + + nsIAtom* tag = elm->Tag(); + if (tag != nsGkAtoms::img && + tag != nsGkAtoms::form && + tag != nsGkAtoms::applet && + tag != nsGkAtoms::embed && + tag != nsGkAtoms::object) { + return nsnull; + } + + const nsAttrValue* val = elm->GetParsedAttr(nsGkAtoms::name); + if (val && val->Type() == nsAttrValue::eAtom) { + return val->GetAtomValue(); + } + + return nsnull; +} diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 4235e82ef5ec..ac7d86426651 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -288,6 +288,144 @@ nsUint32ToContentHashEntry::VisitContent(Visitor* aVisitor) } } +#define ID_NOT_IN_DOCUMENT ((nsIContent *)2) +#define NAME_NOT_VALID ((nsBaseContentList*)1) + +nsIdentifierMapEntry::~nsIdentifierMapEntry() +{ + if (mNameContentList && mNameContentList != NAME_NOT_VALID) { + NS_RELEASE(mNameContentList); + } +} + +void +nsIdentifierMapEntry::Traverse(nsCycleCollectionTraversalCallback* aCallback) +{ + if (mNameContentList != NAME_NOT_VALID) + aCallback->NoteXPCOMChild(mNameContentList); + + aCallback->NoteXPCOMChild(static_cast(mDocAllList)); +} + +void +nsIdentifierMapEntry::SetInvalidName() +{ + mNameContentList = NAME_NOT_VALID; +} + +PRBool +nsIdentifierMapEntry::IsInvalidName() +{ + return mNameContentList == NAME_NOT_VALID; +} + +nsresult +nsIdentifierMapEntry::CreateNameContentList() +{ + mNameContentList = new nsBaseContentList(); + NS_ENSURE_TRUE(mNameContentList, NS_ERROR_OUT_OF_MEMORY); + NS_ADDREF(mNameContentList); + return NS_OK; +} + +nsIContent* +nsIdentifierMapEntry::GetIdContent(PRBool* aNotInDocument) +{ + nsIContent* c = static_cast(mIdContentList.SafeElementAt(0)); + if (aNotInDocument) { + *aNotInDocument = c == ID_NOT_IN_DOCUMENT; + } + return c != ID_NOT_IN_DOCUMENT ? c : nsnull; +} + +PRBool +nsIdentifierMapEntry::AddIdContent(nsIContent* aContent) +{ + NS_PRECONDITION(aContent, "Must have content"); + NS_PRECONDITION(mIdContentList.IndexOf(nsnull) < 0, + "Why is null in our list?"); + NS_PRECONDITION(aContent != ID_NOT_IN_DOCUMENT, + "Bogus content pointer"); + + if (mIdContentList.SafeElementAt(0) == ID_NOT_IN_DOCUMENT) { + NS_ASSERTION(mIdContentList.Count() == 1, "Bogus count"); + mIdContentList.ReplaceElementAt(aContent, 0); + return PR_TRUE; + } + + // Common case + if (mIdContentList.Count() == 0) { + return mIdContentList.AppendElement(aContent) != nsnull; + } + + // We seem to have multiple content nodes for the same id, or we're doing our + // top-down registration when the id table is going live. Search for the + // right place to insert the content. + PRInt32 start = 0; + PRInt32 end = mIdContentList.Count(); + do { + NS_ASSERTION(start < end, "Bogus start/end"); + + PRInt32 cur = (start + end) / 2; + NS_ASSERTION(cur >= start && cur < end, "What happened here?"); + + nsIContent* curContent = static_cast(mIdContentList[cur]); + if (curContent == aContent) { + // Already in the list, so already in the right spot. Get out of here. + return PR_TRUE; + } + + if (nsContentUtils::PositionIsBefore(aContent, curContent)) { + end = cur; + } else { + start = cur + 1; + } + } while (start != end); + + return mIdContentList.InsertElementAt(aContent, start); +} + +PRBool +nsIdentifierMapEntry::RemoveIdContent(nsIContent* aContent) +{ + // XXXbz should this ever Compact() I guess when all the content is gone + // we'll just get cleaned up in the natural order of things... + return mIdContentList.RemoveElement(aContent) && + mIdContentList.Count() == 0; +} + +void +nsIdentifierMapEntry::FlagIDNotInDocument() +{ + NS_ASSERTION(mIdContentList.Count() == 0, + "Flagging ID not in document when we have content?"); + // Note that if this fails that's OK; this is just an optimization + mIdContentList.AppendElement(ID_NOT_IN_DOCUMENT); +} + +void +nsIdentifierMapEntry::AddNameContent(nsIContent* aContent) +{ + if (!mNameContentList || mNameContentList == NAME_NOT_VALID) + return; + + // NOTE: this indexof is absolutely needed, since we don't flush + // content notifications when we do document.foo resolution. So + // aContent may be in our list already and just now getting notified + // for! + if (mNameContentList->IndexOf(aContent, PR_FALSE) < 0) { + mNameContentList->AppendElement(aContent); + } +} + +void +nsIdentifierMapEntry::RemoveNameContent(nsIContent* aContent) +{ + if (mNameContentList && mNameContentList != NAME_NOT_VALID) { + mNameContentList->RemoveElement(aContent); + } +} + // Helper structs for the content->subdoc map class SubDocMapEntry : public PLDHashEntryHdr @@ -1012,7 +1150,7 @@ public: } }; -PLDHashOperator PR_CALLBACK +PR_STATIC_CALLBACK(PLDHashOperator) LinkMapTraverser(nsUint32ToContentHashEntry* aEntry, void* userArg) { LinkMapTraversalVisitor visitor; @@ -1022,11 +1160,22 @@ LinkMapTraverser(nsUint32ToContentHashEntry* aEntry, void* userArg) return PL_DHASH_NEXT; } +PR_STATIC_CALLBACK(PLDHashOperator) +IdentifierMapEntryTraverse(nsIdentifierMapEntry *aEntry, void *aArg) +{ + nsCycleCollectionTraversalCallback *cb = + static_cast(aArg); + aEntry->Traverse(cb); + return PL_DHASH_NEXT; +} + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDocument) if (nsCCUncollectableMarker::InGeneration(tmp->GetMarkedCCGeneration())) { return NS_OK; } + tmp->mIdentifierMap.EnumerateEntries(IdentifierMapEntryTraverse, &cb); + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mNodeInfo) // Traverse the mChildren nsAttrAndChildArray. @@ -1127,6 +1276,7 @@ nsDocument::Init() return NS_ERROR_ALREADY_INITIALIZED; } + mIdentifierMap.Init(); mLinkMap.Init(); mRadioGroups.Init(); @@ -1221,6 +1371,7 @@ nsDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup, #endif mDocumentTitle.SetIsVoid(PR_TRUE); + mIdentifierMap.Clear(); SetPrincipal(nsnull); mSecurityInfo = nsnull; @@ -1530,6 +1681,185 @@ nsDocument::GetLastModified(nsAString& aLastModified) return NS_OK; } +void +nsDocument::UpdateNameTableEntry(nsIContent *aContent) +{ + if (!mIsRegularHTML) + return; + + nsIAtom* name = nsContentUtils::IsNamedItem(aContent); + if (!name) + return; + + nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(name); + if (!entry) { + // We're not tracking the elements with this name + return; + } + + entry->AddNameContent(aContent); +} + +void +nsDocument::RemoveFromNameTable(nsIContent *aContent) +{ + if (!mIsRegularHTML) + return; + + nsIAtom* name = nsContentUtils::IsNamedItem(aContent); + if (!name) + return; + + nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(name); + if (!entry) { + // We're not tracking the elements with this name + return; + } + + entry->RemoveNameContent(aContent); +} + +void +nsDocument::UpdateIdTableEntry(nsIContent *aContent) +{ + nsIAtom* id = aContent->GetID(); + if (!id) + return; + + PRBool liveTable = IdTableIsLive(); + nsIdentifierMapEntry *entry = + liveTable ? mIdentifierMap.PutEntry(id) : mIdentifierMap.GetEntry(id); + + if (entry) { + entry->AddIdContent(aContent); + } +} + +void +nsDocument::RemoveFromIdTable(nsIContent *aContent) +{ + nsIAtom* id = aContent->GetID(); + if (!id) + return; + + nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(id); + if (!entry) + return; + + if (entry->RemoveIdContent(aContent)) { + mIdentifierMap.RemoveEntry(id); + } +} + +void +nsDocument::UnregisterNamedItems(nsIContent *aContent) +{ + if (aContent->IsNodeOfType(nsINode::eTEXT)) { + // Text nodes are not named items nor can they have children. + return; + } + + RemoveFromNameTable(aContent); + RemoveFromIdTable(aContent); + + PRUint32 i, count = aContent->GetChildCount(); + for (i = 0; i < count; ++i) { + UnregisterNamedItems(aContent->GetChildAt(i)); + } +} + +void +nsDocument::RegisterNamedItems(nsIContent *aContent) +{ + if (aContent->IsNodeOfType(nsINode::eTEXT)) { + // Text nodes are not named items nor can they have children. + return; + } + + UpdateNameTableEntry(aContent); + UpdateIdTableEntry(aContent); + + PRUint32 i, count = aContent->GetChildCount(); + for (i = 0; i < count; ++i) { + RegisterNamedItems(aContent->GetChildAt(i)); + } +} + +void +nsDocument::ContentAppended(nsIDocument* aDocument, + nsIContent* aContainer, + PRInt32 aNewIndexInContainer) +{ + NS_ASSERTION(aDocument == this, "unexpected doc"); + + PRUint32 count = aContainer->GetChildCount(); + for (PRUint32 i = aNewIndexInContainer; i < count; ++i) { + RegisterNamedItems(aContainer->GetChildAt(i)); + } +} + +void +nsDocument::ContentInserted(nsIDocument* aDocument, + nsIContent* aContainer, + nsIContent* aContent, + PRInt32 aIndexInContainer) +{ + NS_ASSERTION(aDocument == this, "unexpected doc"); + + NS_ABORT_IF_FALSE(aContent, "Null content!"); + + RegisterNamedItems(aContent); +} + +void +nsDocument::ContentRemoved(nsIDocument* aDocument, + nsIContent* aContainer, + nsIContent* aChild, + PRInt32 aIndexInContainer) +{ + NS_ASSERTION(aDocument == this, "unexpected doc"); + + NS_ABORT_IF_FALSE(aChild, "Null content!"); + + UnregisterNamedItems(aChild); +} + +void +nsDocument::AttributeWillChange(nsIContent* aContent, PRInt32 aNameSpaceID, + nsIAtom* aAttribute) +{ + NS_ABORT_IF_FALSE(aContent, "Null content!"); + NS_PRECONDITION(aAttribute, "Must have an attribute that's changing!"); + + if (aNameSpaceID != kNameSpaceID_None) + return; + if (aAttribute == nsGkAtoms::name) { + RemoveFromNameTable(aContent); + } else if (aAttribute == aContent->GetIDAttributeName()) { + RemoveFromIdTable(aContent); + } +} + +void +nsDocument::AttributeChanged(nsIDocument* aDocument, + nsIContent* aContent, PRInt32 aNameSpaceID, + nsIAtom* aAttribute, PRInt32 aModType, + PRUint32 aStateMask) +{ + NS_ASSERTION(aDocument == this, "unexpected doc"); + + NS_ABORT_IF_FALSE(aContent, "Null content!"); + NS_PRECONDITION(aAttribute, "Must have an attribute that's changing!"); + + if (aNameSpaceID != kNameSpaceID_None) + return; + if (aAttribute == nsGkAtoms::name) { + UpdateNameTableEntry(aContent); + } else if (aAttribute == aContent->GetIDAttributeName()) { + UpdateIdTableEntry(aContent); + } +} + nsIPrincipal* nsDocument::GetPrincipal() { @@ -2777,6 +3107,106 @@ nsDocument::CheckGetElementByIdArg(const nsAString& aId) return PR_TRUE; } +NS_IMETHODIMP +nsDocument::GetElementById(const nsAString& aElementId, + nsIDOMElement** aReturn) +{ + NS_ENSURE_ARG_POINTER(aReturn); + *aReturn = nsnull; + + nsCOMPtr idAtom(do_GetAtom(aElementId)); + NS_ENSURE_TRUE(idAtom, NS_ERROR_OUT_OF_MEMORY); + + // We don't have to flush before we do the initial hashtable lookup, since if + // the id is already in the hashtable it couldn't have been removed without + // us being notified (all removals notify immediately, as far as I can tell). + // So do the lookup first. + nsIdentifierMapEntry *entry = mIdentifierMap.PutEntry(idAtom); + NS_ENSURE_TRUE(entry, NS_ERROR_OUT_OF_MEMORY); + + PRBool isNotInDocument; + nsIContent *e = entry->GetIdContent(&isNotInDocument); + + if (!e) { + // Now we have to flush. It could be that we have a cached "not in + // document" or know nothing about this ID yet but more content has been + // added to the document since. Note that we have to flush notifications, + // so that the entry will get updated properly. + + // Make sure to stash away the current generation so we can check whether + // the table changes when we flush. + PRUint32 generation = mIdentifierMap.GetGeneration(); + + FlushPendingNotifications(Flush_ContentAndNotify); + + if (generation != mIdentifierMap.GetGeneration()) { + // Table changed, so the entry pointer is no longer valid; look up the + // entry again, adding if necessary (the adding may be necessary in case + // the flush actually deleted entries). + entry = mIdentifierMap.PutEntry(idAtom); + NS_ENSURE_TRUE(entry, NS_ERROR_OUT_OF_MEMORY); + } + + // We could now have a new entry, or the entry could have been + // updated, so update e to point to the current entry's + // mIdContent. + e = entry->GetIdContent(&isNotInDocument); + } + + if (isNotInDocument) { + // We've looked for this id before and we didn't find it, so it + // won't be in the document now either (since the + // mIdentifierMap is live for entries in the table) + + return NS_OK; + } + + if (!e) { + // If IdTableIsLive(), no need to look for the element in the document, + // since we're fully maintaining our table's state as the DOM mutates. + nsIContent* root = GetRootContent(); + if (!IdTableIsLive()) { + if (IdTableShouldBecomeLive()) { + // Just make sure our table is up to date and call this method again + // to look up in the hashtable. + if (root) { + RegisterNamedItems(root); + } + return GetElementById(aElementId, aReturn); + } + + if (root && CheckGetElementByIdArg(aElementId)) { + e = nsContentUtils::MatchElementId(root, idAtom); + } + } + + if (!e) { +#ifdef DEBUG + // No reason to call MatchElementId if !IdTableIsLive, since + // we'd have done just that already + if (IdTableIsLive() && root && !aElementId.IsEmpty()) { + nsIContent* eDebug = + nsContentUtils::MatchElementId(root, idAtom); + NS_ASSERTION(!eDebug, + "We got null for |e| but MatchElementId found something?"); + } +#endif + // There is no element with the given id in the document, cache + // the fact that it's not in the document + entry->FlagIDNotInDocument(); + + return NS_OK; + } + + // We found an element with a matching id, store that in the hash + if (NS_UNLIKELY(!entry->AddIdContent(e))) { + return NS_ERROR_OUT_OF_MEMORY; + } + } + + return CallQueryInterface(e, aReturn); +} + void nsDocument::DispatchContentLoadedEvents() { @@ -2884,13 +3314,6 @@ nsDocument::ContentStatesChanged(nsIContent* aContent1, nsIContent* aContent2, (this, aContent1, aContent2, aStateMask)); } -void -nsDocument::AttributeWillChange(nsIContent* aChild, PRInt32 aNameSpaceID, - nsIAtom* aAttribute) -{ - NS_ASSERTION(aChild, "Null child!"); -} - void nsDocument::StyleRuleChanged(nsIStyleSheet* aStyleSheet, nsIStyleRule* aOldStyleRule, @@ -3216,14 +3639,6 @@ nsDocument::GetElementsByTagNameNS(const nsAString& aNamespaceURI, return NS_OK; } -NS_IMETHODIMP -nsDocument::GetElementById(const nsAString & elementId, - nsIDOMElement **_retval) -{ - // Should be implemented by subclass - return NS_ERROR_NOT_IMPLEMENTED; -} - NS_IMETHODIMP nsDocument::GetAsync(PRBool *aAsync) { diff --git a/content/base/src/nsDocument.h b/content/base/src/nsDocument.h index fe12ca7a7aab..f482f56756e5 100644 --- a/content/base/src/nsDocument.h +++ b/content/base/src/nsDocument.h @@ -90,6 +90,7 @@ #include "nsStubMutationObserver.h" #include "nsIChannel.h" #include "nsCycleCollectionParticipant.h" +#include "nsContentList.h" // Put these here so all document impls get them automatically #include "nsHTMLStyleSheet.h" @@ -210,6 +211,68 @@ class nsUint32ToContentHashEntry : public PLDHashEntryHdr void* mValOrHash; }; +/** + * Right now our identifier map entries contain information for 'name' + * and 'id' mappings of a given string. This is so that + * nsHTMLDocument::ResolveName only has to do one hash lookup instead + * of two. It's not clear whether this still matters for performance. + * + * We also store the document.all result list here. This is mainly so that + * when all elements with the given ID are removed and we remove + * the ID's nsIdentifierMapEntry, the document.all result is released too. + * Perhaps the document.all results should have their own hashtable + * in nsHTMLDocument. + */ +class nsIdentifierMapEntry : public nsISupportsHashKey +{ +public: + nsIdentifierMapEntry(const nsISupports* aKey) : + nsISupportsHashKey(aKey), mNameContentList(nsnull) + { + } + nsIdentifierMapEntry(const nsIdentifierMapEntry& aOther) : + nsISupportsHashKey(GetKey()) + { + NS_ERROR("Should never be called"); + } + ~nsIdentifierMapEntry(); + + void SetInvalidName(); + PRBool IsInvalidName(); + void AddNameContent(nsIContent* aContent); + void RemoveNameContent(nsIContent* aContent); + PRBool HasNameContentList() { + return mNameContentList != nsnull; + } + nsBaseContentList* GetNameContentList() { + return mNameContentList; + } + nsresult CreateNameContentList(); + + /** + * Returns the element if we know the element associated with this + * id. Otherwise returns null. + * @param aIsNotInDocument if non-null, we set the output to true + * if we know for sure the element is not in the document. + */ + nsIContent* GetIdContent(PRBool* aIsNotInDocument = nsnull); + PRBool AddIdContent(nsIContent* aContent); + PRBool RemoveIdContent(nsIContent* aContent); + void FlagIDNotInDocument(); + + void Traverse(nsCycleCollectionTraversalCallback* aCallback); + + void SetDocAllList(nsContentList* aContentList) { mDocAllList = aContentList; } + nsContentList* GetDocAllList() { return mDocAllList; } + +private: + // The single element ID_NOT_IN_DOCUMENT, or empty to indicate we + // don't know what element(s) have this key as an ID + nsSmallVoidArray mIdContentList; + // NAME_NOT_VALID if this id cannot be used as a 'name' + nsBaseContentList *mNameContentList; + nsRefPtr mDocAllList; +}; class nsDocHeaderData { @@ -612,6 +675,12 @@ public: // nsIDOMNSEventTarget NS_DECL_NSIDOMNSEVENTTARGET + // nsIMutationObserver + NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED + NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED + NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED + NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED + // nsIScriptObjectPrincipal virtual nsIPrincipal* GetPrincipal(); @@ -665,6 +734,13 @@ public: nsIDOMNodeList** aReturn); protected: + void RegisterNamedItems(nsIContent *aContent); + void UnregisterNamedItems(nsIContent *aContent); + void UpdateNameTableEntry(nsIContent *aContent); + void UpdateIdTableEntry(nsIContent *aContent); + void RemoveFromNameTable(nsIContent *aContent); + void RemoveFromIdTable(nsIContent *aContent); + /** * Check that aId is not empty and log a message to the console * service if it is. @@ -772,6 +848,14 @@ protected: nsRefPtr mStyleSheetSetList; nsRefPtr mScriptLoader; nsDocHeaderData* mHeaderData; + /* mIdentifierMap works as follows for IDs: + * 1) Attribute changes affect the table immediately (removing and adding + * entries as needed). + * 2) Removals from the DOM affect the table immediately + * 3) Additions to the DOM always update existing entries, but only add new + * ones if IdTableIsLive() is true. + */ + nsTHashtable mIdentifierMap; nsClassHashtable mRadioGroups; @@ -787,6 +871,10 @@ protected: PRPackedBool mVisible:1; // True if document has ever had script handling object. PRPackedBool mHasHadScriptHandlingObject:1; + // True if this is a regular (non-XHTML) HTML document + // XXXbz should this be reset if someone manually calls + // SetContentType() on this document? + PRPackedBool mIsRegularHTML:1; PRPackedBool mHasWarnedAboutBoxObjects:1; @@ -796,6 +884,20 @@ protected: PRUint8 mDefaultElementType; + PRBool IdTableIsLive() const { + // live if we've had over 63 misses + return (mIdMissCount & 0x40) != 0; + } + + PRBool IdTableShouldBecomeLive() { + NS_ASSERTION(!IdTableIsLive(), + "Shouldn't be called if table is already live!"); + ++mIdMissCount; + return IdTableIsLive(); + } + + PRUint8 mIdMissCount; + nsInterfaceHashtable *mBoxObjectTable; nsInterfaceHashtable *mContentWrapperHash; diff --git a/content/html/document/src/nsHTMLDocument.cpp b/content/html/document/src/nsHTMLDocument.cpp index ac30ca273960..f3349acfc08b 100644 --- a/content/html/document/src/nsHTMLDocument.cpp +++ b/content/html/document/src/nsHTMLDocument.cpp @@ -158,16 +158,6 @@ const PRInt32 kBackward = 1; //#define DEBUG_charset -// Entries in an nsSmallVoidArray must not have the low bit set, so -// can't use "1" for ID_NOT_IN_DOCUMENT. "2" should be a perfectly -// reasonable value, though -- no real nsIContent* will be equal to 2. -#define ID_NOT_IN_DOCUMENT ((nsIContent *)2) -#define NAME_NOT_VALID ((nsBaseContentList*)1) - -// Returns the name atom of aContent, if the content is a named item -// and has a name atom. -static nsIAtom* IsNamedItem(nsIContent* aContent); - static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID); PRUint32 nsHTMLDocument::gWyciwygSessionCnt = 0; @@ -229,180 +219,23 @@ NS_NewHTMLDocument(nsIDocument** aInstancePtrResult) return rv; } -class IdAndNameMapEntry : public PLDHashEntryHdr -{ -public: - IdAndNameMapEntry(nsIAtom* aKey) : - mKey(aKey), mNameContentList(nsnull), mIdContentList() - { - } - - ~IdAndNameMapEntry() - { - if (mNameContentList && mNameContentList != NAME_NOT_VALID) { - NS_RELEASE(mNameContentList); - } - } - - nsIContent* GetIdContent() { - return static_cast(mIdContentList.SafeElementAt(0)); - } - - PRBool AddIdContent(nsIContent* aContent); - - PRBool RemoveIdContent(nsIContent* aContent) { - // XXXbz should this ever Compact() I guess when all the content is gone - // we'll just get cleaned up in the natural order of things... - return mIdContentList.RemoveElement(aContent) && - mIdContentList.Count() == 0; - } - - void FlagIDNotInDocument() { - NS_ASSERTION(mIdContentList.Count() == 0, - "Flagging ID not in document when we have content?"); - // Note that if this fails that's OK; this is just an optimization - mIdContentList.AppendElement(ID_NOT_IN_DOCUMENT); - } - - nsCOMPtr mKey; - nsBaseContentList *mNameContentList; - nsRefPtr mDocAllList; -private: - nsSmallVoidArray mIdContentList; -}; - -PRBool -IdAndNameMapEntry::AddIdContent(nsIContent* aContent) -{ - NS_PRECONDITION(aContent, "Must have content"); - NS_PRECONDITION(mIdContentList.IndexOf(nsnull) == -1, - "Why is null in our list?"); - NS_PRECONDITION(aContent != ID_NOT_IN_DOCUMENT, - "Bogus content pointer"); - - if (GetIdContent() == ID_NOT_IN_DOCUMENT) { - NS_ASSERTION(mIdContentList.Count() == 1, "Bogus count"); - return mIdContentList.ReplaceElementAt(aContent, 0); - } - - // Common case - if (mIdContentList.Count() == 0) { - return mIdContentList.AppendElement(aContent); - } - - // We seem to have multiple content nodes for the same id, or we're doing our - // top-down registration when the id table is going live. Search for the - // right place to insert the content. - PRInt32 start = 0; - PRInt32 end = mIdContentList.Count(); - do { - NS_ASSERTION(start < end, "Bogus start/end"); - - PRInt32 cur = (start + end) / 2; - NS_ASSERTION(cur >= start && cur < end, "What happened here?"); - - nsIContent* curContent = static_cast(mIdContentList[cur]); - if (curContent == aContent) { - // Already in the list, so already in the right spot. Get out of here. - return PR_TRUE; - } - - if (nsContentUtils::PositionIsBefore(aContent, curContent)) { - end = cur; - } else { - start = cur + 1; - } - } while (start != end); - - return mIdContentList.InsertElementAt(aContent, start); -} - - -PR_STATIC_CALLBACK(PLDHashNumber) -IdAndNameHashHashKey(PLDHashTable *table, const void *key) -{ - // Our key is an nsIAtom*, so just shift it and use that as the hash. - return NS_PTR_TO_INT32(key) >> 2; -} - -PR_STATIC_CALLBACK(PRBool) -IdAndNameHashMatchEntry(PLDHashTable *table, const PLDHashEntryHdr *entry, - const void *key) -{ - const IdAndNameMapEntry *e = - static_cast(entry); - const nsIAtom *atom = static_cast(key); - - return atom == e->mKey; -} - -PR_STATIC_CALLBACK(void) -IdAndNameHashClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry) -{ - IdAndNameMapEntry *e = static_cast(entry); - - // An entry is being cleared, let the entry do its own cleanup. - e->~IdAndNameMapEntry(); -} - -PR_STATIC_CALLBACK(PRBool) -IdAndNameHashInitEntry(PLDHashTable *table, PLDHashEntryHdr *entry, - const void *key) -{ - nsIAtom *atom = const_cast - (static_cast(key)); - - // Inititlize the entry with placement new - new (entry) IdAndNameMapEntry(atom); - return PR_TRUE; -} - // NOTE! nsDocument::operator new() zeroes out all members, so don't // bother initializing members to 0. nsHTMLDocument::nsHTMLDocument() - : nsDocument("text/html"), - mDefaultNamespaceID(kNameSpaceID_None) + : nsDocument("text/html") { - // NOTE! nsDocument::operator new() zeroes out all members, so don't // bother initializing members to 0. + mIsRegularHTML = PR_TRUE; mDefaultElementType = kNameSpaceID_XHTML; mCompatMode = eCompatibility_NavQuirks; } -nsHTMLDocument::~nsHTMLDocument() -{ - if (mIdAndNameHashTable.ops) { - PL_DHashTableFinish(&mIdAndNameHashTable); - } -} - NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLDocument) -PR_STATIC_CALLBACK(PLDHashOperator) -IdAndNameMapEntryTraverse(PLDHashTable *table, PLDHashEntryHdr *hdr, - PRUint32 number, void *arg) -{ - nsCycleCollectionTraversalCallback *cb = - static_cast(arg); - IdAndNameMapEntry *entry = static_cast(hdr); - - if (entry->mNameContentList != NAME_NOT_VALID) - cb->NoteXPCOMChild(entry->mNameContentList); - - cb->NoteXPCOMChild(static_cast(entry->mDocAllList)); - - return PL_DHASH_NEXT; -} - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLDocument, nsDocument) - if (tmp->mIdAndNameHashTable.ops) { - PL_DHashTableEnumerate(&tmp->mIdAndNameHashTable, - IdAndNameMapEntryTraverse, - &cb); - } NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mImageMaps) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mImages) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mApplets) @@ -442,28 +275,7 @@ nsHTMLDocument::Init() CSSLoader()->SetCaseSensitive(IsXHTML()); CSSLoader()->SetCompatibilityMode(mCompatMode); - static PLDHashTableOps hash_table_ops = - { - PL_DHashAllocTable, - PL_DHashFreeTable, - IdAndNameHashHashKey, - IdAndNameHashMatchEntry, - PL_DHashMoveEntryStub, - IdAndNameHashClearEntry, - PL_DHashFinalizeStub, - IdAndNameHashInitEntry - }; - - PRBool ok = PL_DHashTableInit(&mIdAndNameHashTable, &hash_table_ops, nsnull, - sizeof(IdAndNameMapEntry), 16); - if (!ok) { - mIdAndNameHashTable.ops = nsnull; - - return NS_ERROR_OUT_OF_MEMORY; - } - - PrePopulateHashTables(); - + PrePopulateIdentifierMap(); return NS_OK; } @@ -486,8 +298,7 @@ nsHTMLDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup, nsDocument::ResetToURI(aURI, aLoadGroup, aPrincipal); - InvalidateHashTables(); - PrePopulateHashTables(); + PrePopulateIdentifierMap(); mImages = nsnull; mApplets = nsnull; @@ -846,13 +657,13 @@ nsHTMLDocument::StartDocumentLoad(const char* aCommand, (!aCommand || nsCRT::strcmp(aCommand, "view-source") != 0)) { // We're parsing XHTML as XML, remember that. - mDefaultNamespaceID = kNameSpaceID_XHTML; + mIsRegularHTML = PR_FALSE; mCompatMode = eCompatibility_FullStandards; } #ifdef DEBUG else { - NS_ASSERTION(mDefaultNamespaceID == kNameSpaceID_None, - "Hey, someone forgot to reset mDefaultNamespaceID!!!"); + NS_ASSERTION(mIsRegularHTML, + "Hey, someone forgot to reset mIsRegularHTML!!!"); } #endif @@ -1351,101 +1162,6 @@ nsHTMLDocument::SetCompatibilityMode(nsCompatibility aMode) } } -void -nsHTMLDocument::ContentAppended(nsIDocument* aDocument, - nsIContent* aContainer, - PRInt32 aNewIndexInContainer) -{ - NS_ASSERTION(aDocument == this, "unexpected doc"); - - PRUint32 count = aContainer->GetChildCount(); - for (PRUint32 i = aNewIndexInContainer; i < count; ++i) { - RegisterNamedItems(aContainer->GetChildAt(i)); - } -} - -void -nsHTMLDocument::ContentInserted(nsIDocument* aDocument, - nsIContent* aContainer, - nsIContent* aContent, - PRInt32 aIndexInContainer) -{ - NS_ASSERTION(aDocument == this, "unexpected doc"); - - NS_ABORT_IF_FALSE(aContent, "Null content!"); - - RegisterNamedItems(aContent); -} - -void -nsHTMLDocument::ContentRemoved(nsIDocument* aDocument, - nsIContent* aContainer, - nsIContent* aChild, - PRInt32 aIndexInContainer) -{ - NS_ASSERTION(aDocument == this, "unexpected doc"); - - NS_ABORT_IF_FALSE(aChild, "Null content!"); - - UnregisterNamedItems(aChild); -} - -void -nsHTMLDocument::AttributeWillChange(nsIContent* aContent, PRInt32 aNameSpaceID, - nsIAtom* aAttribute) -{ - NS_ABORT_IF_FALSE(aContent, "Null content!"); - NS_PRECONDITION(aAttribute, "Must have an attribute that's changing!"); - - if (!IsXHTML() && aAttribute == nsGkAtoms::name && - aNameSpaceID == kNameSpaceID_None) { - nsIAtom* name = IsNamedItem(aContent); - if (name) { - nsresult rv = RemoveFromNameTable(name, aContent); - - if (NS_FAILED(rv)) { - return; - } - } - } else if (aAttribute == aContent->GetIDAttributeName() && - aNameSpaceID == kNameSpaceID_None) { - nsresult rv = RemoveFromIdTable(aContent); - - if (NS_FAILED(rv)) { - return; - } - } - - nsDocument::AttributeWillChange(aContent, aNameSpaceID, aAttribute); -} - -void -nsHTMLDocument::AttributeChanged(nsIDocument* aDocument, - nsIContent* aContent, PRInt32 aNameSpaceID, - nsIAtom* aAttribute, PRInt32 aModType, - PRUint32 aStateMask) -{ - NS_ASSERTION(aDocument == this, "unexpected doc"); - - NS_ABORT_IF_FALSE(aContent, "Null content!"); - NS_PRECONDITION(aAttribute, "Must have an attribute that's changing!"); - - if (!IsXHTML() && aAttribute == nsGkAtoms::name && - aNameSpaceID == kNameSpaceID_None) { - - nsIAtom* name = IsNamedItem(aContent); - if (name) { - UpdateNameTableEntry(name, aContent); - } - } else if (aAttribute == aContent->GetIDAttributeName() && - aNameSpaceID == kNameSpaceID_None) { - nsIAtom* id = aContent->GetID(); - if (id) { - UpdateIdTableEntry(id, aContent); - } - } -} - PRBool nsHTMLDocument::IsCaseSensitive() { @@ -1863,7 +1579,7 @@ NS_IMETHODIMP nsHTMLDocument::GetImages(nsIDOMHTMLCollection** aImages) { if (!mImages) { - mImages = new nsContentList(this, nsGkAtoms::img, mDefaultNamespaceID); + mImages = new nsContentList(this, nsGkAtoms::img, GetDefaultNamespaceID()); if (!mImages) { return NS_ERROR_OUT_OF_MEMORY; } @@ -1880,7 +1596,7 @@ nsHTMLDocument::GetApplets(nsIDOMHTMLCollection** aApplets) { if (!mApplets) { mApplets = new nsContentList(this, nsGkAtoms::applet, - mDefaultNamespaceID); + GetDefaultNamespaceID()); if (!mApplets) { return NS_ERROR_OUT_OF_MEMORY; } @@ -2565,111 +2281,6 @@ nsHTMLDocument::Writeln() return ScriptWriteCommon(PR_TRUE); } -NS_IMETHODIMP -nsHTMLDocument::GetElementById(const nsAString& aElementId, - nsIDOMElement** aReturn) -{ - NS_ENSURE_ARG_POINTER(aReturn); - *aReturn = nsnull; - - nsCOMPtr idAtom(do_GetAtom(aElementId)); - NS_ENSURE_TRUE(idAtom, NS_ERROR_OUT_OF_MEMORY); - - // We don't have to flush before we do the initial hashtable lookup, since if - // the id is already in the hashtable it couldn't have been removed without - // us being notified (all removals notify immediately, as far as I can tell). - // So do the lookup first. - IdAndNameMapEntry *entry = - static_cast - (PL_DHashTableOperate(&mIdAndNameHashTable, idAtom, - PL_DHASH_ADD)); - NS_ENSURE_TRUE(entry, NS_ERROR_OUT_OF_MEMORY); - - nsIContent *e = entry->GetIdContent(); - - if (!e || e == ID_NOT_IN_DOCUMENT) { - // Now we have to flush. It could be that we have a cached "not in - // document" or know nothing about this ID yet but more content has been - // added to the document since. Note that we have to flush notifications, - // so that the entry will get updated properly. - - // Make sure to stash away the current generation so we can check whether - // the table changes when we flush. - PRUint32 generation = mIdAndNameHashTable.generation; - - FlushPendingNotifications(Flush_ContentAndNotify); - - if (generation != mIdAndNameHashTable.generation) { - // Table changed, so the entry pointer is no longer valid; look up the - // entry again, adding if necessary (the adding may be necessary in case - // the flush actually deleted entries). - entry = - static_cast - (PL_DHashTableOperate(&mIdAndNameHashTable, idAtom, - PL_DHASH_ADD)); - NS_ENSURE_TRUE(entry, NS_ERROR_OUT_OF_MEMORY); - } - - // We could now have a new entry, or the entry could have been - // updated, so update e to point to the current entry's - // mIdContent. - e = entry->GetIdContent(); - } - - if (e == ID_NOT_IN_DOCUMENT) { - // We've looked for this id before and we didn't find it, so it - // won't be in the document now either (since the - // mIdAndNameHashTable is live for entries in the table) - - return NS_OK; - } - - if (!e) { - // If IdTableIsLive(), no need to look for the element in the document, - // since we're fully maintaining our table's state as the DOM mutates. - nsIContent* root = GetRootContent(); - if (!IdTableIsLive()) { - if (IdTableShouldBecomeLive()) { - // Just make sure our table is up to date and call this method again - // to look up in the hashtable. - if (root) { - RegisterNamedItems(root); - } - return GetElementById(aElementId, aReturn); - } - - if (root && CheckGetElementByIdArg(aElementId)) { - e = nsContentUtils::MatchElementId(root, idAtom); - } - } - - if (!e) { -#ifdef DEBUG - // No reason to call MatchElementId if !IdTableIsLive, since - // we'd have done just that already - if (IdTableIsLive() && root && !aElementId.IsEmpty()) { - nsIContent* eDebug = - nsContentUtils::MatchElementId(root, idAtom); - NS_ASSERTION(!eDebug, - "We got null for |e| but MatchElementId found something?"); - } -#endif - // There is no element with the given id in the document, cache - // the fact that it's not in the document - entry->FlagIDNotInDocument(); - - return NS_OK; - } - - // We found an element with a matching id, store that in the hash - if (NS_UNLIKELY(!entry->AddIdContent(e))) { - return NS_ERROR_OUT_OF_MEMORY; - } - } - - return CallQueryInterface(e, aReturn); -} - NS_IMETHODIMP nsHTMLDocument::ImportNode(nsIDOMNode* aImportedNode, PRBool aDeep, @@ -2700,6 +2311,13 @@ nsHTMLDocument::GetElementsByTagNameNS(const nsAString& aNamespaceURI, return nsDocument::GetElementsByTagNameNS(aNamespaceURI, tmp, aReturn); } +NS_IMETHODIMP +nsHTMLDocument::GetElementById(const nsAString& aElementId, + nsIDOMElement** aReturn) +{ + return nsDocument::GetElementById(aElementId, aReturn); +} + PRBool nsHTMLDocument::MatchNameAttribute(nsIContent* aContent, PRInt32 aNamespaceID, nsIAtom* aAtom, void* aData) @@ -2998,7 +2616,7 @@ NS_IMETHODIMP nsHTMLDocument::GetEmbeds(nsIDOMHTMLCollection** aEmbeds) { if (!mEmbeds) { - mEmbeds = new nsContentList(this, nsGkAtoms::embed, mDefaultNamespaceID); + mEmbeds = new nsContentList(this, nsGkAtoms::embed, GetDefaultNamespaceID()); if (!mEmbeds) { return NS_ERROR_OUT_OF_MEMORY; } @@ -3102,283 +2720,13 @@ nsHTMLDocument::GetPlugins(nsIDOMHTMLCollection** aPlugins) return GetEmbeds(aPlugins); } -PR_STATIC_CALLBACK(PLDHashOperator) -IdAndNameMapEntryRemoveCallback(PLDHashTable *table, PLDHashEntryHdr *hdr, - PRUint32 number, void *arg) -{ - return PL_DHASH_REMOVE; -} - - -void -nsHTMLDocument::InvalidateHashTables() -{ - PL_DHashTableEnumerate(&mIdAndNameHashTable, IdAndNameMapEntryRemoveCallback, - nsnull); -} - -static nsresult -ReserveNameInHash(const char* aName, PLDHashTable *aHash) -{ - nsCOMPtr atom(do_GetAtom(aName)); - NS_ENSURE_TRUE(atom, NS_ERROR_OUT_OF_MEMORY); - - IdAndNameMapEntry *entry = - static_cast - (PL_DHashTableOperate(aHash, atom, PL_DHASH_ADD)); - - NS_ENSURE_TRUE(entry, NS_ERROR_OUT_OF_MEMORY); - - entry->mNameContentList = NAME_NOT_VALID; - - return NS_OK; -} - -// Pre-fill the name hash with names that are likely to be resolved in -// this document to avoid walking the tree looking for elements with -// these names. - -nsresult -nsHTMLDocument::PrePopulateHashTables() -{ - nsresult rv = NS_OK; - - rv = ReserveNameInHash("write", &mIdAndNameHashTable); - NS_ENSURE_SUCCESS(rv, rv); - - rv = ReserveNameInHash("writeln", &mIdAndNameHashTable); - NS_ENSURE_SUCCESS(rv, rv); - - rv = ReserveNameInHash("open", &mIdAndNameHashTable); - NS_ENSURE_SUCCESS(rv, rv); - - rv = ReserveNameInHash("close", &mIdAndNameHashTable); - NS_ENSURE_SUCCESS(rv, rv); - - rv = ReserveNameInHash("forms", &mIdAndNameHashTable); - NS_ENSURE_SUCCESS(rv, rv); - - rv = ReserveNameInHash("elements", &mIdAndNameHashTable); - NS_ENSURE_SUCCESS(rv, rv); - - rv = ReserveNameInHash("characterSet", &mIdAndNameHashTable); - NS_ENSURE_SUCCESS(rv, rv); - - rv = ReserveNameInHash("nodeType", &mIdAndNameHashTable); - NS_ENSURE_SUCCESS(rv, rv); - - rv = ReserveNameInHash("parentNode", &mIdAndNameHashTable); - NS_ENSURE_SUCCESS(rv, rv); - - rv = ReserveNameInHash("cookie", &mIdAndNameHashTable); - NS_ENSURE_SUCCESS(rv, rv); - - return rv; -} - -static nsIAtom* -IsNamedItem(nsIContent* aContent) -{ - // Only the content types reflected in Level 0 with a NAME - // attribute are registered. Images, layers and forms always get - // reflected up to the document. Applets and embeds only go - // to the closest container (which could be a form). - nsGenericHTMLElement* elm = nsGenericHTMLElement::FromContent(aContent); - if (!elm) { - return nsnull; - } - - nsIAtom* tag = elm->Tag(); - if (tag != nsGkAtoms::img && - tag != nsGkAtoms::form && - tag != nsGkAtoms::applet && - tag != nsGkAtoms::embed && - tag != nsGkAtoms::object) { - return nsnull; - } - - const nsAttrValue* val = elm->GetParsedAttr(nsGkAtoms::name); - if (val && val->Type() == nsAttrValue::eAtom) { - return val->GetAtomValue(); - } - - return nsnull; -} - -nsresult -nsHTMLDocument::UpdateNameTableEntry(nsIAtom* aName, - nsIContent *aContent) -{ - NS_ASSERTION(!IsXHTML(), - "nsHTMLDocument::UpdateNameTableEntry Don't call me on an XHTML document!!!"); - - IdAndNameMapEntry *entry = - static_cast - (PL_DHashTableOperate(&mIdAndNameHashTable, aName, - PL_DHASH_LOOKUP)); - - if (PL_DHASH_ENTRY_IS_FREE(entry)) { - return NS_OK; - } - - nsBaseContentList *list = entry->mNameContentList; - - if (!list || list == NAME_NOT_VALID) { - return NS_OK; - } - - // NOTE: this indexof is absolutely needed, since we don't flush - // content notifications when we do document.foo resolution. So - // aContent may be in our list already and just now getting notified - // for! - if (list->IndexOf(aContent, PR_FALSE) < 0) { - list->AppendElement(aContent); - } - - return NS_OK; -} - -nsresult -nsHTMLDocument::UpdateIdTableEntry(nsIAtom* aId, nsIContent *aContent) -{ - PRBool liveTable = IdTableIsLive(); - PLDHashOperator op = liveTable ? PL_DHASH_ADD : PL_DHASH_LOOKUP; - IdAndNameMapEntry *entry = - static_cast - (PL_DHashTableOperate(&mIdAndNameHashTable, aId, - op)); - - NS_ENSURE_TRUE(entry, NS_ERROR_OUT_OF_MEMORY); - - if (PL_DHASH_ENTRY_IS_BUSY(entry) && - NS_UNLIKELY(!entry->AddIdContent(aContent))) { - // failed to update... - return NS_ERROR_OUT_OF_MEMORY; - } - - return NS_OK; -} - -nsresult -nsHTMLDocument::RemoveFromNameTable(nsIAtom* aName, nsIContent *aContent) -{ - NS_ASSERTION(!IsXHTML(), - "nsHTMLDocument::RemoveFromNameTable Don't call me on an XHTML document!!!"); - - IdAndNameMapEntry *entry = - static_cast - (PL_DHashTableOperate(&mIdAndNameHashTable, aName, - PL_DHASH_LOOKUP)); - - if (PL_DHASH_ENTRY_IS_BUSY(entry) && entry->mNameContentList && - entry->mNameContentList != NAME_NOT_VALID) { - entry->mNameContentList->RemoveElement(aContent); - } - - return NS_OK; -} - -nsresult -nsHTMLDocument::RemoveFromIdTable(nsIContent *aContent) -{ - nsIAtom* id = aContent->GetID(); - - if (!id) { - return NS_OK; - } - - IdAndNameMapEntry *entry = - static_cast - (PL_DHashTableOperate(&mIdAndNameHashTable, id, - PL_DHASH_LOOKUP)); - - if (PL_DHASH_ENTRY_IS_FREE(entry)) { - return NS_OK; - } - - if (entry->RemoveIdContent(aContent)) { - PL_DHashTableRawRemove(&mIdAndNameHashTable, entry); - } - - return NS_OK; -} - -nsresult -nsHTMLDocument::UnregisterNamedItems(nsIContent *aContent) -{ - if (aContent->IsNodeOfType(nsINode::eTEXT)) { - // Text nodes are not named items nor can they have children. - return NS_OK; - } - - nsresult rv = NS_OK; - - if (!IsXHTML()) { - nsIAtom* name = IsNamedItem(aContent); - if (name) { - rv = RemoveFromNameTable(name, aContent); - - if (NS_FAILED(rv)) { - return rv; - } - } - } - - rv = RemoveFromIdTable(aContent); - - if (NS_FAILED(rv)) { - return rv; - } - - PRUint32 i, count = aContent->GetChildCount(); - - for (i = 0; i < count; ++i) { - UnregisterNamedItems(aContent->GetChildAt(i)); - } - - return NS_OK; -} - -nsresult -nsHTMLDocument::RegisterNamedItems(nsIContent *aContent) -{ - if (aContent->IsNodeOfType(nsINode::eTEXT)) { - // Text nodes are not named items nor can they have children. - return NS_OK; - } - - if (!IsXHTML()) { - nsIAtom* name = IsNamedItem(aContent); - if (name) { - UpdateNameTableEntry(name, aContent); - } - } - - nsIAtom* id = aContent->GetID(); - if (id) { - nsresult rv = UpdateIdTableEntry(id, aContent); - - if (NS_FAILED(rv)) { - return rv; - } - } - - PRUint32 i, count = aContent->GetChildCount(); - - for (i = 0; i < count; ++i) { - RegisterNamedItems(aContent->GetChildAt(i)); - } - - return NS_OK; -} - static void FindNamedItems(nsIAtom* aName, nsIContent *aContent, - IdAndNameMapEntry& aEntry, PRBool aIsXHTML) + nsIdentifierMapEntry* aEntry) { - NS_ASSERTION(aEntry.mNameContentList, + NS_ASSERTION(aEntry->HasNameContentList(), "Entry w/o content list passed to FindNamedItems()!"); - NS_ASSERTION(aEntry.mNameContentList != NAME_NOT_VALID, + NS_ASSERTION(!aEntry->IsInvalidName(), "Entry that should never have a list passed to FindNamedItems()!"); if (aContent->IsNodeOfType(nsINode::eTEXT)) { @@ -3386,22 +2734,19 @@ FindNamedItems(nsIAtom* aName, nsIContent *aContent, return; } - nsAutoString value; - - if (!aIsXHTML && aName == IsNamedItem(aContent)) { - aEntry.mNameContentList->AppendElement(aContent); + if (aName == nsContentUtils::IsNamedItem(aContent)) { + aEntry->AddNameContent(aContent); } - if (!aEntry.GetIdContent() && + if (!aEntry->GetIdContent() && // Maybe this node has the right id? aName == aContent->GetID()) { - aEntry.AddIdContent(aContent); + aEntry->AddIdContent(aContent); } PRUint32 i, count = aContent->GetChildCount(); - for (i = 0; i < count; ++i) { - FindNamedItems(aName, aContent->GetChildAt(i), aEntry, aIsXHTML); + FindNamedItems(aName, aContent->GetChildAt(i), aEntry); } } @@ -3412,9 +2757,8 @@ nsHTMLDocument::ResolveName(const nsAString& aName, { *aResult = nsnull; - if (IsXHTML()) { - // We don't dynamically resolve names on XHTML documents. - + if (!mIsRegularHTML) { + // We don't dynamically resolve names on non-HTML documents. return NS_OK; } @@ -3422,14 +2766,10 @@ nsHTMLDocument::ResolveName(const nsAString& aName, // We have built a table and cache the named items. The table will // be updated as content is added and removed. - - IdAndNameMapEntry *entry = - static_cast - (PL_DHashTableOperate(&mIdAndNameHashTable, name, - PL_DHASH_ADD)); + nsIdentifierMapEntry *entry = mIdentifierMap.PutEntry(name); NS_ENSURE_TRUE(entry, NS_ERROR_OUT_OF_MEMORY); - if (entry->mNameContentList == NAME_NOT_VALID) { + if (entry->IsInvalidName()) { // There won't be any named items by this name -- it's reserved return NS_OK; } @@ -3441,28 +2781,22 @@ nsHTMLDocument::ResolveName(const nsAString& aName, // Make sure to stash away the current generation so we can check whether the // table changes when we flush. - PRUint32 generation = mIdAndNameHashTable.generation; + PRUint32 generation = mIdentifierMap.GetGeneration(); // If we already have an entry->mNameContentList, we need to flush out // notifications too, so that it will get updated properly. - FlushPendingNotifications(entry->mNameContentList ? + FlushPendingNotifications(entry->HasNameContentList() ? Flush_ContentAndNotify : Flush_Content); - if (generation != mIdAndNameHashTable.generation) { + if (generation != mIdentifierMap.GetGeneration()) { // Table changed, so the entry pointer is no longer valid; look up the // entry again, adding if necessary (the adding may be necessary in case // the flush actually deleted entries). - entry = - static_cast - (PL_DHashTableOperate(&mIdAndNameHashTable, name, - PL_DHASH_ADD)); + entry = mIdentifierMap.PutEntry(name); NS_ENSURE_TRUE(entry, NS_ERROR_OUT_OF_MEMORY); } - - nsBaseContentList *list = entry->mNameContentList; - - if (!list) { + if (!entry->HasNameContentList()) { #ifdef DEBUG_jst { printf ("nsHTMLDocument name cache miss for name '%s'\n", @@ -3470,20 +2804,18 @@ nsHTMLDocument::ResolveName(const nsAString& aName, } #endif - list = new nsBaseContentList(); - NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY); - - entry->mNameContentList = list; - NS_ADDREF(entry->mNameContentList); + nsresult rv = entry->CreateNameContentList(); + if (NS_FAILED(rv)) + return rv; nsIContent* root = GetRootContent(); if (root && !aName.IsEmpty()) { - // We'll never get here if !IsXHTML(), so we can just pass - // PR_FALSE to FindNamedItems(). - FindNamedItems(name, root, *entry, PR_FALSE); + FindNamedItems(name, root, entry); } } + nsBaseContentList *list = entry->GetNameContentList(); + PRUint32 length; list->GetLength(&length); @@ -3552,7 +2884,7 @@ nsHTMLDocument::ResolveName(const nsAString& aName, nsIContent *e = entry->GetIdContent(); - if (e && e != ID_NOT_IN_DOCUMENT && e->IsNodeOfType(nsINode::eHTML)) { + if (e && e->IsNodeOfType(nsINode::eHTML)) { nsIAtom *tag = e->Tag(); if ((tag == nsGkAtoms::embed || @@ -3567,6 +2899,31 @@ nsHTMLDocument::ResolveName(const nsAString& aName, return NS_OK; } +// Pre-fill the name hash with names that are likely to be resolved in +// this document to avoid walking the tree looking for elements with +// these names. + +nsresult +nsHTMLDocument::PrePopulateIdentifierMap() +{ + static const char names[][13] = { + "write", "writeln", "open", "close", "forms", "elements", + "characterSet", "nodeType", "parentNode", "cookie" + }; + + for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(names); ++i) { + nsCOMPtr atom(do_GetAtom(names[i])); + NS_ENSURE_TRUE(atom, NS_ERROR_OUT_OF_MEMORY); + + nsIdentifierMapEntry* entry = mIdentifierMap.PutEntry(atom); + NS_ENSURE_TRUE(entry, NS_ERROR_OUT_OF_MEMORY); + + entry->SetInvalidName(); + } + + return NS_OK; +} + //---------------------------- /* virtual */ nsIContent* @@ -3620,7 +2977,7 @@ nsContentList* nsHTMLDocument::GetForms() { if (!mForms) - mForms = new nsContentList(this, nsGkAtoms::form, mDefaultNamespaceID); + mForms = new nsContentList(this, nsGkAtoms::form, GetDefaultNamespaceID()); return mForms; } @@ -3852,19 +3209,16 @@ nsHTMLDocument::GetDocumentAllResult(const nsAString& aID, nsISupports** aResult { *aResult = nsnull; - PLDHashOperator op = IdTableIsLive() ? PL_DHASH_LOOKUP : PL_DHASH_ADD; - nsCOMPtr id = do_GetAtom(aID); - IdAndNameMapEntry *entry = - static_cast - (PL_DHashTableOperate(&mIdAndNameHashTable, id, op)); - NS_ENSURE_TRUE(entry, NS_ERROR_OUT_OF_MEMORY); - - // If we did a lookup and it failed, there are no items with this id - if (PL_DHASH_ENTRY_IS_FREE(entry)) { - NS_ASSERTION(IdTableIsLive(), "should have gotten a busy entry"); - - return NS_OK; + nsIdentifierMapEntry *entry; + if (IdTableIsLive()) { + entry = mIdentifierMap.GetEntry(id); + // If we did a lookup and it failed, there are no items with this id + if (!entry) + return NS_OK; + } else { + entry = mIdentifierMap.PutEntry(id); + NS_ENSURE_TRUE(entry, NS_ERROR_OUT_OF_MEMORY); } nsIContent* root = GetRootContent(); @@ -3872,14 +3226,14 @@ nsHTMLDocument::GetDocumentAllResult(const nsAString& aID, nsISupports** aResult return NS_OK; } - if (!entry->mDocAllList) { - entry->mDocAllList = new nsContentList(root, DocAllResultMatch, - nsnull, nsnull, PR_TRUE, id); - NS_ENSURE_TRUE(entry->mDocAllList, NS_ERROR_OUT_OF_MEMORY); + nsRefPtr docAllList = entry->GetDocAllList(); + if (!docAllList) { + docAllList = new nsContentList(root, DocAllResultMatch, + nsnull, nsnull, PR_TRUE, id); + NS_ENSURE_TRUE(docAllList, NS_ERROR_OUT_OF_MEMORY); + entry->SetDocAllList(docAllList); } - nsRefPtr docAllList = entry->mDocAllList; - // Check if there are more than 1 entries. Do this by getting the second one // rather than the length since getting the length always requires walking // the entire document. @@ -3887,7 +3241,6 @@ nsHTMLDocument::GetDocumentAllResult(const nsAString& aID, nsISupports** aResult nsIContent* cont = docAllList->Item(1, PR_TRUE); if (cont) { NS_ADDREF(*aResult = static_cast(docAllList)); - return NS_OK; } diff --git a/content/html/document/src/nsHTMLDocument.h b/content/html/document/src/nsHTMLDocument.h index 87d3b92c2eaf..5e796e0436fe 100644 --- a/content/html/document/src/nsHTMLDocument.h +++ b/content/html/document/src/nsHTMLDocument.h @@ -74,7 +74,6 @@ class nsHTMLDocument : public nsDocument, { public: nsHTMLDocument(); - virtual ~nsHTMLDocument(); virtual nsresult Init(); NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr); @@ -123,18 +122,8 @@ public: virtual NS_HIDDEN_(nsContentList*) GetFormControls(); - virtual void AttributeWillChange(nsIContent* aChild, - PRInt32 aNameSpaceID, - nsIAtom* aAttribute); - virtual PRBool IsCaseSensitive(); - // nsIMutationObserver - NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED - NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED - NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED - NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED - // nsIDOMDocument interface NS_DECL_NSIDOMDOCUMENT @@ -178,8 +167,8 @@ public: NS_DECL_NSIDOMNSHTMLDOCUMENT virtual nsresult ResolveName(const nsAString& aName, - nsIDOMHTMLFormElement *aForm, - nsISupports **aResult); + nsIDOMHTMLFormElement *aForm, + nsISupports **aResult); virtual void ScriptLoading(nsIScriptElement *aScript); virtual void ScriptExecuted(nsIScriptElement *aScript); @@ -191,7 +180,7 @@ public: PRBool IsXHTML() { - return mDefaultNamespaceID == kNameSpaceID_XHTML; + return !mIsRegularHTML; } #ifdef DEBUG @@ -227,15 +216,7 @@ protected: nsresult GetBodySize(PRInt32* aWidth, PRInt32* aHeight); - nsresult RegisterNamedItems(nsIContent *aContent); - nsresult UnregisterNamedItems(nsIContent *aContent); - nsresult UpdateNameTableEntry(nsIAtom* aName, nsIContent *aContent); - nsresult UpdateIdTableEntry(nsIAtom* aId, nsIContent *aContent); - nsresult RemoveFromNameTable(nsIAtom* aName, nsIContent *aContent); - nsresult RemoveFromIdTable(nsIContent *aContent); - - void InvalidateHashTables(); - nsresult PrePopulateHashTables(); + nsresult PrePopulateIdentifierMap(); nsIContent *MatchId(nsIContent *aContent, const nsAString& aId); @@ -267,9 +248,9 @@ protected: void *GenerateParserKey(void); - PRInt32 GetDefaultNamespaceID() const + virtual PRInt32 GetDefaultNamespaceID() const { - return mDefaultNamespaceID; + return mIsRegularHTML ? kNameSpaceID_None : kNameSpaceID_XHTML; } nsCOMArray mImageMaps; @@ -347,29 +328,6 @@ protected: PRPackedBool mTooDeepWriteRecursion; - PRBool IdTableIsLive() const { - // live if we've had over 63 misses - return (mIdMissCount & 0x40) != 0; - } - - PRBool IdTableShouldBecomeLive() { - NS_ASSERTION(!IdTableIsLive(), - "Shouldn't be called if table is already live!"); - ++mIdMissCount; - return IdTableIsLive(); - } - - PRUint8 mIdMissCount; - - /* mIdAndNameHashTable works as follows for IDs: - * 1) Attribute changes affect the table immediately (removing and adding - * entries as needed). - * 2) Removals from the DOM affect the table immediately - * 3) Additions to the DOM always update existing entries, but only add new - * ones if IdTableIsLive() is true. - */ - PLDHashTable mIdAndNameHashTable; - nsCOMPtr mWyciwygChannel; /* Midas implementation */ @@ -387,12 +345,6 @@ protected: static jsval sCutCopyInternal_id; static jsval sPasteInternal_id; - // kNameSpaceID_None for good ol' HTML documents, and - // kNameSpaceID_XHTML for spiffy new XHTML documents. - // XXXbz should this be reset if someone manually calls - // SetContentType() on this document? - PRInt32 mDefaultNamespaceID; - // Parser used for constructing document fragments. nsCOMPtr mFragmentParser; }; diff --git a/content/xml/document/src/nsXMLDocument.cpp b/content/xml/document/src/nsXMLDocument.cpp index e1a29c5391f3..906a18b95a22 100644 --- a/content/xml/document/src/nsXMLDocument.cpp +++ b/content/xml/document/src/nsXMLDocument.cpp @@ -563,36 +563,6 @@ nsXMLDocument::CloneNode(PRBool aDeep, nsIDOMNode** aReturn) // nsIDOMDocument interface -NS_IMETHODIMP -nsXMLDocument::GetElementById(const nsAString& aElementId, - nsIDOMElement** aReturn) -{ - NS_ENSURE_ARG_POINTER(aReturn); - *aReturn = nsnull; - - if (!CheckGetElementByIdArg(aElementId)) - return NS_OK; - - // If we tried to load a document and something went wrong, we might not have - // root content. This can happen when you do document.load() and the document - // to load is not XML, for example. - nsIContent* root = GetRootContent(); - if (!root) - return NS_OK; - - // XXX For now, we do a brute force search of the content tree. - // We should come up with a more efficient solution. - // Note that content is *not* refcounted here, so do *not* release it! - nsIContent *content = - nsContentUtils::MatchElementId(root, aElementId); - - if (!content) { - return NS_OK; - } - - return CallQueryInterface(content, aReturn); -} - nsresult nsXMLDocument::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const { diff --git a/content/xml/document/src/nsXMLDocument.h b/content/xml/document/src/nsXMLDocument.h index 0491903abd67..448f207c2528 100644 --- a/content/xml/document/src/nsXMLDocument.h +++ b/content/xml/document/src/nsXMLDocument.h @@ -78,10 +78,6 @@ public: // nsIDOMNode interface NS_IMETHOD CloneNode(PRBool aDeep, nsIDOMNode** aReturn); - // nsIDOMDocument interface - NS_IMETHOD GetElementById(const nsAString& aElementId, - nsIDOMElement** aReturn); - // nsIInterfaceRequestor NS_DECL_NSIINTERFACEREQUESTOR diff --git a/xpcom/glue/nsTHashtable.h b/xpcom/glue/nsTHashtable.h index a06efea333f5..c97354189572 100644 --- a/xpcom/glue/nsTHashtable.h +++ b/xpcom/glue/nsTHashtable.h @@ -130,6 +130,12 @@ public: */ PRBool IsInitialized() const { return !!mTable.entrySize; } + /** + * Return the generation number for the table. This increments whenever + * the table data items are moved. + */ + PRUint32 GetGeneration() const { return mTable.generation; } + /** * KeyType is typedef'ed for ease of use. */ From a4b835e94323c831b49222026c50d8e0ece697e3 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Mon, 23 Jun 2008 13:48:05 +1200 Subject: [PATCH 56/66] Bug 344258. Make XUL use the shared ID-element map. r+sr=jst --- content/base/src/nsDocument.cpp | 10 +- content/base/src/nsDocument.h | 8 +- content/xul/document/public/nsIXULDocument.h | 17 +- content/xul/document/src/Makefile.in | 1 - content/xul/document/src/nsXULDocument.cpp | 240 ++++++++++-------- content/xul/document/src/nsXULDocument.h | 53 +++- content/xul/document/test/test_bug311681.xul | 6 +- content/xul/document/test/test_bug403868.xul | 14 +- .../xul/templates/src/nsXULContentBuilder.cpp | 2 +- 9 files changed, 206 insertions(+), 145 deletions(-) diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index ac7d86426651..c9c72a6bd24c 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -338,6 +338,14 @@ nsIdentifierMapEntry::GetIdContent(PRBool* aNotInDocument) return c != ID_NOT_IN_DOCUMENT ? c : nsnull; } +void +nsIdentifierMapEntry::AppendAllIdContent(nsCOMArray* aElements) +{ + for (PRInt32 i = 0; i < mIdContentList.Count(); ++i) { + aElements->AppendObject(static_cast(mIdContentList[i])); + } +} + PRBool nsIdentifierMapEntry::AddIdContent(nsIContent* aContent) { @@ -391,7 +399,7 @@ nsIdentifierMapEntry::RemoveIdContent(nsIContent* aContent) // XXXbz should this ever Compact() I guess when all the content is gone // we'll just get cleaned up in the natural order of things... return mIdContentList.RemoveElement(aContent) && - mIdContentList.Count() == 0; + mIdContentList.Count() == 0 && !mNameContentList; } void diff --git a/content/base/src/nsDocument.h b/content/base/src/nsDocument.h index f482f56756e5..87b562169e8a 100644 --- a/content/base/src/nsDocument.h +++ b/content/base/src/nsDocument.h @@ -256,7 +256,11 @@ public: * if we know for sure the element is not in the document. */ nsIContent* GetIdContent(PRBool* aIsNotInDocument = nsnull); + void AppendAllIdContent(nsCOMArray* aElements); PRBool AddIdContent(nsIContent* aContent); + /** + * @return true if this map entry should be removed + */ PRBool RemoveIdContent(nsIContent* aContent); void FlagIDNotInDocument(); @@ -888,7 +892,9 @@ protected: // live if we've had over 63 misses return (mIdMissCount & 0x40) != 0; } - + void SetIdTableLive() { + mIdMissCount = 0x40; + } PRBool IdTableShouldBecomeLive() { NS_ASSERTION(!IdTableIsLive(), "Shouldn't be called if table is already live!"); diff --git a/content/xul/document/public/nsIXULDocument.h b/content/xul/document/public/nsIXULDocument.h index dc8bd574fd06..bcc30d03a723 100644 --- a/content/xul/document/public/nsIXULDocument.h +++ b/content/xul/document/public/nsIXULDocument.h @@ -47,10 +47,10 @@ class nsIContent; class nsIScriptGlobalObjectOwner; -// {57314526-f749-4cf0-b6b6-3723eba21480} +// {AF676EDD-1FB9-4C75-9B1F-CB4E02E1C779} #define NS_IXULDOCUMENT_IID \ -{ 0x57314526, 0xf749, 0x4cf0, \ - { 0xb6, 0xb6, 0x37, 0x23, 0xeb, 0xa2, 0x14, 0x80 } } +{ 0xaf676edd, 0x1fb9, 0x4c75, \ + { 0x9b, 0x1f, 0xcb, 0x4e, 0x02, 0xe1, 0xc7, 0x79 } } /* @@ -69,16 +69,11 @@ public: /** * Add an entry to the ID-to-element map. */ - NS_IMETHOD AddElementForID(const nsAString& aID, nsIContent* aElement) = 0; + NS_IMETHOD AddElementForID(nsIContent* aElement) = 0; /** - * Remove an entry from the ID-to-element map. - */ - NS_IMETHOD RemoveElementForID(const nsAString& aID, nsIContent* aElement) = 0; - - /** - * Get the elements for a particular resource in the resource-to-element - * map. The nsCOMArray will be truncated and filled in with + * Get the elements for a particular resource --- all elements whose 'id' + * or 'ref' is aID. The nsCOMArray will be truncated and filled in with * nsIContent pointers. */ NS_IMETHOD GetElementsForID(const nsAString& aID, nsCOMArray& aElements) = 0; diff --git a/content/xul/document/src/Makefile.in b/content/xul/document/src/Makefile.in index 67e320b25585..73181f71ba24 100644 --- a/content/xul/document/src/Makefile.in +++ b/content/xul/document/src/Makefile.in @@ -77,7 +77,6 @@ CPPSRCS = nsXULControllers.cpp ifdef MOZ_XUL CPPSRCS += \ - nsElementMap.cpp \ nsXULCommandDispatcher.cpp \ nsXULContentSink.cpp \ nsXULDocument.cpp \ diff --git a/content/xul/document/src/nsXULDocument.cpp b/content/xul/document/src/nsXULDocument.cpp index b79d94b90db5..ebbf05dd182b 100644 --- a/content/xul/document/src/nsXULDocument.cpp +++ b/content/xul/document/src/nsXULDocument.cpp @@ -56,10 +56,6 @@ document observer methods will never be called because we'll be adding the XUL nodes into the content model "quietly". - 2. The "element map" maps an RDF resource to the elements whose 'id' - or 'ref' attributes refer to that resource. We re-use the element - map to support the HTML-like 'getElementById()' method. - */ // Note the ALPHABETICAL ORDERING @@ -185,6 +181,35 @@ struct BroadcastListener { nsCOMPtr mAttribute; }; +nsIContent* +nsRefMapEntry::GetFirstContent() +{ + return static_cast(mRefContentList.SafeElementAt(0)); +} + +void +nsRefMapEntry::AppendAll(nsCOMArray* aElements) +{ + for (PRInt32 i = 0; i < mRefContentList.Count(); ++i) { + aElements->AppendObject(static_cast(mRefContentList[i])); + } +} + +PRBool +nsRefMapEntry::AddContent(nsIContent* aContent) +{ + if (mRefContentList.IndexOf(aContent) >= 0) + return PR_TRUE; + return mRefContentList.AppendElement(aContent); +} + +PRBool +nsRefMapEntry::RemoveContent(nsIContent* aContent) +{ + mRefContentList.RemoveElement(aContent); + return mRefContentList.Count() == 0; +} + //---------------------------------------------------------------------- // // ctors & dtors @@ -290,17 +315,6 @@ NS_NewXULDocument(nsIXULDocument** result) NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULDocument) -static PRIntn -TraverseElement(const PRUnichar* aID, nsIContent* aElement, void* aContext) -{ - nsCycleCollectionTraversalCallback *cb = - static_cast(aContext); - - cb->NoteXPCOMChild(aElement); - - return HT_ENUMERATE_NEXT; -} - static PLDHashOperator PR_CALLBACK TraverseTemplateBuilders(nsISupports* aKey, nsIXULTemplateBuilder* aData, void* aContext) @@ -329,8 +343,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXULDocument, nsXMLDocument) // XXX tmp->mForwardReferences? // XXX tmp->mContextStack? - tmp->mElementMap.Enumerate(TraverseElement, &cb); - // An element will only have a template builder as long as it's in the // document, so we'll traverse the table here instead of from the element. if (tmp->mTemplateBuilderTable) @@ -917,6 +929,23 @@ nsXULDocument::ExecuteOnBroadcastHandlerFor(nsIContent* aBroadcaster, return NS_OK; } +void +nsXULDocument::AttributeWillChange(nsIContent* aContent, PRInt32 aNameSpaceID, + nsIAtom* aAttribute) +{ + NS_ABORT_IF_FALSE(aContent, "Null content!"); + NS_PRECONDITION(aAttribute, "Must have an attribute that's changing!"); + + // XXXbz check aNameSpaceID, dammit! + // See if we need to update our ref map. + if (aAttribute == nsGkAtoms::ref || + (aAttribute == nsGkAtoms::id && !aContent->GetIDAttributeName())) { + RemoveElementFromRefMap(aContent); + } + + nsXMLDocument::AttributeWillChange(aContent, aNameSpaceID, aAttribute); +} + void nsXULDocument::AttributeChanged(nsIDocument* aDocument, nsIContent* aElement, PRInt32 aNameSpaceID, @@ -925,20 +954,18 @@ nsXULDocument::AttributeChanged(nsIDocument* aDocument, { NS_ASSERTION(aDocument == this, "unexpected doc"); - nsresult rv; + // Do this here so that all the exit paths below don't leave this undone + nsXMLDocument::AttributeChanged(aDocument, aElement, aNameSpaceID, + aAttribute, aModType, aStateMask); // XXXbz check aNameSpaceID, dammit! - // First see if we need to update our element map. - if ((aAttribute == nsGkAtoms::id) || (aAttribute == nsGkAtoms::ref)) { - - rv = mElementMap.Enumerate(RemoveElementsFromMapByContent, aElement); - if (NS_FAILED(rv)) return; - - // That'll have removed _both_ the 'ref' and 'id' entries from - // the map. So add 'em back now. - rv = AddElementToMap(aElement); - if (NS_FAILED(rv)) return; + // See if we need to update our ref map. + if (aAttribute == nsGkAtoms::ref || + (aAttribute == nsGkAtoms::id && !aElement->GetIDAttributeName())) { + AddElementToRefMap(aElement); } + + nsresult rv; // Synchronize broadcast listeners if (mBroadcasterMap && CanBroadcast(aNameSpaceID, aAttribute)) { @@ -1013,7 +1040,7 @@ nsXULDocument::ContentAppended(nsIDocument* aDocument, PRInt32 aNewIndexInContainer) { NS_ASSERTION(aDocument == this, "unexpected doc"); - + // Update our element map PRUint32 count = aContainer->GetChildCount(); @@ -1022,6 +1049,8 @@ nsXULDocument::ContentAppended(nsIDocument* aDocument, ++i) { rv = AddSubtreeToDocument(aContainer->GetChildAt(i)); } + + nsXMLDocument::ContentAppended(aDocument, aContainer, aNewIndexInContainer); } void @@ -1033,6 +1062,8 @@ nsXULDocument::ContentInserted(nsIDocument* aDocument, NS_ASSERTION(aDocument == this, "unexpected doc"); AddSubtreeToDocument(aChild); + + nsXMLDocument::ContentInserted(aDocument, aContainer, aChild, aIndexInContainer); } void @@ -1044,6 +1075,8 @@ nsXULDocument::ContentRemoved(nsIDocument* aDocument, NS_ASSERTION(aDocument == this, "unexpected doc"); RemoveSubtreeFromDocument(aChild); + + nsXMLDocument::ContentRemoved(aDocument, aContainer, aChild, aIndexInContainer); } //---------------------------------------------------------------------- @@ -1052,25 +1085,13 @@ nsXULDocument::ContentRemoved(nsIDocument* aDocument, // NS_IMETHODIMP -nsXULDocument::AddElementForID(const nsAString& aID, nsIContent* aElement) +nsXULDocument::AddElementForID(nsIContent* aElement) { NS_PRECONDITION(aElement != nsnull, "null ptr"); if (! aElement) return NS_ERROR_NULL_POINTER; - mElementMap.Add(aID, aElement); - return NS_OK; -} - - -NS_IMETHODIMP -nsXULDocument::RemoveElementForID(const nsAString& aID, nsIContent* aElement) -{ - NS_PRECONDITION(aElement != nsnull, "null ptr"); - if (! aElement) - return NS_ERROR_NULL_POINTER; - - mElementMap.Remove(aID, aElement); + UpdateIdTableEntry(aElement); return NS_OK; } @@ -1078,7 +1099,19 @@ NS_IMETHODIMP nsXULDocument::GetElementsForID(const nsAString& aID, nsCOMArray& aElements) { - mElementMap.Find(aID, aElements); + aElements.Clear(); + + nsCOMPtr atom = do_GetAtom(aID); + if (!atom) + return NS_ERROR_OUT_OF_MEMORY; + nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(atom); + if (entry) { + entry->AppendAllIdContent(&aElements); + } + nsRefMapEntry *refEntry = mRefMap.GetEntry(atom); + if (refEntry) { + refEntry->AppendAll(&aElements); + } return NS_OK; } @@ -1557,17 +1590,22 @@ nsXULDocument::GetElementById(const nsAString& aId, if (!CheckGetElementByIdArg(aId)) return NS_OK; - nsresult rv; - - nsCOMPtr element; - rv = mElementMap.FindFirst(aId, getter_AddRefs(element)); - if (NS_FAILED(rv)) return rv; - - if (element) { - rv = CallQueryInterface(element, aReturn); + nsCOMPtr atom = do_GetAtom(aId); + if (!atom) + return NS_ERROR_OUT_OF_MEMORY; + nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(atom); + if (entry) { + nsIContent* content = entry->GetIdContent(); + if (content) + return CallQueryInterface(content, aReturn); } - - return rv; + nsRefMapEntry* refEntry = mRefMap.GetEntry(atom); + if (refEntry) { + NS_ASSERTION(refEntry->GetFirstContent(), + "nsRefMapEntries should have nonempty content lists"); + return CallQueryInterface(refEntry->GetFirstContent(), aReturn); + } + return NS_OK; } nsresult @@ -1577,8 +1615,11 @@ nsXULDocument::AddElementToDocumentPre(nsIContent* aElement) // to the XUL Document. nsresult rv; - // 1. Add the element to the resource-to-element map - rv = AddElementToMap(aElement); + // 1. Add the element to the resource-to-element map. Also add it to + // the id map, since it seems this can be called when creating + // elements from prototypes. + UpdateIdTableEntry(aElement); + rv = AddElementToRefMap(aElement); if (NS_FAILED(rv)) return rv; // 2. If the element is a 'command updater' (i.e., has a @@ -1699,8 +1740,7 @@ nsXULDocument::RemoveSubtreeFromDocument(nsIContent* aElement) } // 2. Remove the element from the resource-to-element map - rv = RemoveElementFromMap(aElement); - if (NS_FAILED(rv)) return rv; + RemoveElementFromRefMap(aElement); // 3. If the element is a 'command updater', then remove the // element from the document's command dispatcher. @@ -1763,65 +1803,55 @@ nsXULDocument::GetTemplateBuilderFor(nsIContent* aContent, return NS_OK; } -// Attributes that are used with getElementById() and the -// resource-to-element map. -nsIAtom** nsXULDocument::kIdentityAttrs[] = +static void +GetRefMapAttribute(nsIContent* aElement, nsAutoString* aValue) { - &nsGkAtoms::id, - &nsGkAtoms::ref, - nsnull -}; + aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::ref, *aValue); + if (aValue->IsEmpty() && !aElement->GetIDAttributeName()) { + aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::id, *aValue); + } +} nsresult -nsXULDocument::AddElementToMap(nsIContent* aElement) +nsXULDocument::AddElementToRefMap(nsIContent* aElement) { - // Look at the element's 'id' and 'ref' attributes, and if set, - // add pointers in the resource-to-element map to the element. - nsresult rv; - - for (PRInt32 i = 0; kIdentityAttrs[i] != nsnull; ++i) { - nsAutoString value; - aElement->GetAttr(kNameSpaceID_None, *kIdentityAttrs[i], value); - if (!value.IsEmpty()) { - rv = mElementMap.Add(value, aElement); - if (NS_FAILED(rv)) return rv; - } + // Look at the element's 'ref' attribute, and if set, + // add an entry in the resource-to-element map to the element. + nsAutoString value; + GetRefMapAttribute(aElement, &value); + if (!value.IsEmpty()) { + nsCOMPtr atom = do_GetAtom(value); + if (!atom) + return NS_ERROR_OUT_OF_MEMORY; + nsRefMapEntry *entry = mRefMap.PutEntry(atom); + if (!entry) + return NS_ERROR_OUT_OF_MEMORY; + if (!entry->AddContent(aElement)) + return NS_ERROR_OUT_OF_MEMORY; } return NS_OK; } - -nsresult -nsXULDocument::RemoveElementFromMap(nsIContent* aElement) +void +nsXULDocument::RemoveElementFromRefMap(nsIContent* aElement) { // Remove the element from the resource-to-element map. - nsresult rv; - - for (PRInt32 i = 0; kIdentityAttrs[i] != nsnull; ++i) { - nsAutoString value; - aElement->GetAttr(kNameSpaceID_None, *kIdentityAttrs[i], value); - if (!value.IsEmpty()) { - rv = mElementMap.Remove(value, aElement); - if (NS_FAILED(rv)) return rv; + nsAutoString value; + GetRefMapAttribute(aElement, &value); + if (!value.IsEmpty()) { + nsCOMPtr atom = do_GetAtom(value); + if (!atom) + return; + nsRefMapEntry *entry = mRefMap.GetEntry(atom); + if (!entry) + return; + if (entry->RemoveContent(aElement)) { + mRefMap.RemoveEntry(atom); } } - - return NS_OK; } - -PRIntn -nsXULDocument::RemoveElementsFromMapByContent(const PRUnichar* aID, - nsIContent* aElement, - void* aClosure) -{ - nsIContent* content = reinterpret_cast(aClosure); - return (aElement == content) ? HT_ENUMERATE_REMOVE : HT_ENUMERATE_NEXT; -} - - - //---------------------------------------------------------------------- // // nsIDOMNode interface @@ -1844,6 +1874,9 @@ nsXULDocument::CloneNode(PRBool aDeep, nsIDOMNode** aReturn) nsresult nsXULDocument::Init() { + SetIdTableLive(); + mRefMap.Init(); + nsresult rv = nsXMLDocument::Init(); NS_ENSURE_SUCCESS(rv, rv); @@ -2369,7 +2402,8 @@ nsXULDocument::PrepareToWalk() if (NS_FAILED(rv)) return rv; // Add the root element to the XUL document's ID-to-element map. - rv = AddElementToMap(root); + UpdateIdTableEntry(root); + rv = AddElementToRefMap(root); if (NS_FAILED(rv)) return rv; // Block onload until we've finished building the complete diff --git a/content/xul/document/src/nsXULDocument.h b/content/xul/document/src/nsXULDocument.h index e972e3227e60..c7df312c728e 100644 --- a/content/xul/document/src/nsXULDocument.h +++ b/content/xul/document/src/nsXULDocument.h @@ -46,7 +46,6 @@ #include "nsTArray.h" #include "nsXMLDocument.h" -#include "nsElementMap.h" #include "nsForwardReference.h" #include "nsIContent.h" #include "nsIDOMEventTarget.h" @@ -78,6 +77,35 @@ class nsIXULPrototypeScript; struct JSObject; struct PRLogModuleInfo; +class nsRefMapEntry : public nsISupportsHashKey +{ +public: + nsRefMapEntry(const nsISupports* aKey) : + nsISupportsHashKey(aKey) + { + } + nsRefMapEntry(const nsRefMapEntry& aOther) : + nsISupportsHashKey(GetKey()) + { + NS_ERROR("Should never be called"); + } + + nsIContent* GetFirstContent(); + void AppendAll(nsCOMArray* aElements); + /** + * @return true if aContent was added, false if we failed due to OOM + */ + PRBool AddContent(nsIContent* aContent); + /** + * @return true if aContent was removed and it was the last content for + * this ref, so this entry should be removed from the map + */ + PRBool RemoveContent(nsIContent* aContent); + +private: + nsSmallVoidArray mRefContentList; +}; + /** * The XUL document class */ @@ -118,9 +146,12 @@ public: NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED + virtual void AttributeWillChange(nsIContent* aChild, + PRInt32 aNameSpaceID, + nsIAtom* aAttribute); + // nsIXULDocument interface - NS_IMETHOD AddElementForID(const nsAString& aID, nsIContent* aElement); - NS_IMETHOD RemoveElementForID(const nsAString& aID, nsIContent* aElement); + NS_IMETHOD AddElementForID(nsIContent* aElement); NS_IMETHOD GetElementsForID(const nsAString& aID, nsCOMArray& aElements); @@ -170,18 +201,12 @@ protected: nsresult StartLayout(void); nsresult - AddElementToMap(nsIContent* aElement); - - nsresult - RemoveElementFromMap(nsIContent* aElement); + AddElementToRefMap(nsIContent* aElement); + void + RemoveElementFromRefMap(nsIContent* aElement); nsresult GetViewportSize(PRInt32* aWidth, PRInt32* aHeight); - static PRIntn - RemoveElementsFromMapByContent(const PRUnichar* aID, - nsIContent* aElement, - void* aClosure); - void SetIsPopup(PRBool isPopup) { mIsPopup = isPopup; } nsresult PrepareToLoad(nsISupports* aContainer, @@ -250,7 +275,9 @@ protected: nsXULDocument* mNextSrcLoadWaiter; // [OWNER] but not COMPtr - nsElementMap mElementMap; + // Tracks elements with a 'ref' attribute, or an 'id' attribute where + // the element's namespace has no registered ID attribute name. + nsTHashtable mRefMap; nsCOMPtr mLocalStore; PRPackedBool mIsPopup; PRPackedBool mApplyingPersistedAttrs; diff --git a/content/xul/document/test/test_bug311681.xul b/content/xul/document/test/test_bug311681.xul index b1a3ed1e4abe..dc03e16b8601 100644 --- a/content/xul/document/test/test_bug311681.xul +++ b/content/xul/document/test/test_bug311681.xul @@ -47,15 +47,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=311681 newParent.appendChild(node); // Check what getElementById returns, no flushing - todo(getCont() == node, "Should be getting new node pre-flush 1") - is(getCont(), testNode, "XUL does it differently for now"); + is(getCont(), node, "Should be getting new node pre-flush 1") // Trigger a layout flush, just in case. var itemHeight = newParent.offsetHeight/10; // Check what getElementById returns now. - todo(getCont() == node, "Should be getting new node post-flush 1") - is(getCont(), testNode, "XUL does it differently for now"); + is(getCont(), node, "Should be getting new node post-flush 1") clear(newParent); diff --git a/content/xul/document/test/test_bug403868.xul b/content/xul/document/test/test_bug403868.xul index 2579fecb8f95..ad27ea9e1959 100644 --- a/content/xul/document/test/test_bug403868.xul +++ b/content/xul/document/test/test_bug403868.xul @@ -40,19 +40,16 @@ is(document.getElementById("test1"), s1a, "Inserting span with id=test1 not at the beginning; doesn't matter"); var s4a = createSpan("test1", s1a); -todo(document.getElementById("test1") == s4a, +is(document.getElementById("test1"), s4a, "Inserting span with id=test1 at the beginning changes which one is first"); -is(document.getElementById("test1"), s1a, "XUL is confused") s4a.parentNode.removeChild(s4a); is(document.getElementById("test1"), s1a, "First-created span with id=test1 is first again"); s1a.parentNode.removeChild(s1a); -todo(document.getElementById("test1") == s3a, +is(document.getElementById("test1"), s3a, "Third-created span with id=test1 is first now"); -is(document.getElementById("test1"), s2a, - "XUL is confused"); // Start the id hashtable for (var i = 0; i < 256; ++i) { @@ -72,19 +69,16 @@ is(document.getElementById("test2"), s1b, "Inserting span with id=test2 not at the beginning; doesn't matter"); var s4b = createSpan("test2", s1b); -todo(document.getElementById("test2") == s4b, +is(document.getElementById("test2"), s4b, "Inserting span with id=test2 at the beginning changes which one is first"); -is(document.getElementById("test2"), s1b, "XUL is confused") s4b.parentNode.removeChild(s4b); is(document.getElementById("test2"), s1b, "First-created span with id=test2 is first again"); s1b.parentNode.removeChild(s1b); -todo(document.getElementById("test2") == s3b, +is(document.getElementById("test2"), s3b, "Third-created span with id=test2 is first now"); -is(document.getElementById("test2"), s2b, - "XUL is confused"); ]]> diff --git a/content/xul/templates/src/nsXULContentBuilder.cpp b/content/xul/templates/src/nsXULContentBuilder.cpp index 4434b60e6743..f7984b9fd455 100644 --- a/content/xul/templates/src/nsXULContentBuilder.cpp +++ b/content/xul/templates/src/nsXULContentBuilder.cpp @@ -737,7 +737,7 @@ nsXULContentBuilder::BuildContentFromTemplate(nsIContent *aTemplateNode, nsCOMPtr xuldoc = do_QueryInterface(mRoot->GetDocument()); if (xuldoc) - xuldoc->AddElementForID(id, realKid); + xuldoc->AddElementForID(realKid); } // Set up the element's 'container' and 'empty' attributes. From cc0cfcf8e7ac404b5ecfa4350103e066e8b65c68 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Mon, 23 Jun 2008 14:41:21 +1200 Subject: [PATCH 57/66] Mark reftest as passing --- layout/reftests/svg/reftest.list | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/layout/reftests/svg/reftest.list b/layout/reftests/svg/reftest.list index bdb9806a6bfa..bf355fa0a8fa 100755 --- a/layout/reftests/svg/reftest.list +++ b/layout/reftests/svg/reftest.list @@ -60,7 +60,7 @@ random-if(MOZ_WIDGET_TOOLKIT=="cocoa") == opacity-and-gradient-01.svg pass.svg == rect-with-rx-or-ry-01.svg rect-with-rx-or-ry-01-ref.svg == rootElement-null-01.svg pass.svg == stroke-width-percentage-01.svg pass.svg -fails == style-property-not-on-script-element-01.svg pass.svg +== style-property-not-on-script-element-01.svg pass.svg == style-without-type-attribute.svg pass.svg == svg-in-foreignObject-01.xhtml svg-in-foreignObject-01-ref.xhtml == svg-in-foreignObject-02.xhtml svg-in-foreignObject-01-ref.xhtml # reuse -01-ref.xhtml From b13dd43ee0274b680dcfe85dc8127d79aa233c2a Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Mon, 23 Jun 2008 17:16:18 +1200 Subject: [PATCH 58/66] Removing nsElementMap --- content/xul/document/src/nsElementMap.cpp | 431 ---------------------- content/xul/document/src/nsElementMap.h | 153 -------- 2 files changed, 584 deletions(-) delete mode 100644 content/xul/document/src/nsElementMap.cpp delete mode 100644 content/xul/document/src/nsElementMap.h diff --git a/content/xul/document/src/nsElementMap.cpp b/content/xul/document/src/nsElementMap.cpp deleted file mode 100644 index 108d7f5533e0..000000000000 --- a/content/xul/document/src/nsElementMap.cpp +++ /dev/null @@ -1,431 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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 the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Chris Waterson - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - - Maps IDs to elements. - - - To turn on logging for this module, set: - - NS_PR_LOG_MODULES nsElementMap:5 - - */ - -#include "nsCOMPtr.h" -#include "nsCRT.h" -#include "nsElementMap.h" -#include "nsString.h" -#include "nsIAtom.h" -#include "nsReadableUtils.h" -#include "prlog.h" -#include "prbit.h" - -#ifdef PR_LOGGING -static PRLogModuleInfo* gMapLog; -#endif - -static void* PR_CALLBACK AllocTable(void* aPool, PRSize aSize) -{ - return new char[aSize]; -} - -static void PR_CALLBACK FreeTable(void* aPool, void* aItem) -{ - delete[] static_cast(aItem); -} - -static PLHashEntry* PR_CALLBACK AllocEntry(void* aPool, const void* aKey) -{ - nsFixedSizeAllocator* pool = static_cast(aPool); - PLHashEntry* entry = static_cast(pool->Alloc(sizeof(PLHashEntry))); - return entry; -} - -static void PR_CALLBACK FreeEntry(void* aPool, PLHashEntry* aEntry, PRUintn aFlag) -{ - nsFixedSizeAllocator* pool = static_cast(aPool); - if (aFlag == HT_FREE_ENTRY) - pool->Free(aEntry, sizeof(PLHashEntry)); -} - -PLHashAllocOps nsElementMap::gAllocOps = { - AllocTable, FreeTable, AllocEntry, FreeEntry }; - - -nsElementMap::nsElementMap() -{ - MOZ_COUNT_CTOR(nsElementMap); - - // Create a table for mapping IDs to elements in the content tree. - static const size_t kBucketSizes[] = { - sizeof(PLHashEntry), sizeof(ContentListItem) - }; - - static const PRInt32 kNumBuckets = sizeof(kBucketSizes) / sizeof(size_t); - - static const PRInt32 kInitialNumElements = 64; - - // Per news://news.mozilla.org/39BEC105.5090206%40netscape.com - static const PRInt32 kInitialPoolSize = 512; - - mPool.Init("nsElementMap", kBucketSizes, kNumBuckets, kInitialPoolSize); - - mMap = PL_NewHashTable(kInitialNumElements, - Hash, - Compare, - PL_CompareValues, - &gAllocOps, - &mPool); - - NS_ASSERTION(mMap != nsnull, "could not create hash table for resources"); - -#ifdef PR_LOGGING - if (! gMapLog) - gMapLog = PR_NewLogModule("nsElementMap"); - - - PR_LOG(gMapLog, PR_LOG_NOTICE, - ("xulelemap(%p) created", this)); -#endif -} - -nsElementMap::~nsElementMap() -{ - MOZ_COUNT_DTOR(nsElementMap); - - if (mMap) { - PL_HashTableEnumerateEntries(mMap, ReleaseContentList, this); - PL_HashTableDestroy(mMap); - } - - PR_LOG(gMapLog, PR_LOG_NOTICE, - ("xulelemap(%p) destroyed", this)); -} - - -PRIntn -nsElementMap::ReleaseContentList(PLHashEntry* aHashEntry, PRIntn aIndex, void* aClosure) -{ - nsElementMap* self = static_cast(aClosure); - - PRUnichar* id = - reinterpret_cast(const_cast(aHashEntry->key)); - - nsMemory::Free(id); - - ContentListItem* head = - reinterpret_cast(aHashEntry->value); - - while (head) { - ContentListItem* doomed = head; - head = head->mNext; - ContentListItem::Destroy(self->mPool, doomed); - } - - return HT_ENUMERATE_NEXT; -} - - -nsresult -nsElementMap::Add(const nsAString& aID, nsIContent* aContent) -{ - NS_PRECONDITION(mMap != nsnull, "not initialized"); - if (! mMap) - return NS_ERROR_NOT_INITIALIZED; - - const nsPromiseFlatString& flatID = PromiseFlatString(aID); - const PRUnichar *id = flatID.get(); - - ContentListItem* head = - static_cast(PL_HashTableLookup(mMap, id)); - - if (! head) { - head = ContentListItem::Create(mPool, aContent); - if (! head) - return NS_ERROR_OUT_OF_MEMORY; - - PRUnichar* key = ToNewUnicode(aID); - if (! key) - return NS_ERROR_OUT_OF_MEMORY; - - PL_HashTableAdd(mMap, key, head); - } - else { - while (1) { - if (head->mContent.get() == aContent) { - // This can happen if an element that was created via - // frame construction code is then "appended" to the - // content model with aNotify == PR_TRUE. If you see - // this warning, it's an indication that you're - // unnecessarily notifying the frame system, and - // potentially causing unnecessary reflow. - //NS_ERROR("element was already in the map"); -#ifdef PR_LOGGING - if (PR_LOG_TEST(gMapLog, PR_LOG_NOTICE)) { - const char *tagname; - aContent->Tag()->GetUTF8String(&tagname); - - nsCAutoString aidC; - aidC.AssignWithConversion(id, aID.Length()); - PR_LOG(gMapLog, PR_LOG_NOTICE, - ("xulelemap(%p) dup %s[%p] <-- %s\n", - this, - tagname, - aContent, - aidC.get())); - } -#endif - - return NS_OK; - } - if (! head->mNext) - break; - - head = head->mNext; - } - - head->mNext = nsElementMap::ContentListItem::Create(mPool, aContent); - if (! head->mNext) - return NS_ERROR_OUT_OF_MEMORY; - } - -#ifdef PR_LOGGING - if (PR_LOG_TEST(gMapLog, PR_LOG_NOTICE)) { - const char *tagname; - aContent->Tag()->GetUTF8String(&tagname); - - nsCAutoString aidC; - aidC.AssignWithConversion(id, aID.Length()); - PR_LOG(gMapLog, PR_LOG_NOTICE, - ("xulelemap(%p) add %s[%p] <-- %s\n", - this, - tagname, - aContent, - aidC.get())); - } -#endif - - return NS_OK; -} - - -nsresult -nsElementMap::Remove(const nsAString& aID, nsIContent* aContent) -{ - NS_PRECONDITION(mMap != nsnull, "not initialized"); - if (! mMap) - return NS_ERROR_NOT_INITIALIZED; - - const nsPromiseFlatString& flatID = PromiseFlatString(aID); - const PRUnichar *id = flatID.get(); - -#ifdef PR_LOGGING - if (PR_LOG_TEST(gMapLog, PR_LOG_NOTICE)) { - const char *tagname; - aContent->Tag()->GetUTF8String(&tagname); - - nsCAutoString aidC; - aidC.AssignWithConversion(id); - PR_LOG(gMapLog, PR_LOG_NOTICE, - ("xulelemap(%p) remove %s[%p] <-- %s\n", - this, - tagname, - aContent, - aidC.get())); - } -#endif - - PLHashEntry** hep = PL_HashTableRawLookup(mMap, - Hash(id), - id); - - // XXX Don't comment out this assert: if you get here, something - // has gone dreadfully, horribly wrong. Curse. Scream. File a bug - // against waterson@netscape.com. - NS_ASSERTION(hep != nsnull && *hep != nsnull, "attempt to remove an element that was never added"); - if (!hep || !*hep) - return NS_OK; - - ContentListItem* head = reinterpret_cast((*hep)->value); - - if (head->mContent.get() == aContent) { - ContentListItem* next = head->mNext; - if (next) { - (*hep)->value = next; - } - else { - // It was the last reference in the table - PRUnichar* key = reinterpret_cast(const_cast((*hep)->key)); - PL_HashTableRawRemove(mMap, hep, *hep); - nsMemory::Free(key); - } - ContentListItem::Destroy(mPool, head); - } - else { - ContentListItem* item = head->mNext; - while (item) { - if (item->mContent.get() == aContent) { - head->mNext = item->mNext; - ContentListItem::Destroy(mPool, item); - break; - } - head = item; - item = item->mNext; - } - } - - return NS_OK; -} - - - -nsresult -nsElementMap::Find(const nsAString& aID, nsCOMArray& aResults) -{ - NS_PRECONDITION(mMap != nsnull, "not initialized"); - if (! mMap) - return NS_ERROR_NOT_INITIALIZED; - - aResults.Clear(); - ContentListItem* item = - reinterpret_cast(PL_HashTableLookup(mMap, (const PRUnichar *)PromiseFlatString(aID).get())); - - while (item) { - aResults.AppendObject(item->mContent); - item = item->mNext; - } - return NS_OK; -} - - -nsresult -nsElementMap::FindFirst(const nsAString& aID, nsIContent** aResult) -{ - NS_PRECONDITION(mMap != nsnull, "not initialized"); - if (! mMap) - return NS_ERROR_NOT_INITIALIZED; - - ContentListItem* item = - reinterpret_cast(PL_HashTableLookup(mMap, (const PRUnichar *)PromiseFlatString(aID).get())); - - if (item) { - *aResult = item->mContent; - NS_ADDREF(*aResult); - } - else { - *aResult = nsnull; - } - - return NS_OK; -} - -nsresult -nsElementMap::Enumerate(nsElementMapEnumerator aEnumerator, void* aClosure) -{ - EnumerateClosure closure = { this, aEnumerator, aClosure }; - PL_HashTableEnumerateEntries(mMap, EnumerateImpl, &closure); - return NS_OK; -} - - -PRIntn -nsElementMap::EnumerateImpl(PLHashEntry* aHashEntry, PRIntn aIndex, void* aClosure) -{ - // This routine will be called once for each key in the - // hashtable. It will in turn call the enumerator that the user - // has passed in via Enumerate() once for each element that's been - // mapped to this ID. - EnumerateClosure* closure = reinterpret_cast(aClosure); - - const PRUnichar* id = - reinterpret_cast(aHashEntry->key); - - // 'link' holds a pointer to the previous element's link field. - ContentListItem** link = - reinterpret_cast(&aHashEntry->value); - - ContentListItem* item = *link; - - // Iterate through each content node that's been mapped to this ID - while (item) { - ContentListItem* current = item; - item = item->mNext; - PRIntn result = (*closure->mEnumerator)(id, current->mContent, closure->mClosure); - - if (result == HT_ENUMERATE_REMOVE) { - // If the user wants to remove the current, then deal. - *link = item; - ContentListItem::Destroy(closure->mSelf->mPool, current); - - if ((! *link) && (link == reinterpret_cast(&aHashEntry->value))) { - // It's the last content node that was mapped to this - // ID. Unhash it. - PRUnichar* key = const_cast(id); - nsMemory::Free(key); - return HT_ENUMERATE_REMOVE; - } - } - else { - link = ¤t->mNext; - } - } - - return HT_ENUMERATE_NEXT; -} - - -PLHashNumber -nsElementMap::Hash(const void* aKey) -{ - PLHashNumber result = 0; - const PRUnichar* s = reinterpret_cast(aKey); - while (*s != nsnull) { - result = PR_ROTATE_LEFT32(result, 4) ^ *s; - ++s; - } - return result; -} - - -PRIntn -nsElementMap::Compare(const void* aLeft, const void* aRight) -{ - return 0 == nsCRT::strcmp(reinterpret_cast(aLeft), - reinterpret_cast(aRight)); -} diff --git a/content/xul/document/src/nsElementMap.h b/content/xul/document/src/nsElementMap.h deleted file mode 100644 index e3198ad0ed54..000000000000 --- a/content/xul/document/src/nsElementMap.h +++ /dev/null @@ -1,153 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * 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 the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** - * - * - * This Original Code has been modified by IBM Corporation. - * Modifications made by IBM described herein are - * Copyright (c) International Business Machines - * Corporation, 2000 - * - * Modifications to Mozilla code or documentation - * identified per MPL Section 3.3 - * - * Date Modified by Description of modification - * 03/27/2000 IBM Corp. Added PR_CALLBACK for Optlink - * use in OS2 - */ - -/* - - Maintains one-to-many mapping between element IDs and content - nodes. - - */ - -#ifndef nsElementMap_h__ -#define nsElementMap_h__ - -#include "nscore.h" -#include "nsError.h" -#include "plhash.h" -#include "nsIContent.h" -#include "nsFixedSizeAllocator.h" -#include "nsCOMArray.h" - -class nsString; - -class nsElementMap -{ -protected: - PLHashTable* mMap; - nsFixedSizeAllocator mPool; - - static PLHashAllocOps gAllocOps; - - class ContentListItem { - public: - ContentListItem* mNext; - nsCOMPtr mContent; - - static ContentListItem* - Create(nsFixedSizeAllocator& aPool, nsIContent* aContent) { - void* bytes = aPool.Alloc(sizeof(ContentListItem)); - return bytes ? new (bytes) ContentListItem(aContent) : nsnull; } - - static void - Destroy(nsFixedSizeAllocator& aPool, ContentListItem* aItem) { - delete aItem; - aPool.Free(aItem, sizeof(*aItem)); } - - protected: - static void* operator new(size_t aSize, void* aPtr) CPP_THROW_NEW { - return aPtr; } - - static void operator delete(void* aPtr, size_t aSize) { - /* do nothing; memory free()'d in Destroy() */ } - - ContentListItem(nsIContent* aContent) : mNext(nsnull), mContent(aContent) { - MOZ_COUNT_CTOR(nsElementMap::ContentListItem); } - - ~ContentListItem() { - MOZ_COUNT_DTOR(nsElementMap::ContentListItem); } - }; - - static PLHashNumber PR_CALLBACK - Hash(const void* akey); - - static PRIntn PR_CALLBACK - Compare(const void* aLeft, const void* aRight); - - static PRIntn PR_CALLBACK - ReleaseContentList(PLHashEntry* aHashEntry, PRIntn aIndex, void* aClosure); - -public: - nsElementMap(void); - virtual ~nsElementMap(); - - nsresult - Add(const nsAString& aID, nsIContent* aContent); - - nsresult - Remove(const nsAString& aID, nsIContent* aContent); - - nsresult - Find(const nsAString& aID, nsCOMArray& aResults); - - nsresult - FindFirst(const nsAString& aID, nsIContent** aContent); - - typedef PRIntn (*nsElementMapEnumerator)(const PRUnichar* aID, - nsIContent* aElement, - void* aClosure); - - nsresult - Enumerate(nsElementMapEnumerator aEnumerator, void* aClosure); - -private: - struct EnumerateClosure { - nsElementMap* mSelf; - nsElementMapEnumerator mEnumerator; - void* mClosure; - }; - - static PRIntn PR_CALLBACK - EnumerateImpl(PLHashEntry* aHashEntry, PRIntn aIndex, void* aClosure); -}; - - -#endif // nsElementMap_h__ From 1f73fe21bda21c417f1b1aaa6e03e87fa06f7668 Mon Sep 17 00:00:00 2001 From: Olli Pettay Date: Mon, 23 Jun 2008 11:07:06 +0300 Subject: [PATCH 59/66] Bug 438241, Mousover and mouseout don't behave properly with native anonymous content, r=jst,sr=sicking --- content/base/src/nsGenericElement.cpp | 55 +++++++++++++++++++-------- 1 file changed, 39 insertions(+), 16 deletions(-) diff --git a/content/base/src/nsGenericElement.cpp b/content/base/src/nsGenericElement.cpp index d943d12f6dad..e62d619865e6 100644 --- a/content/base/src/nsGenericElement.cpp +++ b/content/base/src/nsGenericElement.cpp @@ -2232,10 +2232,14 @@ nsGenericElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor) } static nsIContent* -FindFirstNonNativeAnonymousAncestor(nsIContent* aContent) +FindNativeAnonymousSubtreeOwner(nsIContent* aContent) { - while (aContent && aContent->IsNativeAnonymous()) { - aContent = aContent->GetParent(); + if (aContent->IsInNativeAnonymousSubtree()) { + PRBool isNativeAnon = PR_FALSE; + while (aContent && !isNativeAnon) { + isNativeAnon = aContent->IsNativeAnonymous(); + aContent = aContent->GetParent(); + } } return aContent; } @@ -2250,8 +2254,11 @@ nsGenericElement::doPreHandleEvent(nsIContent* aContent, // Don't propagate mouseover and mouseout events when mouse is moving // inside native anonymous content. PRBool isAnonForEvents = aContent->IsNativeAnonymous(); - if (aVisitor.mEvent->message == NS_MOUSE_ENTER_SYNTH || - aVisitor.mEvent->message == NS_MOUSE_EXIT_SYNTH) { + if ((aVisitor.mEvent->message == NS_MOUSE_ENTER_SYNTH || + aVisitor.mEvent->message == NS_MOUSE_EXIT_SYNTH) && + // This is an optimization - try to stop event propagation when + // event has just possibly been retargeted. + static_cast(aContent) == aVisitor.mEvent->target) { nsCOMPtr relatedTarget = do_QueryInterface(static_cast (aVisitor.mEvent)->relatedTarget); @@ -2267,17 +2274,33 @@ nsGenericElement::doPreHandleEvent(nsIContent* aContent, (aVisitor.mEvent->originalTarget == aContent && (aVisitor.mRelatedTargetIsInAnon = relatedTarget->IsInNativeAnonymousSubtree()))) { - nsIContent* nonAnon = FindFirstNonNativeAnonymousAncestor(aContent); - if (nonAnon) { - nsIContent* nonAnonRelated = - FindFirstNonNativeAnonymousAncestor(relatedTarget); - if (nonAnonRelated) { - if (nonAnon == nonAnonRelated || - nsContentUtils::ContentIsDescendantOf(nonAnonRelated, nonAnon)) { - aVisitor.mParentTarget = nsnull; - // Event should not propagate to non-anon content. - aVisitor.mCanHandle = isAnonForEvents; - return NS_OK; + nsIContent* anonOwner = FindNativeAnonymousSubtreeOwner(aContent); + if (anonOwner) { + nsIContent* anonOwnerRelated = + FindNativeAnonymousSubtreeOwner(relatedTarget); + if (anonOwnerRelated) { + // Note, anonOwnerRelated may still be inside some other + // native anonymous subtree. The case where anonOwner is still + // inside native anonymous subtree will be handled when event + // propagates up in the DOM tree. + while (anonOwner != anonOwnerRelated && + anonOwnerRelated->IsInNativeAnonymousSubtree()) { + anonOwnerRelated = FindNativeAnonymousSubtreeOwner(anonOwnerRelated); + } + if (anonOwner == anonOwnerRelated) { + nsCOMPtr target = + do_QueryInterface(aVisitor.mEvent->originalTarget); + // Because XBL and native anon content both do event re-targeting, + // static_cast(aContent) == aVisitor.mEvent->target + // optimization may not always work. So be paranoid and make + // sure we never stop event propagation when we shouldn't! + if (relatedTarget->FindFirstNonNativeAnonymous() == + target->FindFirstNonNativeAnonymous()) { + aVisitor.mParentTarget = nsnull; + // Event should not propagate to non-anon content. + aVisitor.mCanHandle = isAnonForEvents; + return NS_OK; + } } } } From 95215d2e79971057a16b27e371d75d14816bb0c9 Mon Sep 17 00:00:00 2001 From: Michael Ventnor Date: Mon, 23 Jun 2008 11:30:07 +0300 Subject: [PATCH 60/66] Bug 440112, Form elements are not hidden behind overlapping parent with overflow:hidden, r+sr=roc --- layout/reftests/bugs/440112-ref.html | 21 +++++++++++++++++++++ layout/reftests/bugs/440112.html | 20 ++++++++++++++++++++ layout/reftests/bugs/reftest.list | 1 + widget/src/gtk2/gtk2drawing.c | 2 +- 4 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 layout/reftests/bugs/440112-ref.html create mode 100644 layout/reftests/bugs/440112.html diff --git a/layout/reftests/bugs/440112-ref.html b/layout/reftests/bugs/440112-ref.html new file mode 100644 index 000000000000..b5a12d63d330 --- /dev/null +++ b/layout/reftests/bugs/440112-ref.html @@ -0,0 +1,21 @@ + + + + + +Bug 440112 + + + +
+
+ + +
+
+
+ + + + diff --git a/layout/reftests/bugs/440112.html b/layout/reftests/bugs/440112.html new file mode 100644 index 000000000000..cb102f681d0e --- /dev/null +++ b/layout/reftests/bugs/440112.html @@ -0,0 +1,20 @@ + + + + + +Bug 440112 + + + +
+
+ + +
+
+ + + + diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index 22221a97fd41..b22809b2cd1e 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -848,6 +848,7 @@ random == 429849-1.html 429849-1-ref.html # bug 432288 == 430813-1.html 430813-1-ref.html == 430813-2.html 430813-2-ref.html == 430813-3.html 430813-3-ref.html +== 440112.html 440112-ref.html == 433640-1.html 433640-1-ref.html == 438981-1.xhtml about:blank == 439004-1.html 439004-1-ref.html diff --git a/widget/src/gtk2/gtk2drawing.c b/widget/src/gtk2/gtk2drawing.c index de68736ee224..272cffd4c4a6 100644 --- a/widget/src/gtk2/gtk2drawing.c +++ b/widget/src/gtk2/gtk2drawing.c @@ -1475,7 +1475,7 @@ moz_gtk_entry_paint(GdkDrawable* drawable, GdkRectangle* rect, /* Draw the default window background */ gdk_draw_rectangle(drawable, style->base_gc[bg_state], TRUE, - rect->x, rect->y, rect->width, rect->height); + cliprect->x, cliprect->y, cliprect->width, cliprect->height); /* Get the position of the inner window, see _gtk_entry_get_borders */ x = XTHICKNESS(style); From e7c172328a62a7565e6625d50fc3b46bd0a69888 Mon Sep 17 00:00:00 2001 From: Michael Ventnor Date: Mon, 23 Jun 2008 11:36:36 +0300 Subject: [PATCH 61/66] Bug 437937, Embedding: GTK tooltips should have the tooltip hint set, r+sr=roc --- embedding/browser/gtk/src/EmbedWindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/embedding/browser/gtk/src/EmbedWindow.cpp b/embedding/browser/gtk/src/EmbedWindow.cpp index 1a34756b1eba..c04e49e3070d 100644 --- a/embedding/browser/gtk/src/EmbedWindow.cpp +++ b/embedding/browser/gtk/src/EmbedWindow.cpp @@ -409,6 +409,7 @@ EmbedWindow::OnShowTooltip(PRInt32 aXCoords, PRInt32 aYCoords, gtk_window_set_resizable(GTK_WINDOW(sTipWindow), TRUE); // needed to get colors + fonts etc correctly gtk_widget_set_name(sTipWindow, "gtk-tooltips"); + gtk_window_set_type_hint(GTK_WINDOW(sTipWindow), GDK_WINDOW_TYPE_HINT_TOOLTIP); // set up the popup window as a transient of the widget. GtkWidget *toplevel_window; From c6a1fd787c4b3fa0c90ff5fca8e124a6f75106c2 Mon Sep 17 00:00:00 2001 From: Michael Ventnor Date: Mon, 23 Jun 2008 11:50:52 +0300 Subject: [PATCH 62/66] Bug 118308, NS_THEME_TEXTFIELD_CARET implementation (GTK), r+sr=roc --- layout/base/nsCaret.cpp | 46 +++++++++++++++++++----- layout/base/nsCaret.h | 7 ++-- layout/base/nsDisplayList.cpp | 3 +- layout/base/nsICaret.h | 8 ++--- widget/public/nsILookAndFeel.h | 6 +++- widget/src/gtk2/gtk2drawing.c | 15 ++++++++ widget/src/gtk2/gtkdrawing.h | 2 ++ widget/src/gtk2/nsLookAndFeel.cpp | 10 ++++++ widget/src/gtk2/nsLookAndFeel.h | 1 + widget/src/gtk2/nsNativeThemeGTK.cpp | 5 ++- widget/src/xpwidgets/nsXPLookAndFeel.cpp | 2 ++ 11 files changed, 86 insertions(+), 19 deletions(-) diff --git a/layout/base/nsCaret.cpp b/layout/base/nsCaret.cpp index 11bcecafa7d5..c5624e7202de 100644 --- a/layout/base/nsCaret.cpp +++ b/layout/base/nsCaret.cpp @@ -72,6 +72,7 @@ #include "nsXULPopupManager.h" #include "nsMenuPopupFrame.h" #include "nsTextFragment.h" +#include "nsThemeConstants.h" // The bidi indicator hangs off the caret to one side, to show which // direction the typing is in. It needs to be at least 2x2 to avoid looking like @@ -123,10 +124,14 @@ NS_IMETHODIMP nsCaret::Init(nsIPresShell *inPresShell) // XXX we should just do this nsILookAndFeel consultation every time // we need these values. mCaretWidthCSSPx = 1; + mCaretAspectRatio = 0; if (presContext && (lookAndFeel = presContext->LookAndFeel())) { PRInt32 tempInt; + float tempFloat; if (NS_SUCCEEDED(lookAndFeel->GetMetric(nsILookAndFeel::eMetric_CaretWidth, tempInt))) mCaretWidthCSSPx = (nscoord)tempInt; + if (NS_SUCCEEDED(lookAndFeel->GetMetric(nsILookAndFeel::eMetricFloat_CaretAspectRatio, tempFloat))) + mCaretAspectRatio = tempFloat; if (NS_SUCCEEDED(lookAndFeel->GetMetric(nsILookAndFeel::eMetric_CaretBlinkTime, tempInt))) mBlinkRate = (PRUint32)tempInt; if (NS_SUCCEEDED(lookAndFeel->GetMetric(nsILookAndFeel::eMetric_ShowCaretDuringSelection, tempInt))) @@ -177,10 +182,12 @@ DrawCJKCaret(nsIFrame* aFrame, PRInt32 aOffset) return 0x2e80 <= ch && ch <= 0xd7ff; } -nsCaret::Metrics nsCaret::ComputeMetrics(nsIFrame* aFrame, PRInt32 aOffset) +nsCaret::Metrics nsCaret::ComputeMetrics(nsIFrame* aFrame, PRInt32 aOffset, nscoord aCaretHeight) { // Compute nominal sizes in appunits - nscoord caretWidth = nsPresContext::CSSPixelsToAppUnits(mCaretWidthCSSPx); + nscoord caretWidth = (aCaretHeight * mCaretAspectRatio) + + nsPresContext::CSSPixelsToAppUnits(mCaretWidthCSSPx); + if (DrawCJKCaret(aFrame, aOffset)) { caretWidth += nsPresContext::CSSPixelsToAppUnits(1); } @@ -367,7 +374,7 @@ NS_IMETHODIMP nsCaret::GetCaretCoordinates(EViewCoordinates aRelativeToType, outCoordinates->x = viewOffset.x; outCoordinates->y = viewOffset.y; outCoordinates->height = theFrame->GetSize().height; - outCoordinates->width = ComputeMetrics(theFrame, theFrameOffset).mCaretWidth; + outCoordinates->width = ComputeMetrics(theFrame, theFrameOffset, outCoordinates->height).mCaretWidth; return NS_OK; } @@ -473,13 +480,36 @@ void nsCaret::UpdateCaretPosition() void nsCaret::PaintCaret(nsDisplayListBuilder *aBuilder, nsIRenderingContext *aCtx, - const nsPoint &aOffset, - nscolor aColor) + nsIFrame* aForFrame, + const nsPoint &aOffset) { NS_ASSERTION(mDrawn, "The caret shouldn't be drawing"); - aCtx->SetColor(aColor); - aCtx->FillRect(mCaretRect + aOffset); + const nsRect drawCaretRect = mCaretRect + aOffset; + nscolor cssColor = aForFrame->GetStyleColor()->mColor; + + // Only draw the native caret if the foreground color matches that of + // -moz-fieldtext (the color of the text in a textbox). If it doesn't match + // we are likely in contenteditable or a custom widget and we risk being hard to see + // against the background. In that case, fall back to the CSS color. + nsPresContext* presContext = aForFrame->PresContext(); + + if (GetHookRect().IsEmpty() && presContext) { + nsITheme *theme = presContext->GetTheme(); + if (theme && theme->ThemeSupportsWidget(presContext, aForFrame, NS_THEME_TEXTFIELD_CARET)) { + nsILookAndFeel* lookAndFeel = presContext->LookAndFeel(); + nscolor fieldText; + if (NS_SUCCEEDED(lookAndFeel->GetColor(nsILookAndFeel::eColor__moz_fieldtext, fieldText)) && + fieldText == cssColor) { + theme->DrawWidgetBackground(aCtx, aForFrame, NS_THEME_TEXTFIELD_CARET, + drawCaretRect, drawCaretRect); + return; + } + } + } + + aCtx->SetColor(cssColor); + aCtx->FillRect(drawCaretRect); if (!GetHookRect().IsEmpty()) aCtx->FillRect(GetHookRect() + aOffset); } @@ -1176,7 +1206,7 @@ nsresult nsCaret::UpdateCaretRects(nsIFrame* aFrame, PRInt32 aFrameOffset) } mCaretRect += framePos; - Metrics metrics = ComputeMetrics(aFrame, aFrameOffset); + Metrics metrics = ComputeMetrics(aFrame, aFrameOffset, mCaretRect.height); mCaretRect.width = metrics.mCaretWidth; // Clamp our position to be within our scroll frame. If we don't, then it diff --git a/layout/base/nsCaret.h b/layout/base/nsCaret.h index f3fc25c6bc90..5a4d036f6b42 100644 --- a/layout/base/nsCaret.h +++ b/layout/base/nsCaret.h @@ -104,8 +104,8 @@ class nsCaret : public nsICaret, void PaintCaret(nsDisplayListBuilder *aBuilder, nsIRenderingContext *aCtx, - const nsPoint &aOffset, - nscolor aColor); + nsIFrame *aForFrame, + const nsPoint &aOffset); void SetIgnoreUserModify(PRBool aIgnoreUserModify); @@ -146,7 +146,7 @@ protected: nscoord mBidiIndicatorSize; // width and height of bidi indicator nscoord mCaretWidth; // full caret width including bidi indicator }; - Metrics ComputeMetrics(nsIFrame* aFrame, PRInt32 aOffset); + Metrics ComputeMetrics(nsIFrame* aFrame, PRInt32 aOffset, nscoord aCaretHeight); // Returns true if the caret should be drawn. When |mDrawn| is true, // this returns true, so that we erase the drawn caret. If |aIgnoreDrawnState| @@ -196,6 +196,7 @@ protected: // probably by ComputeMetrics. PRUint32 mBlinkRate; // time for one cyle (off then on), in milliseconds nscoord mCaretWidthCSSPx; // caret width in CSS pixels + float mCaretAspectRatio; // caret width/height aspect ratio PRPackedBool mVisible; // is the caret blinking diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 6a29d78941dc..beb506ac8b31 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -597,8 +597,7 @@ nsDisplayCaret::Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx, const nsRect& aDirtyRect) { // Note: Because we exist, we know that the caret is visible, so we don't // need to check for the caret's visibility. - mCaret->PaintCaret(aBuilder, aCtx, aBuilder->ToReferenceFrame(mFrame), - mFrame->GetStyleColor()->mColor); + mCaret->PaintCaret(aBuilder, aCtx, mFrame, aBuilder->ToReferenceFrame(mFrame)); } PRBool diff --git a/layout/base/nsICaret.h b/layout/base/nsICaret.h index b86ced2f1656..a22e18eeee3c 100644 --- a/layout/base/nsICaret.h +++ b/layout/base/nsICaret.h @@ -58,8 +58,8 @@ class nsIDOMNode; // IID for the nsICaret interface #define NS_ICARET_IID \ -{ 0x35d82f6b, 0x78f6, 0x4e8a, \ - { 0xb9, 0x2a, 0x1a, 0x26, 0xac, 0x2c, 0xe8, 0x53 } } +{ 0x48e23b7f, 0x264e, 0xab7d, \ + { 0x20, 0x03, 0x2c, 0x79, 0x13, 0xe1, 0x09, 0x4d } } class nsICaret: public nsISupports @@ -182,8 +182,8 @@ public: */ virtual void PaintCaret(nsDisplayListBuilder *aBuilder, nsIRenderingContext *aCtx, - const nsPoint &aOffset, - nscolor aColor) = 0; + nsIFrame *aForFrame, + const nsPoint &aOffset) = 0; /** * Sets whether the caret should only be visible in nodes that are not diff --git a/widget/public/nsILookAndFeel.h b/widget/public/nsILookAndFeel.h index c4b18bf03637..10523fc61eee 100644 --- a/widget/public/nsILookAndFeel.h +++ b/widget/public/nsILookAndFeel.h @@ -300,7 +300,11 @@ public: eMetricFloat_ListHorizontalInsidePadding, eMetricFloat_ButtonVerticalInsidePadding, eMetricFloat_ButtonHorizontalInsidePadding, - eMetricFloat_IMEUnderlineRelativeSize + eMetricFloat_IMEUnderlineRelativeSize, + + // The width/height ratio of the cursor. If used, the CaretWidth int metric + // should be added to the calculated caret width. + eMetricFloat_CaretAspectRatio } nsMetricFloatID; NS_IMETHOD GetColor(const nsColorID aID, nscolor &aColor) = 0; diff --git a/widget/src/gtk2/gtk2drawing.c b/widget/src/gtk2/gtk2drawing.c index 272cffd4c4a6..c44ef2c85f35 100644 --- a/widget/src/gtk2/gtk2drawing.c +++ b/widget/src/gtk2/gtk2drawing.c @@ -1442,6 +1442,17 @@ moz_gtk_vpaned_paint(GdkDrawable* drawable, GdkRectangle* rect, return MOZ_GTK_SUCCESS; } +static gint +moz_gtk_caret_paint(GdkDrawable* drawable, GdkRectangle* rect, + GdkRectangle* cliprect, GtkTextDirection direction) +{ + ensure_entry_widget(); + gtk_draw_insertion_cursor(gEntryWidget, drawable, cliprect, + rect, TRUE, direction, FALSE); + + return MOZ_GTK_SUCCESS; +} + static gint moz_gtk_entry_paint(GdkDrawable* drawable, GdkRectangle* rect, GdkRectangle* cliprect, GtkWidgetState* state, @@ -2784,6 +2795,7 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top, case MOZ_GTK_TOOLBAR: case MOZ_GTK_MENUBAR: case MOZ_GTK_TAB_SCROLLARROW: + case MOZ_GTK_ENTRY_CARET: *left = *top = *right = *bottom = 0; return MOZ_GTK_SUCCESS; default: @@ -3052,6 +3064,9 @@ moz_gtk_widget_paint(GtkThemeWidgetType widget, GdkDrawable* drawable, return moz_gtk_entry_paint(drawable, rect, cliprect, state, gEntryWidget, direction); break; + case MOZ_GTK_ENTRY_CARET: + return moz_gtk_caret_paint(drawable, rect, cliprect, direction); + break; case MOZ_GTK_DROPDOWN: return moz_gtk_combo_box_paint(drawable, rect, cliprect, state, (gboolean) flags, direction); diff --git a/widget/src/gtk2/gtkdrawing.h b/widget/src/gtk2/gtkdrawing.h index 4c9d89c4c8bb..6e44d4a2168e 100644 --- a/widget/src/gtk2/gtkdrawing.h +++ b/widget/src/gtk2/gtkdrawing.h @@ -144,6 +144,8 @@ typedef enum { MOZ_GTK_GRIPPER, /* Paints a GtkEntry. */ MOZ_GTK_ENTRY, + /* Paints the native caret (or in GTK-speak: insertion cursor) */ + MOZ_GTK_ENTRY_CARET, /* Paints a GtkOptionMenu. */ MOZ_GTK_DROPDOWN, /* Paints a dropdown arrow (a GtkButton containing a down GtkArrow). */ diff --git a/widget/src/gtk2/nsLookAndFeel.cpp b/widget/src/gtk2/nsLookAndFeel.cpp index 2ce946314d89..bb23e01834d8 100644 --- a/widget/src/gtk2/nsLookAndFeel.cpp +++ b/widget/src/gtk2/nsLookAndFeel.cpp @@ -58,6 +58,7 @@ nscolor nsLookAndFeel::sButtonOuterLightBorder = 0; nscolor nsLookAndFeel::sButtonInnerDarkBorder = 0; nscolor nsLookAndFeel::sOddCellBackground = 0; PRUnichar nsLookAndFeel::sInvisibleCharacter = PRUnichar('*'); +float nsLookAndFeel::sCaretRatio = 0; //------------------------------------------------------------------------- // @@ -609,6 +610,9 @@ NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricFloatID aID, case eMetricFloat_IMEUnderlineRelativeSize: aMetric = 1.0f; break; + case eMetricFloat_CaretAspectRatio: + aMetric = sCaretRatio; + break; default: aMetric = -1.0; res = NS_ERROR_FAILURE; @@ -733,6 +737,12 @@ nsLookAndFeel::InitLookAndFeel() guint value; g_object_get (entry, "invisible-char", &value, NULL); sInvisibleCharacter = PRUnichar(value); + + // caret styles + gtk_widget_style_get(entry, + "cursor-aspect-ratio", &sCaretRatio, + NULL); + gtk_widget_destroy(entry); } diff --git a/widget/src/gtk2/nsLookAndFeel.h b/widget/src/gtk2/nsLookAndFeel.h index 86e68cd85cdd..c2f4baca30a4 100644 --- a/widget/src/gtk2/nsLookAndFeel.h +++ b/widget/src/gtk2/nsLookAndFeel.h @@ -73,6 +73,7 @@ protected: static nscolor sButtonInnerDarkBorder; static nscolor sOddCellBackground; static PRUnichar sInvisibleCharacter; + static float sCaretRatio; static void InitLookAndFeel(); void InitWidget() { diff --git a/widget/src/gtk2/nsNativeThemeGTK.cpp b/widget/src/gtk2/nsNativeThemeGTK.cpp index 1fee546585f8..cb75408e9954 100644 --- a/widget/src/gtk2/nsNativeThemeGTK.cpp +++ b/widget/src/gtk2/nsNativeThemeGTK.cpp @@ -439,6 +439,9 @@ nsNativeThemeGTK::GetGtkWidgetAndState(PRUint8 aWidgetType, nsIFrame* aFrame, case NS_THEME_TEXTFIELD_MULTILINE: aGtkWidgetType = MOZ_GTK_ENTRY; break; + case NS_THEME_TEXTFIELD_CARET: + aGtkWidgetType = MOZ_GTK_ENTRY_CARET; + break; case NS_THEME_LISTBOX: case NS_THEME_TREEVIEW: aGtkWidgetType = MOZ_GTK_TREEVIEW; @@ -1326,7 +1329,7 @@ nsNativeThemeGTK::ThemeSupportsWidget(nsPresContext* aPresContext, // case NS_THEME_SCROLLBAR_GRIPPER_VERTICAL: (n/a for gtk) case NS_THEME_TEXTFIELD: case NS_THEME_TEXTFIELD_MULTILINE: - // case NS_THEME_TEXTFIELD_CARET: + case NS_THEME_TEXTFIELD_CARET: case NS_THEME_DROPDOWN_TEXTFIELD: case NS_THEME_SCALE_HORIZONTAL: case NS_THEME_SCALE_THUMB_HORIZONTAL: diff --git a/widget/src/xpwidgets/nsXPLookAndFeel.cpp b/widget/src/xpwidgets/nsXPLookAndFeel.cpp index f1a84daacb69..3e010b76cc9f 100644 --- a/widget/src/xpwidgets/nsXPLookAndFeel.cpp +++ b/widget/src/xpwidgets/nsXPLookAndFeel.cpp @@ -143,6 +143,8 @@ nsLookAndFeelFloatPref nsXPLookAndFeel::sFloatPrefs[] = PR_FALSE, nsLookAndFeelTypeFloat, 0 }, { "ui.IMEUnderlineRelativeSize", eMetricFloat_IMEUnderlineRelativeSize, PR_FALSE, nsLookAndFeelTypeFloat, 0 }, + { "ui.caretAspectRatio", eMetricFloat_CaretAspectRatio, PR_FALSE, + nsLookAndFeelTypeFloat, 0 }, }; From 11f8f29a22db69ebcae14f6ab8d1a45a634ec061 Mon Sep 17 00:00:00 2001 From: Jason Evans Date: Mon, 23 Jun 2008 07:46:37 -0700 Subject: [PATCH 63/66] Bug 427109: Add memory reserve and xmalloc() API, r=benjamin Add support for a memory reserve, which is managed via the reserve_*() API. Add xmalloc() variants of malloc()-like functions. These functions never return NULL. --- memory/jemalloc/Makefile.in | 5 +- memory/jemalloc/jemalloc.c | 1708 ++++++++++++++++++++++------------- memory/jemalloc/jemalloc.h | 124 ++- memory/jemalloc/ql.h | 114 +++ memory/jemalloc/qr.h | 98 ++ 5 files changed, 1428 insertions(+), 621 deletions(-) create mode 100644 memory/jemalloc/ql.h create mode 100644 memory/jemalloc/qr.h diff --git a/memory/jemalloc/Makefile.in b/memory/jemalloc/Makefile.in index 47ee60392a8d..71d03d92ef8c 100644 --- a/memory/jemalloc/Makefile.in +++ b/memory/jemalloc/Makefile.in @@ -73,8 +73,9 @@ $(CRT_OBJ_DIR)/jemalloc.c: $(srcdir)/crtsp1.diff $(CRT_OBJ_DIR)/build/intel/mozcrt19.dll: \ $(CRT_OBJ_DIR)/jemalloc.c $(srcdir)/jemalloc.c $(srcdir)/jemalloc.h \ - $(srcdir)/rb.h - cp $(srcdir)/jemalloc.c $(srcdir)/jemalloc.h $(srcdir)/rb.h $(CRT_OBJ_DIR) + $(srcdir)/ql.h $(srcdir)/qr.h $(srcdir)/rb.h + cp $(srcdir)/jemalloc.c $(srcdir)/jemalloc.h $(srcdir)/ql.h \ + $(srcdir)/qr.h $(srcdir)/rb.h $(CRT_OBJ_DIR) # this pretty much sucks, but nmake and make don't play well together $(PYTHON) $(srcdir)/build-crt.py $(CRT_OBJ_DIR) #XXX: these don't link right for some reason diff --git a/memory/jemalloc/jemalloc.c b/memory/jemalloc/jemalloc.c index 178dc8f3d3db..5512b2244bf5 100644 --- a/memory/jemalloc/jemalloc.c +++ b/memory/jemalloc/jemalloc.c @@ -1,4 +1,5 @@ -/* -*- Mode: C; tab-width: 4; c-basic-offset: 4 -*- */ +/* -*- Mode: C; tab-width: 8; c-basic-offset: 8 -*- */ +/* vim:set softtabstop=8 shiftwidth=8: */ /*- * Copyright (C) 2006-2008 Jason Evans . * All rights reserved. @@ -162,31 +163,22 @@ */ /* #define MALLOC_BALANCE */ -/* - * MALLOC_DSS enables use of sbrk(2) to allocate chunks from the data storage - * segment (DSS). In an ideal world, this functionality would be completely - * unnecessary, but we are burdened by history and the lack of resource limits - * for anonymous mapped memory. - */ -/* - * Uniformly disable sbrk(2) use in Mozilla, since it has various problems - * across platforms: - * - * Linux: sbrk() fails to detect error conditions when using large amounts of - * memory, resulting in memory corruption. - * - * Darwin: sbrk() is severely limited in how much memory it can allocate, and - * its use is strongly discouraged. - * - * Solaris: sbrk() does not necessarily discard pages when the DSS is shrunk, - * which makes it possible to get non-zeroed pages when re-expanding - * the DSS. This is incompatible with jemalloc's assumptions, and a - * fix would require chunk_alloc_dss() to optionally zero memory as - * chunk_recycle_dss() does (though the cost could be reduced by - * keeping track of the DSS high water mark and zeroing only when - * below that mark). - */ -/* #define MALLOC_DSS */ +#if (!defined(MOZ_MEMORY_WINDOWS) && !defined(MOZ_MEMORY_DARWIN)) + /* + * MALLOC_PAGEFILE causes all mmap()ed memory to be backed by temporary + * files, so that if a chunk is mapped, it is guaranteed to be swappable. + * This avoids asynchronous OOM failures that are due to VM over-commit. + * + * XXX OS X over-commits, so we should probably use mmap() instead of + * vm_allocate(), so that MALLOC_PAGEFILE works. + */ +# define MALLOC_PAGEFILE +#endif + +#ifdef MALLOC_PAGEFILE +/* Write size when initializing a page file. */ +# define MALLOC_PAGEFILE_WRITE_SIZE 512 +#endif #ifdef MOZ_MEMORY_LINUX #define _GNU_SOURCE /* For mremap(2). */ @@ -285,6 +277,9 @@ __FBSDID("$FreeBSD: head/lib/libc/stdlib/malloc.c 179704 2008-06-10 15:46:18Z ja #ifndef MADV_FREE # define MADV_FREE MADV_DONTNEED #endif +#ifndef MAP_NOSYNC +# define MAP_NOSYNC 0 +#endif #include #ifndef MOZ_MEMORY #include @@ -363,6 +358,8 @@ static const bool __isthreaded = true; #include #endif +#include "qr.h" +#include "ql.h" #ifdef MOZ_MEMORY_WINDOWS /* MSVC++ does not support C99 variable-length arrays. */ # define RB_NO_C99_VARARRAYS @@ -458,6 +455,18 @@ static const bool __isthreaded = true; /* Maximum number of dirty pages per arena. */ #define DIRTY_MAX_DEFAULT (1U << 10) +/* Default reserve chunks. */ +#define RESERVE_MIN_2POW_DEFAULT 1 +/* + * Default range (in chunks) between reserve_min and reserve_max, in addition + * to the mandatory one chunk per arena. + */ +#ifdef MALLOC_PAGEFILE +# define RESERVE_RANGE_2POW_DEFAULT 5 +#else +# define RESERVE_RANGE_2POW_DEFAULT 0 +#endif + /* * Maximum size of L1 cache line. This is used to avoid cache line aliasing, * so over-estimates are okay (up to a point), but under-estimates will @@ -699,6 +708,30 @@ struct extent_node_s { }; typedef rb_tree(extent_node_t) extent_tree_t; +/******************************************************************************/ +/* + * Reserve data structures. + */ + +/* Callback registration. */ +typedef struct reserve_reg_s reserve_reg_t; +struct reserve_reg_s { + /* Linkage for list of all registered callbacks. */ + ql_elm(reserve_reg_t) link; + + /* Callback function pointer. */ + reserve_cb_t *cb; + + /* Opaque application data pointer. */ + void *ctx; + + /* + * Sequence number of most condition notification most recently sent to + * this callback. + */ + uint64_t seq; +}; + /******************************************************************************/ /* * Arena data structures. @@ -837,6 +870,12 @@ struct arena_s { arena_stats_t stats; #endif + /* + * Chunk allocation sequence number, used to detect races with other + * threads during chunk allocation, and then discard unnecessary chunks. + */ + uint64_t chunk_seq; + /* Tree of all chunks this arena manages. */ arena_chunk_tree_t chunks_all; @@ -852,18 +891,6 @@ struct arena_s { */ arena_chunk_tree_t chunks_dirty; - /* - * In order to avoid rapid chunk allocation/deallocation when an arena - * oscillates right on the cusp of needing a new chunk, cache the most - * recently freed chunk. The spare is left in the arena's chunk trees - * until it is deleted. - * - * There is one spare chunk per arena, rather than one spare total, in - * order to avoid interactions between multiple threads that could make - * a single spare inadequate. - */ - arena_chunk_t *spare; - /* * Current count of pages within unused runs that are potentially * dirty, and for which madvise(... MADV_FREE) has not been called. By @@ -960,29 +987,6 @@ static malloc_mutex_t huge_mtx; /* Tree of chunks that are stand-alone huge allocations. */ static extent_tree_t huge; -#ifdef MALLOC_DSS -/* - * Protects sbrk() calls. This avoids malloc races among threads, though it - * does not protect against races with threads that call sbrk() directly. - */ -static malloc_mutex_t dss_mtx; -/* Base address of the DSS. */ -static void *dss_base; -/* Current end of the DSS, or ((void *)-1) if the DSS is exhausted. */ -static void *dss_prev; -/* Current upper limit on DSS addresses. */ -static void *dss_max; - -/* - * Trees of chunks that were previously allocated (trees differ only in node - * ordering). These are used when allocating chunks, in an attempt to re-use - * address space. Depending on function, different tree orderings are needed, - * which is why there are two trees with the same contents. - */ -static extent_tree_t dss_chunks_szad; -static extent_tree_t dss_chunks_ad; -#endif - #ifdef MALLOC_STATS /* Huge allocation statistics. */ static uint64_t huge_nmalloc; @@ -990,6 +994,43 @@ static uint64_t huge_ndalloc; static size_t huge_allocated; #endif +/****************/ +/* + * Memory reserve. + */ + +#ifdef MALLOC_PAGEFILE +static char pagefile_templ[PATH_MAX]; +#endif + +/* Protects reserve-related data structures. */ +static malloc_mutex_t reserve_mtx; + +/* + * Bounds on acceptable reserve size, and current reserve size. Reserve + * depletion may cause (reserve_cur < reserve_min). + */ +static size_t reserve_min; +static size_t reserve_cur; +static size_t reserve_max; + +/* List of registered callbacks. */ +static ql_head(reserve_reg_t) reserve_regs; + +/* + * Condition notification sequence number, used to determine whether all + * registered callbacks have been notified of the most current condition. + */ +static uint64_t reserve_seq; + +/* + * Trees of chunks currently in the memory reserve. Depending on function, + * different tree orderings are needed, which is why there are two trees with + * the same contents. + */ +static extent_tree_t reserve_chunks_szad; +static extent_tree_t reserve_chunks_ad; + /****************************/ /* * base (internal allocation). @@ -1007,6 +1048,7 @@ static void *base_next_decommitted; #endif static void *base_past_addr; /* Addr immediately past base_pages. */ static extent_node_t *base_nodes; +static reserve_reg_t *base_reserve_regs; static malloc_mutex_t base_mtx; #ifdef MALLOC_STATS static size_t base_mapped; @@ -1023,6 +1065,7 @@ static size_t base_mapped; */ static arena_t **arenas; static unsigned narenas; +static unsigned narenas_2pow; #ifndef NO_TLS # ifdef MALLOC_BALANCE static unsigned narenas_2pow; @@ -1068,10 +1111,6 @@ static bool opt_abort = false; static bool opt_junk = false; #endif #endif -#ifdef MALLOC_DSS -static bool opt_dss = true; -static bool opt_mmap = true; -#endif static size_t opt_dirty_max = DIRTY_MAX_DEFAULT; #ifdef MALLOC_BALANCE static uint64_t opt_balance_threshold = BALANCE_THRESHOLD_DEFAULT; @@ -1080,6 +1119,11 @@ static bool opt_print_stats = false; static size_t opt_quantum_2pow = QUANTUM_2POW_MIN; static size_t opt_small_max_2pow = SMALL_MAX_2POW_DEFAULT; static size_t opt_chunk_2pow = CHUNK_2POW_DEFAULT; +static int opt_reserve_min_lshift = 0; +static int opt_reserve_range_lshift = 0; +#ifdef MALLOC_PAGEFILE +static bool opt_pagefile = true; +#endif #ifdef MALLOC_UTRACE static bool opt_utrace = false; #endif @@ -1130,30 +1174,27 @@ static void wrtmessage(const char *p1, const char *p2, const char *p3, static void malloc_printf(const char *format, ...); #endif static char *umax2s(uintmax_t x, char *s); -#ifdef MALLOC_DSS -static bool base_pages_alloc_dss(size_t minsize); -#endif static bool base_pages_alloc_mmap(size_t minsize); static bool base_pages_alloc(size_t minsize); static void *base_alloc(size_t size); static void *base_calloc(size_t number, size_t size); static extent_node_t *base_node_alloc(void); static void base_node_dealloc(extent_node_t *node); +static reserve_reg_t *base_reserve_reg_alloc(void); +static void base_reserve_reg_dealloc(reserve_reg_t *reg); #ifdef MALLOC_STATS static void stats_print(arena_t *arena); #endif -static void *pages_map(void *addr, size_t size); +static void *pages_map(void *addr, size_t size, int pfd); static void pages_unmap(void *addr, size_t size); -#ifdef MALLOC_DSS -static void *chunk_alloc_dss(size_t size); -static void *chunk_recycle_dss(size_t size, bool zero); -#endif -static void *chunk_alloc_mmap(size_t size); -static void *chunk_alloc(size_t size, bool zero); -#ifdef MALLOC_DSS -static extent_node_t *chunk_dealloc_dss_record(void *chunk, size_t size); -static bool chunk_dealloc_dss(void *chunk, size_t size); +static void *chunk_alloc_mmap(size_t size, bool pagefile); +#ifdef MALLOC_PAGEFILE +static int pagefile_init(size_t size); +static void pagefile_close(int pfd); #endif +static void *chunk_recycle_reserve(size_t size, bool zero); +static void *chunk_alloc(size_t size, bool zero, bool pagefile); +static extent_node_t *chunk_dealloc_reserve(void *chunk, size_t size); static void chunk_dealloc_mmap(void *chunk, size_t size); static void chunk_dealloc(void *chunk, size_t size); #ifndef NO_TLS @@ -1164,7 +1205,7 @@ static void arena_chunk_node_dealloc(arena_chunk_t *chunk, extent_node_t *node); static void arena_run_split(arena_t *arena, arena_run_t *run, size_t size, bool small, bool zero); -static arena_chunk_t *arena_chunk_alloc(arena_t *arena); +static void arena_chunk_init(arena_t *arena, arena_chunk_t *chunk); static void arena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk); static arena_run_t *arena_run_alloc(arena_t *arena, size_t size, bool small, bool zero); @@ -1204,6 +1245,10 @@ static void malloc_print_stats(void); static #endif bool malloc_init_hard(void); +static void reserve_shrink(void); +static uint64_t reserve_notify(reserve_cnd_t cnd, size_t size, uint64_t seq); +static uint64_t reserve_crit(size_t size, const char *fname, uint64_t seq); +static void reserve_fail(size_t size, const char *fname); /* * End function prototypes. @@ -1650,69 +1695,31 @@ pages_commit(void *addr, size_t size) } #endif -#ifdef MALLOC_DSS -static bool -base_pages_alloc_dss(size_t minsize) -{ - - /* - * Do special DSS allocation here, since base allocations don't need to - * be chunk-aligned. - */ - malloc_mutex_lock(&dss_mtx); - if (dss_prev != (void *)-1) { - intptr_t incr; - size_t csize = CHUNK_CEILING(minsize); - - do { - /* Get the current end of the DSS. */ - dss_max = sbrk(0); - - /* - * Calculate how much padding is necessary to - * chunk-align the end of the DSS. Don't worry about - * dss_max not being chunk-aligned though. - */ - incr = (intptr_t)chunksize - - (intptr_t)CHUNK_ADDR2OFFSET(dss_max); - assert(incr >= 0); - if ((size_t)incr < minsize) - incr += csize; - - dss_prev = sbrk(incr); - if (dss_prev == dss_max) { - /* Success. */ - dss_max = (void *)((intptr_t)dss_prev + incr); - base_pages = dss_prev; - base_next_addr = base_pages; - base_past_addr = dss_max; -#ifdef MALLOC_STATS - base_mapped += incr; -#endif - malloc_mutex_unlock(&dss_mtx); - return (false); - } - } while (dss_prev != (void *)-1); - } - malloc_mutex_unlock(&dss_mtx); - - return (true); -} -#endif - static bool base_pages_alloc_mmap(size_t minsize) { + bool ret; size_t csize; #ifdef MALLOC_DECOMMIT size_t pminsize; #endif + int pfd; assert(minsize != 0); - csize = PAGE_CEILING(minsize); - base_pages = pages_map(NULL, csize); - if (base_pages == NULL) - return (true); + csize = CHUNK_CEILING(minsize); +#ifdef MALLOC_PAGEFILE + if (opt_pagefile) { + pfd = pagefile_init(csize); + if (pfd == -1) + return (true); + } else +#endif + pfd = -1; + base_pages = pages_map(NULL, csize, pfd); + if (base_pages == NULL) { + ret = true; + goto RETURN; + } base_next_addr = base_pages; base_past_addr = (void *)((uintptr_t)base_pages + csize); #ifdef MALLOC_DECOMMIT @@ -1729,6 +1736,12 @@ base_pages_alloc_mmap(size_t minsize) base_mapped += csize; #endif + ret = false; +RETURN: +#ifdef MALLOC_PAGEFILE + if (pfd != -1) + pagefile_close(pfd); +#endif return (false); } @@ -1736,18 +1749,8 @@ static bool base_pages_alloc(size_t minsize) { -#ifdef MALLOC_DSS - if (opt_dss) { - if (base_pages_alloc_dss(minsize) == false) - return (false); - } - - if (opt_mmap && minsize != 0) -#endif - { - if (base_pages_alloc_mmap(minsize) == false) - return (false); - } + if (base_pages_alloc_mmap(minsize) == false) + return (false); return (true); } @@ -1838,6 +1841,38 @@ base_node_dealloc(extent_node_t *node) malloc_mutex_unlock(&base_mtx); } +static reserve_reg_t * +base_reserve_reg_alloc(void) +{ + reserve_reg_t *ret; + + malloc_mutex_lock(&base_mtx); + if (base_reserve_regs != NULL) { + ret = base_reserve_regs; + base_reserve_regs = *(reserve_reg_t **)ret; + VALGRIND_FREELIKE_BLOCK(ret, 0); + VALGRIND_MALLOCLIKE_BLOCK(ret, sizeof(reserve_reg_t), 0, false); + malloc_mutex_unlock(&base_mtx); + } else { + malloc_mutex_unlock(&base_mtx); + ret = (reserve_reg_t *)base_alloc(sizeof(reserve_reg_t)); + } + + return (ret); +} + +static void +base_reserve_reg_dealloc(reserve_reg_t *reg) +{ + + malloc_mutex_lock(&base_mtx); + VALGRIND_FREELIKE_BLOCK(reg, 0); + VALGRIND_MALLOCLIKE_BLOCK(reg, sizeof(reserve_reg_t *), 0, false); + *(reserve_reg_t **)reg = base_reserve_regs; + base_reserve_regs = reg; + malloc_mutex_unlock(&base_mtx); +} + /******************************************************************************/ #ifdef MALLOC_STATS @@ -2006,7 +2041,7 @@ rb_wrap(static, extent_tree_ad_, extent_tree_t, extent_node_t, link_ad, #ifdef MOZ_MEMORY_WINDOWS static void * -pages_map(void *addr, size_t size) +pages_map(void *addr, size_t size, int pfd) { void *ret; @@ -2029,7 +2064,7 @@ pages_unmap(void *addr, size_t size) } #elif (defined(MOZ_MEMORY_DARWIN)) static void * -pages_map(void *addr, size_t size) +pages_map(void *addr, size_t size, int pfd) { void *ret; kern_return_t err; @@ -2081,7 +2116,7 @@ pages_copy(void *dest, const void *src, size_t n) } #else /* MOZ_MEMORY_DARWIN */ static void * -pages_map(void *addr, size_t size) +pages_map(void *addr, size_t size, int pfd) { void *ret; @@ -2089,8 +2124,16 @@ pages_map(void *addr, size_t size) * We don't use MAP_FIXED here, because it can cause the *replacement* * of existing mappings, and we only want to create new mappings. */ - ret = mmap(addr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, - -1, 0); +#ifdef MALLOC_PAGEFILE + if (pfd != -1) { + ret = mmap(addr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | + MAP_NOSYNC, pfd, 0); + } else +#endif + { + ret = mmap(addr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | + MAP_ANON, -1, 0); + } assert(ret != NULL); if (ret == MAP_FAILED) @@ -2132,131 +2175,50 @@ pages_unmap(void *addr, size_t size) } #endif -#ifdef MALLOC_DSS -static void * -chunk_alloc_dss(size_t size) -{ - - /* - * sbrk() uses a signed increment argument, so take care not to - * interpret a huge allocation request as a negative increment. - */ - if ((intptr_t)size < 0) - return (NULL); - - malloc_mutex_lock(&dss_mtx); - if (dss_prev != (void *)-1) { - intptr_t incr; - - /* - * The loop is necessary to recover from races with other - * threads that are using the DSS for something other than - * malloc. - */ - do { - void *ret; - - /* Get the current end of the DSS. */ - dss_max = sbrk(0); - - /* - * Calculate how much padding is necessary to - * chunk-align the end of the DSS. - */ - incr = (intptr_t)size - - (intptr_t)CHUNK_ADDR2OFFSET(dss_max); - if (incr == (intptr_t)size) - ret = dss_max; - else { - ret = (void *)((intptr_t)dss_max + incr); - incr += size; - } - - dss_prev = sbrk(incr); - if (dss_prev == dss_max) { - /* Success. */ - dss_max = (void *)((intptr_t)dss_prev + incr); - malloc_mutex_unlock(&dss_mtx); - return (ret); - } - } while (dss_prev != (void *)-1); - } - malloc_mutex_unlock(&dss_mtx); - - return (NULL); -} - -static void * -chunk_recycle_dss(size_t size, bool zero) -{ - extent_node_t *node, key; - - key.addr = NULL; - key.size = size; - malloc_mutex_lock(&dss_mtx); - node = extent_tree_szad_nsearch(&dss_chunks_szad, &key); - if (node != NULL) { - void *ret = node->addr; - - /* Remove node from the tree. */ - extent_tree_szad_remove(&dss_chunks_szad, node); - if (node->size == size) { - extent_tree_ad_remove(&dss_chunks_ad, node); - base_node_dealloc(node); - } else { - /* - * Insert the remainder of node's address range as a - * smaller chunk. Its position within dss_chunks_ad - * does not change. - */ - assert(node->size > size); - node->addr = (void *)((uintptr_t)node->addr + size); - node->size -= size; - extent_tree_szad_insert(&dss_chunks_szad, node); - } - malloc_mutex_unlock(&dss_mtx); - - if (zero) - memset(ret, 0, size); - return (ret); - } - malloc_mutex_unlock(&dss_mtx); - - return (NULL); -} -#endif - -#ifdef MOZ_MEMORY_WINDOWS static inline void * -chunk_alloc_mmap(size_t size) +chunk_alloc_mmap(size_t size, bool pagefile) { void *ret; size_t offset; + int pfd; + +#ifdef MALLOC_PAGEFILE + if (opt_pagefile && pagefile) { + pfd = pagefile_init(size); + if (pfd == -1) + return (NULL); + } else +#endif + pfd = -1; /* * Windows requires that there be a 1:1 mapping between VM * allocation/deallocation operations. Therefore, take care here to * acquire the final result via one mapping operation. This means * unmapping any preliminary result that is not correctly aligned. + * + * The MALLOC_PAGEFILE code also benefits from this mapping algorithm, + * since it reduces the number of page files. */ - ret = pages_map(NULL, size); + ret = pages_map(NULL, size, pfd); if (ret == NULL) - return (NULL); + goto RETURN; offset = CHUNK_ADDR2OFFSET(ret); if (offset != 0) { /* Deallocate, then try to allocate at (ret + size - offset). */ pages_unmap(ret, size); - ret = pages_map((void *)((uintptr_t)ret + size - offset), size); + ret = pages_map((void *)((uintptr_t)ret + size - offset), size, + pfd); while (ret == NULL) { /* * Over-allocate in order to map a memory region that * is definitely large enough. */ - ret = pages_map(NULL, size + chunksize); + ret = pages_map(NULL, size + chunksize, -1); if (ret == NULL) - return (NULL); + goto RETURN; /* * Deallocate, then allocate the correct size, within * the over-sized mapping. @@ -2264,10 +2226,10 @@ chunk_alloc_mmap(size_t size) offset = CHUNK_ADDR2OFFSET(ret); pages_unmap(ret, size + chunksize); if (offset == 0) - ret = pages_map(ret, size); + ret = pages_map(ret, size, pfd); else { ret = pages_map((void *)((uintptr_t)ret + - chunksize - offset), size); + chunksize - offset), size, pfd); } /* * Failure here indicates a race with another thread, so @@ -2276,121 +2238,204 @@ chunk_alloc_mmap(size_t size) } } +RETURN: +#ifdef MALLOC_PAGEFILE + if (pfd != -1) + pagefile_close(pfd); +#endif return (ret); } -#else -static inline void * -chunk_alloc_mmap(size_t size) + +#ifdef MALLOC_PAGEFILE +static int +pagefile_init(size_t size) { - void *ret; - size_t offset; + int ret; + size_t i; + char pagefile_path[PATH_MAX]; + char zbuf[MALLOC_PAGEFILE_WRITE_SIZE]; /* - * Ideally, there would be a way to specify alignment to mmap() (like - * NetBSD has), but in the absence of such a feature, we have to work - * hard to efficiently create aligned mappings. The reliable, but - * expensive method is to create a mapping that is over-sized, then - * trim the excess. However, that always results in at least one call - * to pages_unmap(). - * - * A more optimistic approach is to try mapping precisely the right - * amount, then try to append another mapping if alignment is off. In - * practice, this works out well as long as the application is not - * interleaving mappings via direct mmap() calls. If we do run into a - * situation where there is an interleaved mapping and we are unable to - * extend an unaligned mapping, our best option is to momentarily - * revert to the reliable-but-expensive method. This will tend to - * leave a gap in the memory map that is too small to cause later - * problems for the optimistic method. + * Create a temporary file, then immediately unlink it so that it will + * not persist. */ + strcpy(pagefile_path, pagefile_templ); + ret = mkstemp(pagefile_path); + if (ret == -1) + return (ret); + if (unlink(pagefile_path)) { + char buf[STRERROR_BUF]; - ret = pages_map(NULL, size); - if (ret == NULL) - return (NULL); + strerror_r(errno, buf, sizeof(buf)); + _malloc_message(_getprogname(), ": (malloc) Error in unlink(\"", + pagefile_path, "\"):"); + _malloc_message(buf, "\n", "", ""); + if (opt_abort) + abort(); + } - offset = CHUNK_ADDR2OFFSET(ret); - if (offset != 0) { - /* Try to extend chunk boundary. */ - if (pages_map((void *)((uintptr_t)ret + size), - chunksize - offset) == NULL) { - /* - * Extension failed. Clean up, then revert to the - * reliable-but-expensive method. - */ - pages_unmap(ret, size); + /* + * Write sequential zeroes to the file in order to assure that disk + * space is committed, with minimal fragmentation. It would be + * sufficient to write one zero per disk block, but that potentially + * results in more system calls, for no real gain. + */ + memset(zbuf, 0, sizeof(zbuf)); + for (i = 0; i < size; i += sizeof(zbuf)) { + if (write(ret, zbuf, sizeof(zbuf)) != sizeof(zbuf)) { + if (errno != ENOSPC) { + char buf[STRERROR_BUF]; - /* Beware size_t wrap-around. */ - if (size + chunksize <= size) - return NULL; - - ret = pages_map(NULL, size + chunksize); - if (ret == NULL) - return (NULL); - - /* Clean up unneeded leading/trailing space. */ - offset = CHUNK_ADDR2OFFSET(ret); - if (offset != 0) { - /* Leading space. */ - pages_unmap(ret, chunksize - offset); - - ret = (void *)((uintptr_t)ret + - (chunksize - offset)); - - /* Trailing space. */ - pages_unmap((void *)((uintptr_t)ret + size), - offset); - } else { - /* Trailing space only. */ - pages_unmap((void *)((uintptr_t)ret + size), - chunksize); + strerror_r(errno, buf, sizeof(buf)); + _malloc_message(_getprogname(), + ": (malloc) Error in write(): ", buf, "\n"); + if (opt_abort) + abort(); } - } else { - /* Clean up unneeded leading space. */ - pages_unmap(ret, chunksize - offset); - ret = (void *)((uintptr_t)ret + (chunksize - offset)); + pagefile_close(ret); + return (-1); } } return (ret); } + +static void +pagefile_close(int pfd) +{ + + if (close(pfd)) { + char buf[STRERROR_BUF]; + + strerror_r(errno, buf, sizeof(buf)); + _malloc_message(_getprogname(), + ": (malloc) Error in close(): ", buf, "\n"); + if (opt_abort) + abort(); + } +} #endif static void * -chunk_alloc(size_t size, bool zero) +chunk_recycle_reserve(size_t size, bool zero) +{ + extent_node_t *node, key; + +#ifdef MALLOC_DECOMMIT + if (size != chunksize) + return (NULL); +#endif + + key.addr = NULL; + key.size = size; + malloc_mutex_lock(&reserve_mtx); + node = extent_tree_szad_nsearch(&reserve_chunks_szad, &key); + if (node != NULL) { + void *ret = node->addr; + + /* Remove node from the tree. */ + extent_tree_szad_remove(&reserve_chunks_szad, node); +#ifndef MALLOC_DECOMMIT + if (node->size == size) { +#else + assert(node->size == size); +#endif + extent_tree_ad_remove(&reserve_chunks_ad, node); + base_node_dealloc(node); +#ifndef MALLOC_DECOMMIT + } else { + /* + * Insert the remainder of node's address range as a + * smaller chunk. Its position within reserve_chunks_ad + * does not change. + */ + assert(node->size > size); + node->addr = (void *)((uintptr_t)node->addr + size); + node->size -= size; + extent_tree_szad_insert(&reserve_chunks_szad, node); + } +#endif + reserve_cur -= size; + /* + * Try to replenish the reserve if this allocation depleted it. + */ +#ifndef MALLOC_DECOMMIT + if (reserve_cur < reserve_min) { + size_t diff = reserve_min - reserve_cur; +#else + while (reserve_cur < reserve_min) { +# define diff chunksize +#endif + void *chunk; + + malloc_mutex_unlock(&reserve_mtx); + chunk = chunk_alloc_mmap(diff, true); + malloc_mutex_lock(&reserve_mtx); + if (chunk == NULL) { + uint64_t seq = 0; + + do { + seq = reserve_notify(RESERVE_CND_LOW, + size, seq); + } while (reserve_cur < reserve_min && seq != 0); + } else { + extent_node_t *node; + + node = chunk_dealloc_reserve(chunk, diff); + if (node == NULL) { + uint64_t seq = 0; + + pages_unmap(chunk, diff); + do { + seq = reserve_notify( + RESERVE_CND_LOW, size, seq); + } while (reserve_cur < reserve_min && + seq != 0); + } + } + } + malloc_mutex_unlock(&reserve_mtx); + +#ifdef MALLOC_DECOMMIT + pages_commit(ret, size); +# undef diff +#else + if (zero) + memset(ret, 0, size); +#endif + return (ret); + } + malloc_mutex_unlock(&reserve_mtx); + + return (NULL); +} + +static void * +chunk_alloc(size_t size, bool zero, bool pagefile) { void *ret; assert(size != 0); assert((size & chunksize_mask) == 0); -#ifdef MALLOC_DSS - if (opt_dss) { - ret = chunk_recycle_dss(size, zero); - if (ret != NULL) { - goto RETURN; - } + ret = chunk_recycle_reserve(size, zero); + if (ret != NULL) + goto RETURN; - ret = chunk_alloc_dss(size); - if (ret != NULL) - goto RETURN; - } - - if (opt_mmap) + ret = chunk_alloc_mmap(size, pagefile); + if (ret != NULL) { +#ifdef MALLOC_STATS + stats_chunks.nchunks += (size / chunksize); #endif - { - ret = chunk_alloc_mmap(size); - if (ret != NULL) - goto RETURN; + goto RETURN; } /* All strategies for allocation failed. */ ret = NULL; RETURN: #ifdef MALLOC_STATS - if (ret != NULL) { - stats_chunks.nchunks += (size / chunksize); + if (ret != NULL) stats_chunks.curchunks += (size / chunksize); - } if (stats_chunks.curchunks > stats_chunks.highchunks) stats_chunks.highchunks = stats_chunks.curchunks; #endif @@ -2399,122 +2444,77 @@ RETURN: return (ret); } -#ifdef MALLOC_DSS static extent_node_t * -chunk_dealloc_dss_record(void *chunk, size_t size) +chunk_dealloc_reserve(void *chunk, size_t size) { - extent_node_t *node, *prev, key; + extent_node_t *node; + +#ifdef MALLOC_DECOMMIT + if (size != chunksize) + return (NULL); +#else + extent_node_t *prev, key; key.addr = (void *)((uintptr_t)chunk + size); - node = extent_tree_ad_nsearch(&dss_chunks_ad, &key); + node = extent_tree_ad_nsearch(&reserve_chunks_ad, &key); /* Try to coalesce forward. */ if (node != NULL && node->addr == key.addr) { /* * Coalesce chunk with the following address range. This does - * not change the position within dss_chunks_ad, so only - * remove/insert from/into dss_chunks_szad. + * not change the position within reserve_chunks_ad, so only + * remove/insert from/into reserve_chunks_szad. */ - extent_tree_szad_remove(&dss_chunks_szad, node); + extent_tree_szad_remove(&reserve_chunks_szad, node); node->addr = chunk; node->size += size; - extent_tree_szad_insert(&dss_chunks_szad, node); + extent_tree_szad_insert(&reserve_chunks_szad, node); } else { - /* - * Coalescing forward failed, so insert a new node. Drop - * dss_mtx during node allocation, since it is possible that a - * new base chunk will be allocated. - */ - malloc_mutex_unlock(&dss_mtx); +#endif + /* Coalescing forward failed, so insert a new node. */ node = base_node_alloc(); - malloc_mutex_lock(&dss_mtx); if (node == NULL) return (NULL); node->addr = chunk; node->size = size; - extent_tree_ad_insert(&dss_chunks_ad, node); - extent_tree_szad_insert(&dss_chunks_szad, node); + extent_tree_ad_insert(&reserve_chunks_ad, node); + extent_tree_szad_insert(&reserve_chunks_szad, node); +#ifndef MALLOC_DECOMMIT } /* Try to coalesce backward. */ - prev = extent_tree_ad_prev(&dss_chunks_ad, node); + prev = extent_tree_ad_prev(&reserve_chunks_ad, node); if (prev != NULL && (void *)((uintptr_t)prev->addr + prev->size) == chunk) { /* * Coalesce chunk with the previous address range. This does - * not change the position within dss_chunks_ad, so only - * remove/insert node from/into dss_chunks_szad. + * not change the position within reserve_chunks_ad, so only + * remove/insert node from/into reserve_chunks_szad. */ - extent_tree_szad_remove(&dss_chunks_szad, prev); - extent_tree_ad_remove(&dss_chunks_ad, prev); + extent_tree_szad_remove(&reserve_chunks_szad, prev); + extent_tree_ad_remove(&reserve_chunks_ad, prev); - extent_tree_szad_remove(&dss_chunks_szad, node); + extent_tree_szad_remove(&reserve_chunks_szad, node); node->addr = prev->addr; node->size += prev->size; - extent_tree_szad_insert(&dss_chunks_szad, node); + extent_tree_szad_insert(&reserve_chunks_szad, node); base_node_dealloc(prev); } +#endif + +#ifdef MALLOC_DECOMMIT + pages_decommit(chunk, size); +#else + madvise(chunk, size, MADV_FREE); +#endif + + reserve_cur += size; + if (reserve_cur > reserve_max) + reserve_shrink(); return (node); } -static bool -chunk_dealloc_dss(void *chunk, size_t size) -{ - - malloc_mutex_lock(&dss_mtx); - if ((uintptr_t)chunk >= (uintptr_t)dss_base - && (uintptr_t)chunk < (uintptr_t)dss_max) { - extent_node_t *node; - - /* Try to coalesce with other unused chunks. */ - node = chunk_dealloc_dss_record(chunk, size); - if (node != NULL) { - chunk = node->addr; - size = node->size; - } - - /* Get the current end of the DSS. */ - dss_max = sbrk(0); - - /* - * Try to shrink the DSS if this chunk is at the end of the - * DSS. The sbrk() call here is subject to a race condition - * with threads that use brk(2) or sbrk(2) directly, but the - * alternative would be to leak memory for the sake of poorly - * designed multi-threaded programs. - */ - if ((void *)((uintptr_t)chunk + size) == dss_max - && (dss_prev = sbrk(-(intptr_t)size)) == dss_max) { - /* Success. */ - dss_max = (void *)((intptr_t)dss_prev - (intptr_t)size); - - if (node != NULL) { - extent_tree_szad_remove(&dss_chunks_szad, node); - extent_tree_ad_remove(&dss_chunks_ad, node); - base_node_dealloc(node); - } - malloc_mutex_unlock(&dss_mtx); - } else { - malloc_mutex_unlock(&dss_mtx); -#ifdef MOZ_MEMORY_WINDOWS - VirtualAlloc(chunk, size, MEM_RESET, PAGE_READWRITE); -#elif (defined(MOZ_MEMORY_DARWIN)) - mmap(chunk, size, PROT_READ | PROT_WRITE, MAP_PRIVATE - | MAP_ANON | MAP_FIXED, -1, 0); -#else - madvise(chunk, size, MADV_FREE); -#endif - } - - return (false); - } - malloc_mutex_unlock(&dss_mtx); - - return (true); -} -#endif - static void chunk_dealloc_mmap(void *chunk, size_t size) { @@ -2525,6 +2525,7 @@ chunk_dealloc_mmap(void *chunk, size_t size) static void chunk_dealloc(void *chunk, size_t size) { + extent_node_t *node; assert(chunk != NULL); assert(CHUNK_ADDR2BASE(chunk) == chunk); @@ -2535,14 +2536,9 @@ chunk_dealloc(void *chunk, size_t size) stats_chunks.curchunks -= (size / chunksize); #endif -#ifdef MALLOC_DSS - if (opt_dss) { - if (chunk_dealloc_dss(chunk, size) == false) - return; - } - - if (opt_mmap) -#endif + /* Try to merge chunk into the reserve. */ + node = chunk_dealloc_reserve(chunk, size); + if (node == NULL) chunk_dealloc_mmap(chunk, size); } @@ -2961,7 +2957,7 @@ arena_run_split(arena_t *arena, arena_run_t *run, size_t size, bool small, # ifdef MALLOC_STATS arena->stats.ncommit++; # endif - } + } else /* No need to zero since commit zeros. */ #endif /* Zero if necessary. */ @@ -3014,72 +3010,56 @@ arena_run_split(arena_t *arena, arena_run_t *run, size_t size, bool small, arena_chunk_tree_dirty_remove(&arena->chunks_dirty, chunk); } -static arena_chunk_t * -arena_chunk_alloc(arena_t *arena) +static void +arena_chunk_init(arena_t *arena, arena_chunk_t *chunk) { - arena_chunk_t *chunk; extent_node_t *node; - if (arena->spare != NULL) { - chunk = arena->spare; - arena->spare = NULL; - } else { - chunk = (arena_chunk_t *)chunk_alloc(chunksize, true); - if (chunk == NULL) - return (NULL); - VALGRIND_MALLOCLIKE_BLOCK(chunk, (arena_chunk_header_npages << - pagesize_2pow), 0, false); + VALGRIND_MALLOCLIKE_BLOCK(chunk, (arena_chunk_header_npages << + pagesize_2pow), 0, false); #ifdef MALLOC_STATS - arena->stats.mapped += chunksize; + arena->stats.mapped += chunksize; #endif - chunk->arena = arena; + chunk->arena = arena; - arena_chunk_tree_all_insert(&arena->chunks_all, chunk); + arena_chunk_tree_all_insert(&arena->chunks_all, chunk); - /* - * Claim that no pages are in use, since the header is merely - * overhead. - */ - chunk->pages_used = 0; - chunk->ndirty = 0; + /* + * Claim that no pages are in use, since the header is merely overhead. + */ + chunk->pages_used = 0; + chunk->ndirty = 0; - /* - * Initialize the map to contain one maximal free untouched - * run. - */ - memset(chunk->map, (CHUNK_MAP_LARGE | CHUNK_MAP_POS_MASK), - arena_chunk_header_npages); - memset(&chunk->map[arena_chunk_header_npages], - (CHUNK_MAP_UNTOUCHED + /* Initialize the map to contain one maximal free untouched run. */ + memset(chunk->map, (CHUNK_MAP_LARGE | CHUNK_MAP_POS_MASK), + arena_chunk_header_npages); + memset(&chunk->map[arena_chunk_header_npages], (CHUNK_MAP_UNTOUCHED #ifdef MALLOC_DECOMMIT - | CHUNK_MAP_DECOMMITTED + | CHUNK_MAP_DECOMMITTED #endif - ), (chunk_npages - - arena_chunk_header_npages)); + ), (chunk_npages - + arena_chunk_header_npages)); - /* Initialize the tree of unused extent nodes. */ - extent_tree_ad_new(&chunk->nodes); - chunk->nodes_past = (extent_node_t *)QUANTUM_CEILING( - (uintptr_t)&chunk->map[chunk_npages]); + /* Initialize the tree of unused extent nodes. */ + extent_tree_ad_new(&chunk->nodes); + chunk->nodes_past = (extent_node_t *)QUANTUM_CEILING( + (uintptr_t)&chunk->map[chunk_npages]); #ifdef MALLOC_DECOMMIT - /* - * Start out decommitted, in order to force a closer - * correspondence between dirty pages and committed untouched - * pages. - */ - pages_decommit((void *)((uintptr_t)chunk + - (arena_chunk_header_npages << pagesize_2pow)), - ((chunk_npages - arena_chunk_header_npages) << - pagesize_2pow)); + /* + * Start out decommitted, in order to force a closer correspondence + * between dirty pages and committed untouched pages. + */ + pages_decommit((void *)((uintptr_t)chunk + + (arena_chunk_header_npages << pagesize_2pow)), + ((chunk_npages - arena_chunk_header_npages) << + pagesize_2pow)); # ifdef MALLOC_STATS - arena->stats.ndecommit++; - arena->stats.decommitted += (chunk_npages - - arena_chunk_header_npages); + arena->stats.ndecommit++; + arena->stats.decommitted += (chunk_npages - arena_chunk_header_npages); # endif #endif - } /* Insert the run into the runs_avail_* red-black trees. */ node = arena_chunk_node_alloc(chunk); @@ -3088,8 +3068,6 @@ arena_chunk_alloc(arena_t *arena) node->size = chunksize - (arena_chunk_header_npages << pagesize_2pow); extent_tree_szad_insert(&arena->runs_avail_szad, node); extent_tree_ad_insert(&arena->runs_avail_ad, node); - - return (chunk); } static void @@ -3097,21 +3075,6 @@ arena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk) { extent_node_t *node, key; - if (arena->spare != NULL) { - arena_chunk_tree_all_remove(&chunk->arena->chunks_all, - arena->spare); - if (arena->spare->ndirty > 0) { - arena_chunk_tree_dirty_remove( - &chunk->arena->chunks_dirty, arena->spare); - arena->ndirty -= arena->spare->ndirty; - } - VALGRIND_FREELIKE_BLOCK(arena->spare, 0); - chunk_dealloc((void *)arena->spare, chunksize); -#ifdef MALLOC_STATS - arena->stats.mapped -= chunksize; -#endif - } - /* * Remove run from the runs trees, regardless of whether this chunk * will be cached, so that the arena does not use it. Dirty page @@ -3126,7 +3089,18 @@ arena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk) extent_tree_ad_remove(&arena->runs_avail_ad, node); arena_chunk_node_dealloc(chunk, node); - arena->spare = chunk; + arena_chunk_tree_all_remove(&chunk->arena->chunks_all, + chunk); + if (chunk->ndirty > 0) { + arena_chunk_tree_dirty_remove( + &chunk->arena->chunks_dirty, chunk); + arena->ndirty -= chunk->ndirty; + } + VALGRIND_FREELIKE_BLOCK(chunk, 0); + chunk_dealloc((void *)chunk, chunksize); +#ifdef MALLOC_STATS + arena->stats.mapped -= chunksize; +#endif } static arena_run_t * @@ -3140,27 +3114,69 @@ arena_run_alloc(arena_t *arena, size_t size, bool small, bool zero) pagesize_2pow))); assert((size & pagesize_mask) == 0); - /* Search the arena's chunks for the lowest best fit. */ - key.addr = NULL; - key.size = size; - node = extent_tree_szad_nsearch(&arena->runs_avail_szad, &key); - if (node != NULL) { - run = (arena_run_t *)node->addr; + chunk = NULL; + while (true) { + /* Search the arena's chunks for the lowest best fit. */ + key.addr = NULL; + key.size = size; + node = extent_tree_szad_nsearch(&arena->runs_avail_szad, &key); + if (node != NULL) { + if (chunk != NULL) + chunk_dealloc(chunk, chunksize); + run = (arena_run_t *)node->addr; + arena_run_split(arena, run, size, small, zero); + return (run); + } + + /* + * No usable runs. Create a new chunk from which to allocate + * the run. + */ + if (chunk == NULL) { + uint64_t chunk_seq; + + /* + * Record the chunk allocation sequence number in order + * to detect races. + */ + arena->chunk_seq++; + chunk_seq = arena->chunk_seq; + + /* + * Drop the arena lock while allocating a chunk, since + * reserve notifications may cause recursive + * allocation. Dropping the lock here opens an + * allocataion race, but we recover. + */ + malloc_mutex_unlock(&arena->lock); + chunk = (arena_chunk_t *)chunk_alloc(chunksize, true, + true); + malloc_mutex_lock(&arena->lock); + + /* + * If this thread raced with another such that multiple + * chunks were allocated, make sure that there is still + * inadequate space before using this chunk. + */ + if (chunk_seq != arena->chunk_seq) + continue; + + /* + * Check for an error *after* checking for a race, + * since a race could also cause a transient OOM + * condition. + */ + if (chunk == NULL) + return (NULL); + } + + arena_chunk_init(arena, chunk); + run = (arena_run_t *)((uintptr_t)chunk + + (arena_chunk_header_npages << pagesize_2pow)); + /* Update page map. */ arena_run_split(arena, run, size, small, zero); return (run); } - - /* - * No usable runs. Create a new chunk from which to allocate the run. - */ - chunk = arena_chunk_alloc(arena); - if (chunk == NULL) - return (NULL); - run = (arena_run_t *)((uintptr_t)chunk + (arena_chunk_header_npages << - pagesize_2pow)); - /* Update page map. */ - arena_run_split(arena, run, size, small, zero); - return (run); } static void @@ -4496,10 +4512,11 @@ arena_new(arena_t *arena) memset(&arena->stats, 0, sizeof(arena_stats_t)); #endif + arena->chunk_seq = 0; + /* Initialize chunks. */ arena_chunk_tree_all_new(&arena->chunks_all); arena_chunk_tree_dirty_new(&arena->chunks_dirty); - arena->spare = NULL; arena->ndirty = 0; @@ -4627,7 +4644,7 @@ huge_malloc(size_t size, bool zero) if (node == NULL) return (NULL); - ret = chunk_alloc(csize, zero); + ret = chunk_alloc(csize, zero, true); if (ret == NULL) { base_node_dealloc(node); return (NULL); @@ -4695,6 +4712,7 @@ huge_palloc(size_t alignment, size_t size) size_t psize; #endif extent_node_t *node; + int pfd; /* * This allocation requires alignment that is even larger than chunk @@ -4718,19 +4736,30 @@ huge_palloc(size_t alignment, size_t size) if (node == NULL) return (NULL); -#ifdef MOZ_MEMORY_WINDOWS /* * Windows requires that there be a 1:1 mapping between VM * allocation/deallocation operations. Therefore, take care here to * acquire the final result via one mapping operation. + * + * The MALLOC_PAGEFILE code also benefits from this mapping algorithm, + * since it reduces the number of page files. */ +#ifdef MALLOC_PAGEFILE + if (opt_pagefile) { + pfd = pagefile_init(size); + if (pfd == -1) + return (NULL); + } else +#endif + pfd = -1; do { void *over; - over = chunk_alloc(alloc_size, false); + over = chunk_alloc(alloc_size, false, false); if (over == NULL) { base_node_dealloc(node); - return (NULL); + ret = NULL; + goto RETURN; } offset = (uintptr_t)over & (alignment - 1); @@ -4738,43 +4767,12 @@ huge_palloc(size_t alignment, size_t size) assert(offset < alloc_size); ret = (void *)((uintptr_t)over + offset); chunk_dealloc(over, alloc_size); - ret = pages_map(ret, chunk_size); + ret = pages_map(ret, chunk_size, pfd); /* * Failure here indicates a race with another thread, so try * again. */ } while (ret == NULL); -#else - ret = chunk_alloc(alloc_size, false); - if (ret == NULL) { - base_node_dealloc(node); - return (NULL); - } - - offset = (uintptr_t)ret & (alignment - 1); - assert((offset & chunksize_mask) == 0); - assert(offset < alloc_size); - if (offset == 0) { - /* Trim trailing space. */ - chunk_dealloc((void *)((uintptr_t)ret + chunk_size), alloc_size - - chunk_size); - } else { - size_t trailsize; - - /* Trim leading space. */ - chunk_dealloc(ret, alignment - offset); - - ret = (void *)((uintptr_t)ret + (alignment - offset)); - - trailsize = alloc_size - (alignment - offset) - chunk_size; - if (trailsize != 0) { - /* Trim trailing space. */ - assert(trailsize < alloc_size); - chunk_dealloc((void *)((uintptr_t)ret + chunk_size), - trailsize); - } - } -#endif /* Insert node into huge. */ node->addr = ret; @@ -4825,6 +4823,11 @@ huge_palloc(size_t alignment, size_t size) # endif #endif +RETURN: +#ifdef MALLOC_PAGEFILE + if (pfd != -1) + pagefile_close(pfd); +#endif return (ret); } @@ -4935,12 +4938,10 @@ huge_dalloc(void *ptr) malloc_mutex_unlock(&huge_mtx); /* Unmap chunk. */ -#ifdef MALLOC_DSS #ifdef MALLOC_FILL - if (opt_dss && opt_junk) + if (opt_junk) memset(node->addr, 0x5a, node->size); #endif -#endif #ifdef MALLOC_DECOMMIT chunk_dealloc(node->addr, CHUNK_CEILING(node->size)); #else @@ -5074,14 +5075,11 @@ malloc_print_stats(void) "\n", ""); _malloc_message("Boolean MALLOC_OPTIONS: ", opt_abort ? "A" : "a", "", ""); -#ifdef MALLOC_DSS - _malloc_message(opt_dss ? "D" : "d", "", "", ""); -#endif #ifdef MALLOC_FILL _malloc_message(opt_junk ? "J" : "j", "", "", ""); #endif -#ifdef MALLOC_DSS - _malloc_message(opt_mmap ? "M" : "m", "", "", ""); +#ifdef MALLOC_PAGEFILE + _malloc_message(opt_pagefile ? "o" : "O", "", "", ""); #endif _malloc_message("P", "", "", ""); #ifdef MALLOC_UTRACE @@ -5159,6 +5157,22 @@ malloc_print_stats(void) allocated, mapped); #endif + malloc_mutex_lock(&reserve_mtx); + malloc_printf("Reserve: min " + "cur max\n"); +#ifdef MOZ_MEMORY_WINDOWS + malloc_printf(" %12lu %12lu %12lu\n", + CHUNK_CEILING(reserve_min) >> opt_chunk_2pow, + reserve_cur >> opt_chunk_2pow, + reserve_max >> opt_chunk_2pow); +#else + malloc_printf(" %12zu %12zu %12zu\n", + CHUNK_CEILING(reserve_min) >> opt_chunk_2pow, + reserve_cur >> opt_chunk_2pow, + reserve_max >> opt_chunk_2pow); +#endif + malloc_mutex_unlock(&reserve_mtx); + #ifdef MALLOC_BALANCE malloc_printf("Arena balance reassignments: %llu\n", nbalance); @@ -5289,6 +5303,37 @@ malloc_init_hard(void) pagesize_mask = result - 1; pagesize_2pow = ffs((int)result) - 1; +#ifdef MALLOC_PAGEFILE + /* + * Determine where to create page files. It is insufficient to + * unconditionally use P_tmpdir (typically "/tmp"), since for some + * operating systems /tmp is a separate filesystem that is rather small. + * Therefore prefer, in order, the following locations: + * + * 1) MALLOC_TMPDIR + * 2) TMPDIR + * 3) P_tmpdir + */ + { + char *s; + size_t slen; + static const char suffix[] = "/jemalloc.XXXXXX"; + + if ((s = getenv("MALLOC_TMPDIR")) == NULL && (s = + getenv("TMPDIR")) == NULL) + s = P_tmpdir; + slen = strlen(s); + if (slen + sizeof(suffix) > sizeof(pagefile_templ)) { + _malloc_message(_getprogname(), + ": (malloc) Page file path too long\n", + "", ""); + abort(); + } + memcpy(pagefile_templ, s, slen); + memcpy(&pagefile_templ[slen], suffix, sizeof(suffix)); + } +#endif + for (i = 0; i < 3; i++) { unsigned j; @@ -5387,16 +5432,6 @@ MALLOC_OUT: else if ((opt_balance_threshold << 1) > opt_balance_threshold) opt_balance_threshold <<= 1; -#endif - break; - case 'd': -#ifdef MALLOC_DSS - opt_dss = false; -#endif - break; - case 'D': -#ifdef MALLOC_DSS - opt_dss = true; #endif break; case 'f': @@ -5408,6 +5443,12 @@ MALLOC_OUT: else if ((opt_dirty_max << 1) != 0) opt_dirty_max <<= 1; break; + case 'g': + opt_reserve_range_lshift--; + break; + case 'G': + opt_reserve_range_lshift++; + break; #ifdef MALLOC_FILL case 'j': opt_junk = false; @@ -5430,22 +5471,22 @@ MALLOC_OUT: (sizeof(size_t) << 3)) opt_chunk_2pow++; break; - case 'm': -#ifdef MALLOC_DSS - opt_mmap = false; -#endif - break; - case 'M': -#ifdef MALLOC_DSS - opt_mmap = true; -#endif - break; case 'n': opt_narenas_lshift--; break; case 'N': opt_narenas_lshift++; break; +#ifdef MALLOC_PAGEFILE + case 'o': + /* Do not over-commit. */ + opt_pagefile = true; + break; + case 'O': + /* Allow over-commit. */ + opt_pagefile = false; + break; +#endif case 'p': opt_print_stats = false; break; @@ -5461,6 +5502,12 @@ MALLOC_OUT: 1) opt_quantum_2pow++; break; + case 'r': + opt_reserve_min_lshift--; + break; + case 'R': + opt_reserve_min_lshift++; + break; case 's': if (opt_small_max_2pow > QUANTUM_2POW_MIN) @@ -5518,12 +5565,6 @@ MALLOC_OUT: } } -#ifdef MALLOC_DSS - /* Make sure that there is some method for acquiring memory. */ - if (opt_dss == false && opt_mmap == false) - opt_mmap = true; -#endif - /* Take care to call atexit() only once. */ if (opt_print_stats) { #ifndef MOZ_MEMORY_WINDOWS @@ -5592,14 +5633,6 @@ MALLOC_OUT: /* Initialize chunks data. */ malloc_mutex_init(&huge_mtx); extent_tree_ad_new(&huge); -#ifdef MALLOC_DSS - malloc_mutex_init(&dss_mtx); - dss_base = sbrk(0); - dss_prev = dss_base; - dss_max = dss_base; - extent_tree_szad_new(&dss_chunks_szad); - extent_tree_ad_new(&dss_chunks_ad); -#endif #ifdef MALLOC_STATS huge_nmalloc = 0; huge_ndalloc = 0; @@ -5609,17 +5642,9 @@ MALLOC_OUT: /* Initialize base allocation data structures. */ #ifdef MALLOC_STATS base_mapped = 0; -#endif -#ifdef MALLOC_DSS - /* - * Allocate a base chunk here, since it doesn't actually have to be - * chunk-aligned. Doing this before allocating any other chunks allows - * the use of space that would otherwise be wasted. - */ - if (opt_dss) - base_pages_alloc(0); #endif base_nodes = NULL; + base_reserve_regs = NULL; malloc_mutex_init(&base_mtx); #ifdef MOZ_MEMORY_NARENAS_DEFAULT_ONE @@ -5740,6 +5765,27 @@ MALLOC_OUT: malloc_spin_init(&arenas_lock); + /* + * Configure and initialize the memory reserve. This needs to happen + * late during initialization, since chunks are allocated. + */ + malloc_mutex_init(&reserve_mtx); + reserve_min = 0; + reserve_cur = 0; + reserve_max = chunksize * narenas; + if (RESERVE_RANGE_2POW_DEFAULT + opt_reserve_range_lshift >= 0) { + reserve_max += chunksize << (RESERVE_RANGE_2POW_DEFAULT + + opt_reserve_range_lshift); + } + ql_new(&reserve_regs); + reserve_seq = 0; + extent_tree_szad_new(&reserve_chunks_szad); + extent_tree_ad_new(&reserve_chunks_ad); + if (RESERVE_MIN_2POW_DEFAULT + opt_reserve_min_lshift >= 0) { + reserve_min_set(chunksize << (RESERVE_MIN_2POW_DEFAULT + + opt_reserve_min_lshift)); + } + malloc_initialized = true; #ifndef MOZ_MEMORY_WINDOWS malloc_mutex_unlock(&init_lock); @@ -6071,21 +6117,11 @@ jemalloc_stats(jemalloc_stats_t *stats) * Gather runtime settings. */ stats->opt_abort = opt_abort; - stats->opt_dss = -#ifdef MALLOC_DSS - opt_dss ? true : -#endif - false; stats->opt_junk = #ifdef MALLOC_FILL opt_junk ? true : #endif false; - stats->opt_mmap = -#ifdef MALLOC_DSS - opt_mmap == false ? false : -#endif - true; stats->opt_utrace = #ifdef MALLOC_UTRACE opt_utrace ? true : @@ -6120,6 +6156,12 @@ jemalloc_stats(jemalloc_stats_t *stats) stats->chunksize = chunksize; stats->dirty_max = opt_dirty_max; + malloc_mutex_lock(&reserve_mtx); + stats->reserve_min = reserve_min; + stats->reserve_max = reserve_max; + stats->reserve_cur = reserve_cur; + malloc_mutex_unlock(&reserve_mtx); + /* * Gather current memory usage statistics. */ @@ -6177,6 +6219,447 @@ jemalloc_stats(jemalloc_stats_t *stats) #endif } +void * +xmalloc(size_t size) +{ + void *ret; + + if (malloc_init()) + reserve_fail(size, "xmalloc"); + + if (size == 0) { +#ifdef MALLOC_SYSV + if (opt_sysv == false) +#endif + size = 1; +#ifdef MALLOC_SYSV + else { + _malloc_message(_getprogname(), + ": (malloc) Error in xmalloc(): ", + "invalid size 0", "\n"); + abort(); + } +#endif + } + + ret = imalloc(size); + if (ret == NULL) { + uint64_t seq = 0; + + do { + seq = reserve_crit(size, "xmalloc", seq); + ret = imalloc(size); + } while (ret == NULL); + } + + UTRACE(0, size, ret); + return (ret); +} + +void * +xcalloc(size_t num, size_t size) +{ + void *ret; + size_t num_size; + + num_size = num * size; + if (malloc_init()) + reserve_fail(num_size, "xcalloc"); + + if (num_size == 0) { +#ifdef MALLOC_SYSV + if ((opt_sysv == false) && ((num == 0) || (size == 0))) +#endif + num_size = 1; +#ifdef MALLOC_SYSV + else { + _malloc_message(_getprogname(), + ": (malloc) Error in xcalloc(): ", + "invalid size 0", "\n"); + abort(); + } +#endif + /* + * Try to avoid division here. We know that it isn't possible to + * overflow during multiplication if neither operand uses any of the + * most significant half of the bits in a size_t. + */ + } else if (((num | size) & (SIZE_T_MAX << (sizeof(size_t) << 2))) + && (num_size / size != num)) { + /* size_t overflow. */ + _malloc_message(_getprogname(), + ": (malloc) Error in xcalloc(): ", + "size overflow", "\n"); + abort(); + } + + ret = icalloc(num_size); + if (ret == NULL) { + uint64_t seq = 0; + + do { + seq = reserve_crit(num_size, "xcalloc", seq); + ret = icalloc(num_size); + } while (ret == NULL); + } + + UTRACE(0, num_size, ret); + return (ret); +} + +void * +xrealloc(void *ptr, size_t size) +{ + void *ret; + + if (size == 0) { +#ifdef MALLOC_SYSV + if (opt_sysv == false) +#endif + size = 1; +#ifdef MALLOC_SYSV + else { + if (ptr != NULL) + idalloc(ptr); + _malloc_message(_getprogname(), + ": (malloc) Error in xrealloc(): ", + "invalid size 0", "\n"); + abort(); + } +#endif + } + + if (ptr != NULL) { + assert(malloc_initialized); + + ret = iralloc(ptr, size); + if (ret == NULL) { + uint64_t seq = 0; + + do { + seq = reserve_crit(size, "xrealloc", seq); + ret = iralloc(ptr, size); + } while (ret == NULL); + } + } else { + if (malloc_init()) + reserve_fail(size, "xrealloc"); + + ret = imalloc(size); + if (ret == NULL) { + uint64_t seq = 0; + + do { + seq = reserve_crit(size, "xrealloc", seq); + ret = imalloc(size); + } while (ret == NULL); + } + } + + UTRACE(ptr, size, ret); + return (ret); +} + +void * +xmemalign(size_t alignment, size_t size) +{ + void *ret; + + assert(((alignment - 1) & alignment) == 0 && alignment >= + sizeof(void *)); + + if (malloc_init()) + reserve_fail(size, "xmemalign"); + + ret = ipalloc(alignment, size); + if (ret == NULL) { + uint64_t seq = 0; + + do { + seq = reserve_crit(size, "xmemalign", seq); + ret = ipalloc(alignment, size); + } while (ret == NULL); + } + + UTRACE(0, size, ret); + return (ret); +} + +static void +reserve_shrink(void) +{ + extent_node_t *node; + + assert(reserve_cur > reserve_max); +#ifdef MALLOC_DEBUG + { + extent_node_t *node; + size_t reserve_size; + + reserve_size = 0; + rb_foreach_begin(extent_node_t, link_szad, &reserve_chunks_szad, + node) { + reserve_size += node->size; + } rb_foreach_end(extent_node_t, link_szad, &reserve_chunks_szad, + node) + assert(reserve_size == reserve_cur); + + reserve_size = 0; + rb_foreach_begin(extent_node_t, link_ad, &reserve_chunks_ad, + node) { + reserve_size += node->size; + } rb_foreach_end(extent_node_t, link_ad, &reserve_chunks_ad, + node) + assert(reserve_size == reserve_cur); + } +#endif + + /* Discard chunks until the the reserve is below the size limit. */ + rb_foreach_reverse_begin(extent_node_t, link_ad, &reserve_chunks_ad, + node) { +#ifndef MALLOC_DECOMMIT + if (node->size <= reserve_cur - reserve_max) { +#endif + extent_node_t *tnode = extent_tree_ad_prev( + &reserve_chunks_ad, node); + +#ifdef MALLOC_DECOMMIT + assert(node->size <= reserve_cur - reserve_max); +#endif + + /* Discard the entire [multi-]chunk. */ + extent_tree_szad_remove(&reserve_chunks_szad, node); + extent_tree_ad_remove(&reserve_chunks_ad, node); + reserve_cur -= node->size; + pages_unmap(node->addr, node->size); + base_node_dealloc(node); + if (reserve_cur == reserve_max) + break; + + rb_foreach_reverse_prev(extent_node_t, link_ad, + extent_ad_comp, &reserve_chunks_ad, tnode); +#ifndef MALLOC_DECOMMIT + } else { + /* Discard the end of the multi-chunk. */ + extent_tree_szad_remove(&reserve_chunks_szad, node); + node->size -= reserve_cur - reserve_max; + extent_tree_szad_insert(&reserve_chunks_szad, node); + pages_unmap((void *)((uintptr_t)node->addr + + node->size), reserve_cur - reserve_max); + reserve_cur = reserve_max; + break; + } +#endif + assert(reserve_cur > reserve_max); + } rb_foreach_reverse_end(extent_node_t, link_ad, &reserve_chunks_ad, + node) +} + +/* Send a condition notification. */ +static uint64_t +reserve_notify(reserve_cnd_t cnd, size_t size, uint64_t seq) +{ + reserve_reg_t *reg; + + /* seq is used to keep track of distinct condition-causing events. */ + if (seq == 0) { + /* Allocate new sequence number. */ + reserve_seq++; + seq = reserve_seq; + } + + /* + * Advance to the next callback registration and send a notification, + * unless one has already been sent for this condition-causing event. + */ + reg = ql_first(&reserve_regs); + if (reg == NULL) + return (0); + ql_first(&reserve_regs) = ql_next(&reserve_regs, reg, link); + if (reg->seq == seq) + return (0); + reg->seq = seq; + malloc_mutex_unlock(&reserve_mtx); + reg->cb(reg->ctx, cnd, size); + malloc_mutex_lock(&reserve_mtx); + + return (seq); +} + +/* Allocation failure due to OOM. Try to free some memory via callbacks. */ +static uint64_t +reserve_crit(size_t size, const char *fname, uint64_t seq) +{ + + /* + * Send one condition notification. Iteration is handled by the + * caller of this function. + */ + malloc_mutex_lock(&reserve_mtx); + seq = reserve_notify(RESERVE_CND_CRIT, size, seq); + malloc_mutex_unlock(&reserve_mtx); + + /* If no notification could be sent, then no further recourse exists. */ + if (seq == 0) + reserve_fail(size, fname); + + return (seq); +} + +/* Permanent allocation failure due to OOM. */ +static void +reserve_fail(size_t size, const char *fname) +{ + uint64_t seq = 0; + + /* Send fail notifications. */ + malloc_mutex_lock(&reserve_mtx); + do { + seq = reserve_notify(RESERVE_CND_FAIL, size, seq); + } while (seq != 0); + malloc_mutex_unlock(&reserve_mtx); + + /* Terminate the application. */ + _malloc_message(_getprogname(), + ": (malloc) Error in ", fname, "(): out of memory\n"); + abort(); +} + +bool +reserve_cb_register(reserve_cb_t *cb, void *ctx) +{ + reserve_reg_t *reg = base_reserve_reg_alloc(); + if (reg == NULL) + return (true); + + ql_elm_new(reg, link); + reg->cb = cb; + reg->ctx = ctx; + reg->seq = 0; + + malloc_mutex_lock(&reserve_mtx); + ql_head_insert(&reserve_regs, reg, link); + malloc_mutex_unlock(&reserve_mtx); + + return (false); +} + +bool +reserve_cb_unregister(reserve_cb_t *cb, void *ctx) +{ + reserve_reg_t *reg = NULL; + + malloc_mutex_lock(&reserve_mtx); + ql_foreach(reg, &reserve_regs, link) { + if (reg->cb == cb && reg->ctx == ctx) { + ql_remove(&reserve_regs, reg, link); + break; + } + } + malloc_mutex_unlock(&reserve_mtx); + + if (reg != NULL) + base_reserve_reg_dealloc(reg); + return (false); + return (true); +} + +size_t +reserve_cur_get(void) +{ + size_t ret; + + malloc_mutex_lock(&reserve_mtx); + ret = reserve_cur; + malloc_mutex_unlock(&reserve_mtx); + + return (ret); +} + +size_t +reserve_min_get(void) +{ + size_t ret; + + malloc_mutex_lock(&reserve_mtx); + ret = reserve_min; + malloc_mutex_unlock(&reserve_mtx); + + return (ret); +} + +bool +reserve_min_set(size_t min) +{ + + min = CHUNK_CEILING(min); + + malloc_mutex_lock(&reserve_mtx); + /* Keep |reserve_max - reserve_min| the same. */ + if (min < reserve_min) { + reserve_max -= reserve_min - min; + reserve_min = min; + } else { + /* Protect against wrap-around. */ + if (reserve_max + min - reserve_min < reserve_max) { + reserve_min = SIZE_T_MAX - (reserve_max - reserve_min) + - chunksize + 1; + reserve_max = SIZE_T_MAX - chunksize + 1; + } else { + reserve_max += min - reserve_min; + reserve_min = min; + } + } + + /* Resize the reserve if necessary. */ + if (reserve_cur < reserve_min) { + size_t size = reserve_min - reserve_cur; + + /* Force the reserve to grow by allocating/deallocating. */ + malloc_mutex_unlock(&reserve_mtx); +#ifdef MALLOC_DECOMMIT + { + void **chunks; + size_t i, n; + + n = size >> opt_chunk_2pow; + chunks = imalloc(n * sizeof(void *)); + if (chunks == NULL) + return (true); + for (i = 0; i < n; i++) { + chunks[i] = huge_malloc(chunksize, false); + if (chunks[i] == NULL) { + size_t j; + + for (j = 0; j < i; j++) { + huge_dalloc(chunks[j]); + } + idalloc(chunks); + return (true); + } + } + for (i = 0; i < n; i++) + huge_dalloc(chunks[i]); + idalloc(chunks); + } +#else + { + void *x = huge_malloc(size, false); + if (x == NULL) { + return (true); + } + huge_dalloc(x); + } +#endif + } else if (reserve_cur > reserve_max) { + reserve_shrink(); + malloc_mutex_unlock(&reserve_mtx); + } else + malloc_mutex_unlock(&reserve_mtx); + + return (false); +} + #ifdef MOZ_MEMORY_WINDOWS void* _recalloc(void *ptr, size_t count, size_t size) @@ -6222,7 +6705,6 @@ _msize(const void *ptr) } #endif - /* * End non-standard functions. */ @@ -6251,10 +6733,6 @@ _malloc_prefork(void) malloc_mutex_lock(&base_mtx); malloc_mutex_lock(&huge_mtx); - -#ifdef MALLOC_DSS - malloc_mutex_lock(&dss_mtx); -#endif } void @@ -6264,10 +6742,6 @@ _malloc_postfork(void) /* Release all mutexes, now that fork() has completed. */ -#ifdef MALLOC_DSS - malloc_mutex_unlock(&dss_mtx); -#endif - malloc_mutex_unlock(&huge_mtx); malloc_mutex_unlock(&base_mtx); diff --git a/memory/jemalloc/jemalloc.h b/memory/jemalloc/jemalloc.h index da92f2fbd981..0c5b7c541442 100644 --- a/memory/jemalloc/jemalloc.h +++ b/memory/jemalloc/jemalloc.h @@ -19,9 +19,7 @@ typedef struct { * Run-time configuration settings. */ bool opt_abort; /* abort(3) on error? */ - bool opt_dss; /* Use sbrk(2) to map memory? */ bool opt_junk; /* Fill allocated/free memory with 0xa5/0x5a? */ - bool opt_mmap; /* Use mmap(2) to map memory? */ bool opt_utrace; /* Trace all allocation events? */ bool opt_sysv; /* SysV semantics? */ bool opt_xmalloc; /* abort(3) on OOM? */ @@ -33,6 +31,8 @@ typedef struct { size_t large_max; /* Max sub-chunksize allocation size. */ size_t chunksize; /* Size of each virtual memory mapping. */ size_t dirty_max; /* Max dirty pages per arena. */ + size_t reserve_min; /* reserve_low callback threshold. */ + size_t reserve_max; /* Maximum reserve size before unmapping. */ /* * Current memory usage statistics. @@ -41,6 +41,7 @@ typedef struct { size_t committed; /* Bytes committed (readable/writable). */ size_t allocated; /* Bytes allocted (in use by application). */ size_t dirty; /* Bytes dirty (committed unused pages). */ + size_t reserve_cur; /* Current memory reserve. */ } jemalloc_stats_t; #ifndef MOZ_MEMORY_DARWIN @@ -55,3 +56,122 @@ int posix_memalign(void **memptr, size_t alignment, size_t size); void *memalign(size_t alignment, size_t size); size_t malloc_usable_size(const void *ptr); void jemalloc_stats(jemalloc_stats_t *stats); + +/* The x*() functions never return NULL. */ +void *xmalloc(size_t size); +void *xcalloc(size_t num, size_t size); +void *xrealloc(void *ptr, size_t size); +void *xmemalign(size_t alignment, size_t size); + +/* + * The allocator maintains a memory reserve that is used to satisfy allocation + * requests when no additional memory can be acquired from the operating + * system. Under normal operating conditions, the reserve size is at least + * reserve_min bytes. If the reserve is depleted or insufficient to satisfy an + * allocation request, then condition notifications are sent to one or more of + * the registered callback functions: + * + * RESERVE_CND_LOW: The reserve had to be used to satisfy an allocation + * request, which dropped the reserve size below the + * minimum. The callee should try to free memory in order + * to restore the reserve. + * + * RESERVE_CND_CRIT: The reserve was not large enough to satisfy a pending + * allocation request. Some callee must free adequate + * memory in order to prevent application failure (unless + * the condition spontaneously desists due to concurrent + * deallocation). + * + * RESERVE_CND_FAIL: An allocation request could not be satisfied, despite all + * attempts. The allocator is about to terminate the + * application. + * + * The order in which the callback functions are called is only loosely + * specified: in the absence of interposing callback + * registrations/unregistrations, enabled callbacks will be called in an + * arbitrary round-robin order. + * + * Condition notifications are sent to callbacks only while conditions exist. + * For example, just before the allocator sends a RESERVE_CND_LOW condition + * notification to a callback, the reserve is in fact depleted. However, due + * to allocator concurrency, the reserve may have been restored by the time the + * callback function executes. Furthermore, if the reserve is restored at some + * point during the delivery of condition notifications to callbacks, no + * further deliveries will occur, since the condition no longer exists. + * + * Callback functions can freely call back into the allocator (i.e. the + * allocator releases all internal resources before calling each callback + * function), though allocation is discouraged, since recursive callbacks are + * likely to result, which places extra burden on the application to avoid + * deadlock. + * + * Callback functions must be thread-safe, since it is possible that multiple + * threads will call into the same callback function concurrently. + */ + +/* Memory reserve condition types. */ +typedef enum { + RESERVE_CND_LOW, + RESERVE_CND_CRIT, + RESERVE_CND_FAIL +} reserve_cnd_t; + +/* + * Reserve condition notification callback function type definition. + * + * Inputs: + * ctx: Opaque application data, as passed to reserve_cb_register(). + * cnd: Condition type being delivered. + * size: Allocation request size for the allocation that caused the condition. + */ +typedef void reserve_cb_t(void *ctx, reserve_cnd_t cnd, size_t size); + +/* + * Register a callback function. + * + * Inputs: + * cb: Callback function pointer. + * ctx: Opaque application data, passed to cb(). + * + * Output: + * ret: If true, failure due to OOM; success otherwise. + */ +bool reserve_cb_register(reserve_cb_t *cb, void *ctx); + +/* + * Unregister a callback function. + * + * Inputs: + * cb: Callback function pointer. + * ctx: Opaque application data, same as that passed to reserve_cb_register(). + * + * Output: + * ret: False upon success, true if the {cb,ctx} registration could not be + * found. + */ +bool reserve_cb_unregister(reserve_cb_t *cb, void *ctx); + +/* + * Get the current reserve size. + * + * ret: Current reserve size. + */ +size_t reserve_cur_get(void); + +/* + * Get the minimum acceptable reserve size. If the reserve drops below this + * value, the RESERVE_CND_LOW condition notification is sent to the callbacks. + * + * ret: Minimum acceptable reserve size. + */ +size_t reserve_min_get(void); + +/* + * Set the minimum acceptable reserve size. + * + * min: Reserve threshold. This value may be internally rounded up. + * ret: False if the reserve was successfully resized; true otherwise. Note + * that failure to resize the reserve also results in a RESERVE_CND_LOW + * condition. + */ +bool reserve_min_set(size_t min); diff --git a/memory/jemalloc/ql.h b/memory/jemalloc/ql.h new file mode 100644 index 000000000000..000cd2380c96 --- /dev/null +++ b/memory/jemalloc/ql.h @@ -0,0 +1,114 @@ +/****************************************************************************** + * + * Copyright (C) 2002 Jason Evans . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice(s), this list of conditions and the following disclaimer + * unmodified other than the allowable addition of one or more + * copyright notices. + * 2. Redistributions in binary form must reproduce the above copyright + * notice(s), this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + +/* + * List definitions. + */ +#define ql_head(a_type) \ +struct { \ + a_type *qlh_first; \ +} + +#define ql_head_initializer(a_head) {NULL} + +#define ql_elm(a_type) qr(a_type) + +/* List functions. */ +#define ql_new(a_head) do { \ + (a_head)->qlh_first = NULL; \ +} while (0) + +#define ql_elm_new(a_elm, a_field) qr_new((a_elm), a_field) + +#define ql_first(a_head) ((a_head)->qlh_first) + +#define ql_last(a_head, a_field) \ + ((ql_first(a_head) != NULL) \ + ? qr_prev(ql_first(a_head), a_field) : NULL) + +#define ql_next(a_head, a_elm, a_field) \ + ((ql_last(a_head, a_field) != (a_elm)) \ + ? qr_next((a_elm), a_field) : NULL) + +#define ql_prev(a_head, a_elm, a_field) \ + ((ql_first(a_head) != (a_elm)) ? qr_prev((a_elm), a_field) \ + : NULL) + +#define ql_before_insert(a_head, a_qlelm, a_elm, a_field) do { \ + qr_before_insert((a_qlelm), (a_elm), a_field); \ + if (ql_first(a_head) == (a_qlelm)) { \ + ql_first(a_head) = (a_elm); \ + } \ +} while (0) + +#define ql_after_insert(a_qlelm, a_elm, a_field) \ + qr_after_insert((a_qlelm), (a_elm), a_field) + +#define ql_head_insert(a_head, a_elm, a_field) do { \ + if (ql_first(a_head) != NULL) { \ + qr_before_insert(ql_first(a_head), (a_elm), a_field); \ + } \ + ql_first(a_head) = (a_elm); \ +} while (0) + +#define ql_tail_insert(a_head, a_elm, a_field) do { \ + if (ql_first(a_head) != NULL) { \ + qr_before_insert(ql_first(a_head), (a_elm), a_field); \ + } \ + ql_first(a_head) = qr_next((a_elm), a_field); \ +} while (0) + +#define ql_remove(a_head, a_elm, a_field) do { \ + if (ql_first(a_head) == (a_elm)) { \ + ql_first(a_head) = qr_next(ql_first(a_head), a_field); \ + } \ + if (ql_first(a_head) != (a_elm)) { \ + qr_remove((a_elm), a_field); \ + } else { \ + ql_first(a_head) = NULL; \ + } \ +} while (0) + +#define ql_head_remove(a_head, a_type, a_field) do { \ + a_type *t = ql_first(a_head); \ + ql_remove((a_head), t, a_field); \ +} while (0) + +#define ql_tail_remove(a_head, a_type, a_field) do { \ + a_type *t = ql_last(a_head, a_field); \ + ql_remove((a_head), t, a_field); \ +} while (0) + +#define ql_foreach(a_var, a_head, a_field) \ + qr_foreach((a_var), ql_first(a_head), a_field) + +#define ql_reverse_foreach(a_var, a_head, a_field) \ + qr_reverse_foreach((a_var), ql_first(a_head), a_field) diff --git a/memory/jemalloc/qr.h b/memory/jemalloc/qr.h new file mode 100644 index 000000000000..ee60491d7fdf --- /dev/null +++ b/memory/jemalloc/qr.h @@ -0,0 +1,98 @@ +/****************************************************************************** + * + * Copyright (C) 2002 Jason Evans . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice(s), this list of conditions and the following disclaimer + * unmodified other than the allowable addition of one or more + * copyright notices. + * 2. Redistributions in binary form must reproduce the above copyright + * notice(s), this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + +/* Ring definitions. */ +#define qr(a_type) \ +struct { \ + a_type *qre_next; \ + a_type *qre_prev; \ +} + +/* Ring functions. */ +#define qr_new(a_qr, a_field) do { \ + (a_qr)->a_field.qre_next = (a_qr); \ + (a_qr)->a_field.qre_prev = (a_qr); \ +} while (0) + +#define qr_next(a_qr, a_field) ((a_qr)->a_field.qre_next) + +#define qr_prev(a_qr, a_field) ((a_qr)->a_field.qre_prev) + +#define qr_before_insert(a_qrelm, a_qr, a_field) do { \ + (a_qr)->a_field.qre_prev = (a_qrelm)->a_field.qre_prev; \ + (a_qr)->a_field.qre_next = (a_qrelm); \ + (a_qr)->a_field.qre_prev->a_field.qre_next = (a_qr); \ + (a_qrelm)->a_field.qre_prev = (a_qr); \ +} while (0) + +#define qr_after_insert(a_qrelm, a_qr, a_field) \ + do \ + { \ + (a_qr)->a_field.qre_next = (a_qrelm)->a_field.qre_next; \ + (a_qr)->a_field.qre_prev = (a_qrelm); \ + (a_qr)->a_field.qre_next->a_field.qre_prev = (a_qr); \ + (a_qrelm)->a_field.qre_next = (a_qr); \ + } while (0) + +#define qr_meld(a_qr_a, a_qr_b, a_field) do { \ + void *t; \ + (a_qr_a)->a_field.qre_prev->a_field.qre_next = (a_qr_b); \ + (a_qr_b)->a_field.qre_prev->a_field.qre_next = (a_qr_a); \ + t = (a_qr_a)->a_field.qre_prev; \ + (a_qr_a)->a_field.qre_prev = (a_qr_b)->a_field.qre_prev; \ + (a_qr_b)->a_field.qre_prev = t; \ +} while (0) + +/* qr_meld() and qr_split() are functionally equivalent, so there's no need to + * have two copies of the code. */ +#define qr_split(a_qr_a, a_qr_b, a_field) \ + qr_meld((a_qr_a), (a_qr_b), a_field) + +#define qr_remove(a_qr, a_field) do { \ + (a_qr)->a_field.qre_prev->a_field.qre_next \ + = (a_qr)->a_field.qre_next; \ + (a_qr)->a_field.qre_next->a_field.qre_prev \ + = (a_qr)->a_field.qre_prev; \ + (a_qr)->a_field.qre_next = (a_qr); \ + (a_qr)->a_field.qre_prev = (a_qr); \ +} while (0) + +#define qr_foreach(var, a_qr, a_field) \ + for ((var) = (a_qr); \ + (var) != NULL; \ + (var) = (((var)->a_field.qre_next != (a_qr)) \ + ? (var)->a_field.qre_next : NULL)) + +#define qr_reverse_foreach(var, a_qr, a_field) \ + for ((var) = ((a_qr) != NULL) ? qr_prev(a_qr, a_field) : NULL; \ + (var) != NULL; \ + (var) = (((var) != (a_qr)) \ + ? (var)->a_field.qre_prev : NULL)) From 002301be5afaee0a03136c8fbf903e25efc58cfb Mon Sep 17 00:00:00 2001 From: Axel Hecht Date: Mon, 23 Jun 2008 17:57:26 +0200 Subject: [PATCH 64/66] bug 440431, hardcode en-US in Gran Paradiso branding, it's not localized anyway, r=ted, a=beltzner --- browser/branding/unofficial/locales/jar.mn | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/browser/branding/unofficial/locales/jar.mn b/browser/branding/unofficial/locales/jar.mn index 0ba09759c1a4..4d3e35507e39 100755 --- a/browser/branding/unofficial/locales/jar.mn +++ b/browser/branding/unofficial/locales/jar.mn @@ -2,5 +2,6 @@ @AB_CD@.jar: % locale branding @AB_CD@ %locale/branding/ - locale/branding/brand.dtd (%brand.dtd) -* locale/branding/brand.properties (%brand.properties) +# Gran Paradiso branding only exists in en-US + locale/branding/brand.dtd (en-US/brand.dtd) +* locale/branding/brand.properties (en-US/brand.properties) From 074b6644f690a4f4959234fb64c4292f45cce5e5 Mon Sep 17 00:00:00 2001 From: Robert Strong Date: Mon, 23 Jun 2008 12:06:37 -0700 Subject: [PATCH 65/66] Bug 437349 - updater.exe lacks elevation manifest and fails to start when installer detection is disabled r=jmathies r=ted.mielczarek --- .../mozapps/update/src/updater/updater.cpp | 96 ++++++++++++++++++- .../update/src/updater/updater.exe.manifest | 8 ++ toolkit/xre/nsAppRunner.cpp | 7 +- toolkit/xre/nsUpdateDriver.cpp | 2 +- 4 files changed, 106 insertions(+), 7 deletions(-) diff --git a/toolkit/mozapps/update/src/updater/updater.cpp b/toolkit/mozapps/update/src/updater/updater.cpp index b04446435ee4..d6d74609e0da 100644 --- a/toolkit/mozapps/update/src/updater/updater.cpp +++ b/toolkit/mozapps/update/src/updater/updater.cpp @@ -21,6 +21,7 @@ * * Contributor(s): * Darin Fisher + * Robert Strong * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -1101,7 +1102,7 @@ LaunchWinPostProcess(const WCHAR *appExe) L"\0" }; - WinLaunchChild(exefullpath, argc, argv, 1); + WinLaunchChild(exefullpath, argc, argv, 0); free(argv); } #endif @@ -1120,7 +1121,7 @@ LaunchCallbackApp(const NS_tchar *workingDir, int argc, NS_tchar **argv) #elif defined(XP_MACOSX) LaunchChild(argc, argv); #elif defined(XP_WIN) - WinLaunchChild(argv[0], argc, argv, -1); + WinLaunchChild(argv[0], argc, argv, 0); #else # warning "Need implementaton of LaunchCallbackApp" #endif @@ -1212,6 +1213,91 @@ int NS_main(int argc, NS_tchar **argv) #endif } +#ifdef XP_WIN + // Launch a second instance of the updater with the runas verb on Windows + // when write access is denied to the installation directory. + + NS_tchar updateLockFilePath[MAXPATHLEN]; + NS_tsnprintf(updateLockFilePath, MAXPATHLEN, + NS_T("%s/update_in_progress.lock"), argv[3]); + + // The update_in_progress.lock file should only exist during an update. In + // case it exists attempt to remove it and exit if that fails to prevent + // simultaneous updates occurring. + if (!_waccess(updateLockFilePath, F_OK) && + NS_tremove(updateLockFilePath) != 0) { + fprintf(stderr, "Update already in progress! Exiting\n"); + return 1; + } + + HANDLE updateLockFileHandle; + updateLockFileHandle = CreateFileW(updateLockFilePath, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + OPEN_ALWAYS, + FILE_FLAG_DELETE_ON_CLOSE, + NULL); + + NS_tchar elevatedLockFilePath[MAXPATHLEN]; + NS_tsnprintf(elevatedLockFilePath, MAXPATHLEN, + NS_T("%s/update_elevated.lock"), argv[1]); + + if (updateLockFileHandle == INVALID_HANDLE_VALUE) { + if (!_waccess(elevatedLockFilePath, F_OK) && + NS_tremove(elevatedLockFilePath) != 0) { + fprintf(stderr, "Update already elevated! Exiting\n"); + return 1; + } + + HANDLE elevatedFileHandle; + elevatedFileHandle = CreateFileW(elevatedLockFilePath, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + OPEN_ALWAYS, + FILE_FLAG_DELETE_ON_CLOSE, + NULL); + + if (elevatedFileHandle == INVALID_HANDLE_VALUE) { + fprintf(stderr, "Unable to create elevated lock file! Exiting\n"); + return 1; + } + + PRUnichar *cmdLine = MakeCommandLine(argc - 1, argv + 1); + if (!cmdLine) { + CloseHandle(elevatedFileHandle); + return 1; + } + + SHELLEXECUTEINFO sinfo; + memset(&sinfo, 0, sizeof(SHELLEXECUTEINFO)); + sinfo.cbSize = sizeof(SHELLEXECUTEINFO); + sinfo.fMask = SEE_MASK_NOASYNC | + SEE_MASK_FLAG_NO_UI | + SEE_MASK_NOCLOSEPROCESS; + sinfo.hwnd = NULL; + sinfo.lpFile = argv[0]; + sinfo.lpParameters = cmdLine; + sinfo.lpVerb = L"runas"; + sinfo.nShow = SW_SHOWNORMAL; + + BOOL result = ShellExecuteEx(&sinfo); + free(cmdLine); + + if (result) { + WaitForSingleObject(sinfo.hProcess, INFINITE); + CloseHandle(sinfo.hProcess); + } + + if (argc > 4) + LaunchCallbackApp(argv[3], argc - 4, argv + 4); + + CloseHandle(elevatedFileHandle); + return 0; + } +#endif + gSourcePath = argv[1]; LogInit(); @@ -1229,6 +1315,12 @@ int NS_main(int argc, NS_tchar **argv) #ifdef XP_WIN if (gSucceeded && argc > 4) LaunchWinPostProcess(argv[4]); + CloseHandle(updateLockFileHandle); + // If elevated return early and let the process that launched this process + // launch the callback application. + if (!_waccess(elevatedLockFilePath, F_OK) && + NS_tremove(elevatedLockFilePath) != 0) + return 0; #endif // The callback to execute is given as the last N arguments of our command diff --git a/toolkit/mozapps/update/src/updater/updater.exe.manifest b/toolkit/mozapps/update/src/updater/updater.exe.manifest index 4c50f9dc1567..8bea07a34b22 100644 --- a/toolkit/mozapps/update/src/updater/updater.exe.manifest +++ b/toolkit/mozapps/update/src/updater/updater.exe.manifest @@ -19,4 +19,12 @@ /> + + + + + + + + diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index 67916fdca587..79f0c136c7bf 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -1544,8 +1544,7 @@ int OS2LaunchChild(const char *aExePath, int aArgc, char **aArgv) // blank command line instead of being launched with the same command line that // it was initially started with. static nsresult LaunchChild(nsINativeAppSupport* aNative, - PRBool aBlankCommandLine = PR_FALSE, - int needElevation = 0) + PRBool aBlankCommandLine = PR_FALSE) { aNative->Quit(); // release DDE mutex, if we're holding it @@ -1573,7 +1572,7 @@ static nsresult LaunchChild(nsINativeAppSupport* aNative, if (NS_FAILED(rv)) return rv; - if (!WinLaunchChild(exePath.get(), gRestartArgc, gRestartArgv, needElevation)) + if (!WinLaunchChild(exePath.get(), gRestartArgc, gRestartArgv, 0)) return NS_ERROR_FAILURE; #else @@ -3275,7 +3274,7 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData) MOZ_gdk_display_close(display); #endif - rv = LaunchChild(nativeApp, appInitiatedRestart, upgraded ? -1 : 0); + rv = LaunchChild(nativeApp, appInitiatedRestart); #ifdef MOZ_CRASHREPORTER if (appData.flags & NS_XRE_ENABLE_CRASH_REPORTER) diff --git a/toolkit/xre/nsUpdateDriver.cpp b/toolkit/xre/nsUpdateDriver.cpp index 8084e07f2bf8..4e2dfb3855bb 100644 --- a/toolkit/xre/nsUpdateDriver.cpp +++ b/toolkit/xre/nsUpdateDriver.cpp @@ -474,7 +474,7 @@ ApplyUpdate(nsIFile *greDir, nsIFile *updateDir, nsILocalFile *statusFile, #elif defined(XP_WIN) _wchdir(applyToDir.get()); - if (!WinLaunchChild(updaterPathW.get(), appArgc + 4, argv, 1)) + if (!WinLaunchChild(updaterPathW.get(), appArgc + 4, argv, 0)) return; _exit(0); #else From 8c89e4f74087d6cf978f444c294a1283d7a829ae Mon Sep 17 00:00:00 2001 From: Axel Hecht Date: Mon, 23 Jun 2008 21:26:26 +0200 Subject: [PATCH 66/66] bug 440675, add USE_EXTENSION_MANIFEST coveragae to jar.mn tests, r=ted --- config/Makefile.in | 1 + config/tests/chrome.manifest.flat | 4 ++++ config/tests/src-simple/Makefile.in | 5 ++++- 3 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 config/tests/chrome.manifest.flat diff --git a/config/Makefile.in b/config/Makefile.in index 2cdc1c4a2e2e..9f162468de3c 100644 --- a/config/Makefile.in +++ b/config/Makefile.in @@ -166,6 +166,7 @@ check-preprocessor:: check-jar-mn:: make -C tests/src-simple check-jar make -C tests/src-simple check-flat + make -C tests/src-simple check-flat USE_EXTENSION_MANIFEST=1 ifneq ($(OS_ARCH), WINNT) make -C tests/src-simple check-symlink endif diff --git a/config/tests/chrome.manifest.flat b/config/tests/chrome.manifest.flat new file mode 100644 index 000000000000..4e3a144f3f9f --- /dev/null +++ b/config/tests/chrome.manifest.flat @@ -0,0 +1,4 @@ +content test chrome/test/one xpcnativewrappers=no +locale ab-X-stuff chrome/test/three +overlay chrome://one/file.xml chrome://two/otherfile.xml +skin test classic chrome/test/one diff --git a/config/tests/src-simple/Makefile.in b/config/tests/src-simple/Makefile.in index 2d75e00cce1c..5c33a50583d2 100644 --- a/config/tests/src-simple/Makefile.in +++ b/config/tests/src-simple/Makefile.in @@ -52,11 +52,14 @@ DEFINES += \ -DAB_CD=ab-X-stuff \ $(NULL) +MY_MANIFEST = $(if $(USE_EXTENSION_MANIFEST), $(FINAL_TARGET)/chrome.manifest, $(FINAL_TARGET)/chrome/test.manifest) +REF_MANIFEST = $(if $(USE_EXTENSION_MANIFEST),chrome.manifest,test.manifest) + check-%:: if test -d $(FINAL_TARGET); then rm -rf $(FINAL_TARGET); fi; make realchrome MOZ_CHROME_FILE_FORMAT=$* @echo "Comparing manifests..." - @if ! sort $(FINAL_TARGET)/chrome/test.manifest | diff -u $(srcdir)/../test.manifest.$* - ; then \ + @if ! sort $(MY_MANIFEST) | diff -u $(srcdir)/../$(REF_MANIFEST).$* - ; then \ echo "FAIL: different content in manifest!" ; \ fi @if [ $* == "jar" ]; then \