Versioning.
[WebKit-https.git] / Source / JavaScriptCore / create_hash_table
index 3bb9cc2..b5c8db7 100755 (executable)
@@ -1,11 +1,11 @@
-#! /usr/bin/perl -w
+#! /usr/bin/env perl
 #
 # Static Hashtable Generator
 #
 # (c) 2000-2002 by Harri Porten <porten@kde.org> and
 #                  David Faure <faure@kde.org>
 # Modified (c) 2004 by Nikolas Zimmermann <wildfox@kde.org>
-# Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
+# Copyright (C) 2007-2018 Apple Inc. All rights reserved.
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
 # License along with this library; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 #
-
 use strict;
+use warnings;
+use Getopt::Long qw(:config pass_through);
 
-my $file = $ARGV[0];
-shift;
-my $includelookup = 0;
-
-# Use -i as second argument to make it include "Lookup.h"
-$includelookup = 1 if (defined($ARGV[0]) && $ARGV[0] eq "-i");
+my $file = shift @ARGV or die("Must provide source file as final argument.");
 
-# Use -n as second argument to make it use the third argument as namespace parameter ie. -n KDOM
-my $useNameSpace = $ARGV[1] if (defined($ARGV[0]) && $ARGV[0] eq "-n");
-
-print STDERR "Creating hashtable for $file\n";
 open(IN, $file) or die "No such file $file";
 
 my @keys = ();
 my @attrs = ();
 my @values = ();
 my @hashes = ();
+my @table = ();
+my @links = ();
+
+my $hasSetter = "false";
 
+my $includeBuiltin = 0;
 my $inside = 0;
 my $name;
 my $pefectHashSize;
