aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/analyzer.js2
-rw-r--r--src/intertyper.js2
-rw-r--r--src/library.js37
-rw-r--r--src/library_sdl.js60
-rw-r--r--src/long.js11
-rw-r--r--src/relooper/Relooper.cpp72
-rw-r--r--src/relooper/fuzzer.py4
-rw-r--r--src/relooper/test.txt4
8 files changed, 154 insertions, 38 deletions
diff --git a/src/analyzer.js b/src/analyzer.js
index ecb5ea6b..dbbb267d 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -1380,7 +1380,7 @@ function analyzer(data, sidePass) {
var label = func.labels[i];
for (var j = 0; j < label.lines.length; j++) {
var line = label.lines[j];
- if (line.intertype == 'call' && line.ident == setjmp) {
+ if ((line.intertype == 'call' || line.intertype == 'invoke') && line.ident == setjmp) {
// Add a new label
var oldIdent = label.ident;
var newIdent = func.labelIdCounter++;
diff --git a/src/intertyper.js b/src/intertyper.js
index 6c88e765..2103ecfa 100644
--- a/src/intertyper.js
+++ b/src/intertyper.js
@@ -677,7 +677,7 @@ function intertyper(data, sidePass, baseLineNums) {
item.type = item.tokens[1].text;
Types.needAnalysis[item.type] = 0;
while (['@', '%'].indexOf(item.tokens[2].text[0]) == -1 && !(item.tokens[2].text in PARSABLE_LLVM_FUNCTIONS) &&
- item.tokens[2].text != 'null' && item.tokens[2].text != 'asm') {
+ item.tokens[2].text != 'null' && item.tokens[2].text != 'asm' && item.tokens[2].text != 'undef') {
assert(item.tokens[2].text != 'asm', 'Inline assembly cannot be compiled to JavaScript!');
item.tokens.splice(2, 1);
}
diff --git a/src/library.js b/src/library.js
index a288b739..848a2571 100644
--- a/src/library.js
+++ b/src/library.js
@@ -3670,6 +3670,17 @@ LibraryManager.library = {
abs: 'Math.abs',
labs: 'Math.abs',
+#if USE_TYPED_ARRAYS == 2
+ llabs__deps: [function() { Types.preciseI64MathUsed = 1 }],
+ llabs: function(lo, hi) {
+ i64Math.abs(lo, hi);
+ {{{ makeStructuralReturn([makeGetTempDouble(0, 'i32'), makeGetTempDouble(1, 'i32')]) }}};
+ },
+#else
+ llabs: function(lo, hi) {
+ throw 'unsupported llabs';
+ },
+#endif
exit__deps: ['_exit'],
exit: function(status) {
@@ -5507,6 +5518,14 @@ LibraryManager.library = {
return -a;
},
copysignf: 'copysign',
+ __signbit__deps: ['copysign'],
+ __signbit: function(x) {
+ // We implement using copysign so that we get support
+ // for negative zero (once copysign supports that).
+ return _copysign(1.0, x) < 0;
+ },
+ __signbitf: '__signbit',
+ __signbitd: '__signbit',
hypot: function(a, b) {
return Math.sqrt(a*a + b*b);
},
@@ -6703,6 +6722,13 @@ LibraryManager.library = {
},
// ==========================================================================
+ // sched.h (stubs only - no thread support yet!)
+ // ==========================================================================
+ sched_yield: function() {
+ return 0;
+ },
+
+ // ==========================================================================
// pthread.h (stubs for mutexes only - no thread support yet!)
// ==========================================================================
@@ -6718,8 +6744,15 @@ LibraryManager.library = {
},
pthread_cond_init: function() {},
pthread_cond_destroy: function() {},
- pthread_cond_broadcast: function() {},
- pthread_cond_wait: function() {},
+ pthread_cond_broadcast: function() {
+ return 0;
+ },
+ pthread_cond_wait: function() {
+ return 0;
+ },
+ pthread_cond_timedwait: function() {
+ return 0;
+ },
pthread_self: function() {
//FIXME: assumes only a single thread
return 0;
diff --git a/src/library_sdl.js b/src/library_sdl.js
index 96ae6fa2..d707a8bf 100644
--- a/src/library_sdl.js
+++ b/src/library_sdl.js
@@ -1463,10 +1463,70 @@ var LibrarySDL = {
return (SDL.music.audio && !SDL.music.audio.paused) ? 1 : 0;
},
+ // http://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer_38.html#SEC38
+ // "Note: Does not check if the channel has been paused."
+ Mix_Playing: function(id) {
+ if (id === -1) {
+ var count = 0;
+ for (var i = 0; i < SDL.audios.length; i++) {
+ count += SDL.Mix_Playing(i);
+ }
+ return count;
+ }
+ var info = SDL.audios[id];
+ if (info && info.audio && !info.audio.paused) {
+ return 1;
+ }
+ return 0;
+ },
+
+ Mix_Pause: function(id) {
+ if (id === -1) {
+ for (var i = 0; i<SDL.audios.length;i++) {
+ SDL.Mix_Pause(i);
+ }
+ return;
+ }
+ var info = SDL.audios[id];
+ if (info && info.audio) {
+ info.audio.pause();
+ }
+ },
+
+ // http://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer_39.html#SEC39
+ Mix_Paused: function(id) {
+ if (id === -1) {
+ var pausedCount = 0;
+ for (var i = 0; i<SDL.audios.length;i++) {
+ pausedCount += SDL.Mix_Paused(i);
+ }
+ return pausedCount;
+ }
+ var info = SDL.audios[id];
+ if (info && info.audio && info.audio.paused) {
+ return 1;
+ }
+ return 0;
+ },
+
Mix_PausedMusic: function() {
return (SDL.music.audio && SDL.music.audio.paused) ? 1 : 0;
},
+ // http://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer_33.html#SEC33
+ Mix_Resume: function(id) {
+ if (id === -1) {
+ for (var i = 0; i<SDL.audios.length;i++) {
+ SDL.Mix_Resume(i);
+ }
+ return;
+ }
+ var info = SDL.audios[id];
+ if (info && info.audio) {
+ info.audio.play();
+ }
+ },
+
// SDL TTF
TTF_Init: function() { return 0 },
diff --git a/src/long.js b/src/long.js
index c3b0e605..c3651bd9 100644
--- a/src/long.js
+++ b/src/long.js
@@ -1551,6 +1551,17 @@ var i64Math = (function() { // Emscripten wrapper
HEAP32[tempDoublePtr>>2] = ret.low_;
HEAP32[tempDoublePtr+4>>2] = ret.high_;
},
+ abs: function(l, h) {
+ var x = new goog.math.Long(l, h);
+ var ret;
+ if (x.isNegative()) {
+ ret = x.negate();
+ } else {
+ ret = x;
+ }
+ HEAP32[tempDoublePtr>>2] = ret.low_;
+ HEAP32[tempDoublePtr+4>>2] = ret.high_;
+ },
ensureTemps: function() {
if (Wrapper.ensuredTemps) return;
Wrapper.ensuredTemps = true;
diff --git a/src/relooper/Relooper.cpp b/src/relooper/Relooper.cpp
index 1a7acc15..ae393de3 100644
--- a/src/relooper/Relooper.cpp
+++ b/src/relooper/Relooper.cpp
@@ -347,17 +347,25 @@ struct RelooperRecursor {
RelooperRecursor(Relooper *ParentInit) : Parent(ParentInit) {}
};
+typedef std::list<Block*> BlockList;
+
void Relooper::Calculate(Block *Entry) {
// Scan and optimize the input
struct PreOptimizer : public RelooperRecursor {
PreOptimizer(Relooper *Parent) : RelooperRecursor(Parent) {}
BlockSet Live;
- void FindLive(Block *Curr) {
- if (Live.find(Curr) != Live.end()) return;
- Live.insert(Curr);
- for (BlockBranchMap::iterator iter = Curr->BranchesOut.begin(); iter != Curr->BranchesOut.end(); iter++) {
- FindLive(iter->first);
+ void FindLive(Block *Root) {
+ BlockList ToInvestigate;
+ ToInvestigate.push_back(Root);
+ while (ToInvestigate.size() > 0) {
+ Block *Curr = ToInvestigate.front();
+ ToInvestigate.pop_front();
+ if (Live.find(Curr) != Live.end()) continue;
+ Live.insert(Curr);
+ for (BlockBranchMap::iterator iter = Curr->BranchesOut.begin(); iter != Curr->BranchesOut.end(); iter++) {
+ ToInvestigate.push_back(iter->first);
+ }
}
}
@@ -529,7 +537,6 @@ void Relooper::Calculate(Block *Entry) {
// ignore directly reaching the entry itself by another entry.
void FindIndependentGroups(BlockSet &Blocks, BlockSet &Entries, BlockBlockSetMap& IndependentGroups) {
typedef std::map<Block*, Block*> BlockBlockMap;
- typedef std::list<Block*> BlockList;
struct HelperClass {
BlockBlockSetMap& IndependentGroups;
@@ -872,33 +879,38 @@ void Relooper::Calculate(Block *Entry) {
// A flow operation is trivially unneeded if the shape we naturally get to by normal code
// execution is the same as the flow forces us to.
void RemoveUnneededFlows(Shape *Root, Shape *Natural=NULL) {
- SHAPE_SWITCH(Root, {
- // If there is a next block, we already know at Simple creation time to make direct branches,
- // and we can do nothing more. If there is no next however, then Natural is where we will
- // go to by doing nothing, so we can potentially optimize some branches to direct.
- if (Simple->Next) {
- RemoveUnneededFlows(Simple->Next, Natural);
- } else {
- for (BlockBranchMap::iterator iter = Simple->Inner->ProcessedBranchesOut.begin(); iter != Simple->Inner->ProcessedBranchesOut.end(); iter++) {
- Block *Target = iter->first;
- Branch *Details = iter->second;
- if (Details->Type != Branch::Direct && Target->Parent == Natural) {
- Details->Type = Branch::Direct;
- if (MultipleShape *Multiple = Shape::IsMultiple(Details->Ancestor)) {
- Multiple->NeedLoop--;
+ Shape *Next = Root;
+ while (Next) {
+ Root = Next;
+ Next = NULL;
+ SHAPE_SWITCH(Root, {
+ // If there is a next block, we already know at Simple creation time to make direct branches,
+ // and we can do nothing more. If there is no next however, then Natural is where we will
+ // go to by doing nothing, so we can potentially optimize some branches to direct.
+ if (Simple->Next) {
+ Next = Simple->Next;
+ } else {
+ for (BlockBranchMap::iterator iter = Simple->Inner->ProcessedBranchesOut.begin(); iter != Simple->Inner->ProcessedBranchesOut.end(); iter++) {
+ Block *Target = iter->first;
+ Branch *Details = iter->second;
+ if (Details->Type != Branch::Direct && Target->Parent == Natural) {
+ Details->Type = Branch::Direct;
+ if (MultipleShape *Multiple = Shape::IsMultiple(Details->Ancestor)) {
+ Multiple->NeedLoop--;
+ }
}
}
}
- }
- }, {
- for (BlockShapeMap::iterator iter = Multiple->InnerMap.begin(); iter != Multiple->InnerMap.end(); iter++) {
- RemoveUnneededFlows(iter->second, Multiple->Next);
- }
- RemoveUnneededFlows(Multiple->Next, Natural);
- }, {
- RemoveUnneededFlows(Loop->Inner, Loop->Inner);
- RemoveUnneededFlows(Loop->Next, Natural);
- });
+ }, {
+ for (BlockShapeMap::iterator iter = Multiple->InnerMap.begin(); iter != Multiple->InnerMap.end(); iter++) {
+ RemoveUnneededFlows(iter->second, Multiple->Next);
+ }
+ Next = Multiple->Next;
+ }, {
+ RemoveUnneededFlows(Loop->Inner, Loop->Inner);
+ Next = Loop->Next;
+ });
+ }
}
// After we know which loops exist, we can calculate which need to be labeled
diff --git a/src/relooper/fuzzer.py b/src/relooper/fuzzer.py
index 887eab3b..96929028 100644
--- a/src/relooper/fuzzer.py
+++ b/src/relooper/fuzzer.py
@@ -98,14 +98,14 @@ int main() {
open('fuzz.slow.js', 'w').write(slow)
open('fuzz.cpp', 'w').write(fast)
print '_'
- slow_out = subprocess.Popen(['/home/alon/Dev/mozilla-central/js/src/fast/js', '-m', '-n', 'fuzz.slow.js'], stdout=subprocess.PIPE).communicate()[0]
+ slow_out = subprocess.Popen(['/home/alon/Dev/odinmonkey/js/src/fast/js', '-m', '-n', 'fuzz.slow.js'], stdout=subprocess.PIPE).communicate()[0]
print '.'
subprocess.call(['g++', 'fuzz.cpp', 'Relooper.o', '-o', 'fuzz', '-g'])
print '*'
subprocess.call(['./fuzz'], stdout=open('fuzz.fast.js', 'w'))
print '-'
- fast_out = subprocess.Popen(['/home/alon/Dev/mozilla-central/js/src/fast/js', '-m', '-n', 'fuzz.fast.js'], stdout=subprocess.PIPE).communicate()[0]
+ fast_out = subprocess.Popen(['/home/alon/Dev/odinmonkey/js/src/fast/js', '-m', '-n', 'fuzz.fast.js'], stdout=subprocess.PIPE).communicate()[0]
print
if slow_out != fast_out:
diff --git a/src/relooper/test.txt b/src/relooper/test.txt
index b7c8794d..12d0ef39 100644
--- a/src/relooper/test.txt
+++ b/src/relooper/test.txt
@@ -54,7 +54,7 @@ while(1) {
// code 2
if (!($2)) {
var $x_1 = $x_0;
- label = 19;
+ label = 18;
break;
}
// code 3
@@ -64,7 +64,7 @@ while(1) {
var $i_0 = $7;var $x_0 = $5;
}
}
-if (label == 19) {
+if (label == 18) {
// code 7
}
// code 4