15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#!/usr/bin/perl -w
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# Copyright (C) 2007 Apple Inc. All rights reserved.
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# Redistribution and use in source and binary forms, with or without
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# modification, are permitted provided that the following conditions
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# are met:
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# 1. Redistributions of source code must retain the above copyright
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#    notice, this list of conditions and the following disclaimer.
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# 2. Redistributions in binary form must reproduce the above copyright
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#    notice, this list of conditions and the following disclaimer in the
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#    documentation and/or other materials provided with the distribution.
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)use strict;
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)use Getopt::Long;
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)use File::Basename;
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $showHelp = 0;
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $jsShellPath;
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $suite = "";
335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $ubench = 0;
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $v8suite = 0;
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $parseOnly = 0;
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $programName = basename($0);
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $usage = <<EOF;
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Usage: $programName --shell=[path] [options] FILE FILE
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  --help        Show this help message
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  --shell       Path to javascript shell
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  --suite           Select a specific benchmark suite. The default is sunspider-1.0
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  --ubench          Use microbenchmark suite instead of regular tests. Same as --suite=ubench
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  --v8-suite        Use the V8 benchmark suite. Same as --suite=v8-v4
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  --parse-only  Compare the parse-only benchmark results
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)EOF
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)GetOptions('shell=s' => \$jsShellPath,
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)           'suite=s' => \$suite,
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)           'ubench' => \$ubench,
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)           'v8-suite' => \$v8suite,
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)           'parse-only' => \$parseOnly,
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)           'help' => \$showHelp);
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)$suite = "ubench" if ($ubench);
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)$suite = "v8-v4" if ($v8suite);
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)$suite = "parse-only" if ($parseOnly);
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)$suite = "sunspider-1.0" if (!$suite);
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $resultDirectory = "${suite}-results";
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)if ((scalar @ARGV != 0 && scalar @ARGV != 2) || !$jsShellPath || $showHelp) {
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   print STDERR $usage;
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   exit 1;
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub readResultsFile($)
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    my ($filename) = @_;
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    open FILE, "<", $filename or die;
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    my $foundStart = 0;
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    my $foundOutput = 0;
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    my $foundEnd = 0;
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    my $result = "";
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (<FILE>) {
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!$foundStart) {
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (/^\[\{$/) {
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                $foundStart = 1;
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                $result .= $_;
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            } elsif (/^var \w+ = \[$/) {
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                $foundOutput = 1;
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            } elsif ($foundOutput && /^\{$/) {
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                $foundOutput = 0;
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                $foundStart = 1;
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                $result = "[{\n";
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else {
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (/\];?$/) {
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                $foundEnd = 1;
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                chomp;
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                s/;$//;
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                $result .= $_;
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                last;
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            } else {
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                $result .= $_;
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } 
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    close FILE;
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    die "Cound not find data in ${filename} - needs to start with [{" unless $foundStart;
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    die "Cound not find data in ${filename} - needs to end with }]" unless $foundEnd;
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return $result;
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub dumpToFile($$)
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    my ($contents, $path) = @_;
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    open FILE, ">", $path or die;
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    print FILE $contents;
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    close FILE;
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub readFile($)
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    my ($path) = @_;
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    open FILE, "<", $path or die;
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    my $result = <FILE>;
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    close FILE;
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return $result;
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub newestFile($$)
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    my ($dir, $pattern) = @_;
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    my $newestAge;
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    my $newestFile = "";
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    opendir DIR, $dir or die;
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for my $file (readdir DIR) {
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if ($file =~ $pattern) {
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            my $age = -M "$dir/$file";
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!defined $newestAge || $age < $newestAge) {
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                $newestFile = $file;
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                $newestAge = $age;
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    closedir DIR;
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return "$dir/$newestFile";
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $file1;
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $file2;
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)if (scalar @ARGV == 2) {
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    $file1 = $ARGV[0];
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    $file2 = $ARGV[1];
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} else {
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    $file1 = readFile("$resultDirectory/baseline-filename.txt");
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    $file2 = newestFile("$resultDirectory", qr/sunspider-results-.+\.js$/);
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $output = "var output1 = " . readResultsFile($file1) . ";\n";
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)$output .= "var output2 = " . readResultsFile($file2) . ";\n";
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)dumpToFile($output, "$resultDirectory/sunspider-comparison-data.js");
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)system($jsShellPath, "-f", "$resultDirectory/sunspider-test-prefix.js", "-f", "$resultDirectory/sunspider-comparison-data.js", "-f", "resources/sunspider-compare-results.js", "-f", "resources/sunspider-standalone-compare.js");
162