@@ -74,26 +72,52 @@ while (<IN>) {
         @attrs = ();
         @values = ();
         @hashes = ();
+        @table = ();
+        @links = ();
+        $includeBuiltin = 0;
 
         $inside = 0;
-    } elsif (/^(\S+)\s*(\S+)\s*([\w\|]*)\s*(\w*)\s*$/ && $inside) {
+    } elsif (/^(\S+)\s*(\S+)\s*([\w\|]*)\s*(\w*)\s*(\w*)\s*$/ && $inside) {
         my $key = $1;
         my $val = $2;
         my $att = $3;
         my $param = $4;
+        my $intrinsic = $5;
 
         push(@keys, $key);
-        push(@attrs, length($att) > 0 ? $att : "0");
+        push(@attrs, length($att) > 0 ? $att : "None");
+
+        if ($val eq "JSBuiltin") {
+            $includeBuiltin = 1;
+        }
 
         if ($att =~ m/Function/) {
-            push(@values, { "type" => "Function", "function" => $val, "params" => (length($param) ? $param : "") });
+            push(@values, { "type" => "PropertyAttribute::Function", "function" => $val, "params" => (length($param) ? $param : ""), "intrinsic" => (length($intrinsic) ? $intrinsic : "NoIntrinsic") });
             #printf STDERR "WARNING: Number of arguments missing for $key/$val\n" if (length($param) == 0);
+        } elsif ($att =~ m/Accessor/) {
+            my $get = $val;
+            my $put = "nullptr";
+            $hasSetter = "true";
+            push(@values, { "type" => "PropertyAttribute::Accessor", "get" => $get, "put" => $put });
+        } elsif ($att =~ m/CellProperty/) {
+            my $property = $val;
+            push(@values, { "type" => "PropertyAttribute::CellProperty", "property" => $property });
+        } elsif ($att =~ m/ClassStructure/) {
+            my $property = $val;
+            push(@values, { "type" => "PropertyAttribute::ClassStructure", "property" => $property });
+        } elsif ($att =~ m/PropertyCallback/) {
+            my $cback = $val;
+            push(@values, { "type" => "PropertyAttribute::PropertyCallback", "cback" => $cback });
         } elsif (length($att)) {
             my $get = $val;
-            my $put = !($att =~ m/ReadOnly/) ? "set" . jsc_ucfirst($val) : "0";
-            push(@values, { "type" => "Property", "get" => $get, "put" => $put });
+            my $put = "0";
+            if (!($att =~ m/ReadOnly/)) {
+                $put = "set" . jsc_ucfirst($val);
+            }
+            $hasSetter = "true";
+            push(@values, { "type" => "PropertyAttribute::Property", "get" => $get, "put" => $put });
         } else {
-            push(@values, { "type" => "Lexer", "value" => $val });        
+            push(@values, { "type" => "Lexer", "value" => $val });
         }
         push(@hashes, hashValue($key));
     } elsif ($inside) {
@@ -149,8 +173,6 @@ sub leftShift($$) {
 
 sub calcCompactHashSize()
 {
-    my @table = ();
-    my @links = ();
     my $compactHashSize = ceilingToPowerOf2(2 * @keys);
     $compactHashSizeMask = $compactHashSize - 1;
     $compactSize = $compactHashSize;
@@ -179,7 +201,6 @@ sub calcCompactHashSize()
 
 # Paul Hsieh's SuperFastHash
 # http://www.azillionmonkeys.com/qed/hash.html
-# Ported from UString..
 sub hashValue($) {
   my @chars = split(/ */, $_[0]);
 
@@ -207,7 +228,7 @@ sub hashValue($) {
   }
 
   # Handle end case
-  if ($rem !=0) {
+  if ($rem != 0) {
     $hash += ord($chars[$s]);
     $hash ^= (leftShift($hash, 11)% $EXP2_32);
     $hash += $hash >> 17;
@@ -221,11 +242,15 @@ sub hashValue($) {
   $hash += ($hash >> 15);
   $hash = $hash% $EXP2_32;
   $hash ^= (leftShift($hash, 10)% $EXP2_32);
-  
-  # this avoids ever returning a hash code of 0, since that is used to
-  # signal "hash not computed yet", using a value that is likely to be
-  # effectively the same as 0 when the low bits are masked
-  $hash = 0x80000000  if ($hash == 0);
+
+  # Save 8 bits for StringImpl to use as flags.
+  $hash &= 0xffffff;
+
+  # This avoids ever returning a hash code of 0, since that is used to
+  # signal "hash not computed yet". Setting the high bit maintains
+  # reasonable fidelity to a hash code of 0 because it is likely to yield
+  # exactly 0 when hash lookup masks out the high bits.
+  $hash = (0x80000000 >> 8) if ($hash == 0);
 
   return $hash;
 }
@@ -238,89 +263,93 @@ sub output() {
 
     my $nameEntries = "${name}Values";
     $nameEntries =~ s/:/_/g;
+    my $nameIndex = "${name}Index";
+    $nameIndex =~ s/:/_/g;
+
+    print "\n";
+    print "#include \"JSCBuiltins.h\"\n" if ($includeBuiltin);
+    print "#include \"Lookup.h\"\n";
+    print "\n";
+    print "namespace JSC {\n";
+    print "\n";
+    if ($compactSize != 0) {
+        print "static const struct CompactHashIndex ${nameIndex}\[$compactSize\] = {\n";
+        for (my $i = 0; $i < $compactSize; $i++) {
+            my $T = -1;
+            if (defined($table[$i])) { $T = $table[$i]; }
+            my $L = -1;
+            if (defined($links[$i])) { $L = $links[$i]; }
+            print "    { $T, $L },\n";
+        }
+    } else {
+        # MSVC dislikes empty arrays.
+        print "static const struct CompactHashIndex ${nameIndex}\[1\] = {\n";
+        print "    { 0, 0 }\n";
+    }
+    print "};\n";
+    print "\n";
 
-    print "\n#include \"Lookup.h\"\n" if ($includelookup);
-    if ($useNameSpace) {
-        print "\nnamespace ${useNameSpace} {\n";
-        print "\nusing namespace JSC;\n";
+    my $packedSize = scalar @keys;
+    if ($packedSize != 0) {
+        print "static const struct HashTableValue ${nameEntries}\[$packedSize\] = {\n";
     } else {
-        print "\nnamespace JSC {\n";
+        # MSVC dislikes empty arrays.
+        print "static const struct HashTableValue ${nameEntries}\[1\] = {\n";
+        print "    { nullptr, 0, NoIntrinsic, { 0, 0 } }\n";
     }
-    my $count = scalar @keys + 1;
-    print "#if ENABLE(JIT)\n";
-    print "#define THUNK_GENERATOR(generator) , generator\n";
-    print "#else\n";
-    print "#define THUNK_GENERATOR(generator)\n";
-    print "#endif\n";
-    print "#if ENABLE(DFG_JIT)\n";
-    print "#define INTRINSIC(intrinsic) , intrinsic\n";
-    print "#else\n";
-    print "#define INTRINSIC(intrinsic)\n";
-    print "#endif\n";
-    print "\nstatic const struct HashTableValue ${nameEntries}\[$count\] = {\n";
     my $i = 0;
     foreach my $key (@keys) {
         my $firstValue = "";
         my $secondValue = "";
-        my $castStr = "";
+        my $firstCastStr = "";
+        my $secondCastStr = "";
+        my $intrinsic = "NoIntrinsic";
 
-        if ($values[$i]{"type"} eq "Function") {
-            $castStr = "static_cast<NativeFunction>";
+        if ($values[$i]{"type"} eq "PropertyAttribute::Function") {
+            $firstCastStr = "static_cast<RawNativeFunction>";
             $firstValue = $values[$i]{"function"};
             $secondValue = $values[$i]{"params"};
-        } elsif ($values[$i]{"type"} eq "Property") {
-            $castStr = "static_cast<PropertySlot::GetValueFunc>";
+            $intrinsic = $values[$i]{"intrinsic"};
+        } elsif ($values[$i]{"type"} eq "PropertyAttribute::Accessor") {
+            $firstCastStr = "static_cast<RawNativeFunction>";
+            $secondCastStr = "static_cast<RawNativeFunction>";
+            $firstValue = $values[$i]{"get"};
+            $secondValue = $values[$i]{"put"};
+        } elsif ($values[$i]{"type"} eq "PropertyAttribute::Property") {
+            $firstCastStr = "static_cast<PropertySlot::GetValueFunc>";
+            $secondCastStr = "static_cast<PutPropertySlot::PutValueFunc>";
             $firstValue = $values[$i]{"get"};
             $secondValue = $values[$i]{"put"};
         } elsif ($values[$i]{"type"} eq "Lexer") {
             $firstValue = $values[$i]{"value"};
             $secondValue = "0";
+        } elsif ($values[$i]{"type"} eq "PropertyAttribute::CellProperty" || $values[$i]{"type"} eq "PropertyAttribute::ClassStructure") {
+            $values[$i]{"property"} =~ /\A([a-zA-Z0-9_]+)::(.*)\Z/ or die;
+            $firstValue = "OBJECT_OFFSETOF($1, $2)";
+            $secondValue = "0";
+        } elsif ($values[$i]{"type"} eq "PropertyAttribute::PropertyCallback") {
+            $firstCastStr = "static_cast<LazyPropertyCallback>";
+            $firstValue = $values[$i]{"cback"};
+            $secondValue = "0";
         }
-        my $thunkGenerator = "0";
-        my $intrinsic = "DFG::NoIntrinsic";
-        if ($key eq "charCodeAt") {
-            $thunkGenerator = "charCodeAtThunkGenerator";
-        }
-        if ($key eq "charAt") {
-            $thunkGenerator = "charAtThunkGenerator";
-        }
-        if ($key eq "fromCharCode") {
-            $thunkGenerator = "fromCharCodeThunkGenerator";
+
+        my $attributes = "PropertyAttribute::" . $attrs[$i];
+        $attributes =~ s/\|/\|PropertyAttribute::/g;
+        $attributes = "static_cast<unsigned>(" . $attributes . ")";
+        if ($values[$i]{"type"} eq "PropertyAttribute::Function" && $firstValue eq "JSBuiltin")  {
+            my $tableHead = $name;
+            $tableHead =~ s/Table$//;
+            print "   { \"$key\", (($attributes) & ~PropertyAttribute::Function) | PropertyAttribute::Builtin, $intrinsic, { (intptr_t)static_cast<BuiltinGenerator>(" . $tableHead . ucfirst($key) . "CodeGenerator), (intptr_t)$secondValue } },\n";
         }
-        if ($name eq "mathTable") {
-            if ($key eq "sqrt") {
-                $thunkGenerator = "sqrtThunkGenerator";
-            }
-            if ($key eq "pow") {
-                $thunkGenerator = "powThunkGenerator";
-            }
-            if ($key eq "abs") {
-                $thunkGenerator = "absThunkGenerator";
-                $intrinsic = "DFG::AbsIntrinsic";
-            }
-            if ($key eq "floor") {
-                $thunkGenerator = "floorThunkGenerator";
-            }
-            if ($key eq "ceil") {
-                $thunkGenerator = "ceilThunkGenerator";
-            }
-            if ($key eq "round") {
-                $thunkGenerator = "roundThunkGenerator";
-            }
-            if ($key eq "exp") {
-                $thunkGenerator = "expThunkGenerator";
-            }
-            if ($key eq "log") {
-                $thunkGenerator = "logThunkGenerator";
-            }
+        else {
+            print "   { \"$key\", $attributes, $intrinsic, { (intptr_t)" . $firstCastStr . "($firstValue), (intptr_t)" . $secondCastStr . "($secondValue) } },\n";
         }
-        print "   { \"$key\", $attrs[$i], (intptr_t)" . $castStr . "($firstValue), (intptr_t)$secondValue THUNK_GENERATOR($thunkGenerator) INTRINSIC($intrinsic) },\n";
         $i++;
     }
-    print "   { 0, 0, 0, 0 THUNK_GENERATOR(0) INTRINSIC(DFG::NoIntrinsic) }\n";
-    print "};\n\n";
-    print "#undef THUNK_GENERATOR\n";
-    print "extern JSC_CONST_HASHTABLE HashTable $name =\n";
-    print "    \{ $compactSize, $compactHashSizeMask, $nameEntries, 0 \};\n";
-    print "} // namespace\n";
+    print "};\n";
+    print "\n";
+    print "static const struct HashTable $name =\n";
+    print "    \{ $packedSize, $compactHashSizeMask, $hasSetter, nullptr, $nameEntries, $nameIndex \};\n";
+    print "\n";
+    print "} // namespace JSC\n";
 }