blob: 1c2d75a243e968881025264a68e2253b4495ef4b [file] [log] [blame]
# Copyright 2016 Google Inc. All Rights Reserved.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# See the License for the specific language governing permissions and
# limitations under the License.
"""JSC-specific implementation of CodeGeneratorCobalt.
Defines CodeGeneratorJsc and ExpressionGeneratorJsc classes.
import os
import sys
# Add the bindings directory to the path.
module_path, module_filename = os.path.split(os.path.realpath(__file__))
cobalt_bindings_dir = os.path.normpath(os.path.join(module_path, os.pardir))
from code_generator_cobalt import CodeGeneratorCobalt # pylint: disable=g-import-not-at-top
from expression_generator import ExpressionGenerator
TEMPLATES_DIR = os.path.normpath(os.path.join(module_path, 'templates'))
def calculate_jsc_lookup_size(num_properties):
"""Calculate the number of entries to allocate in JSC::Lookup hash table."""
# JSC::Lookup uses an array internally to represent hash entries.
# The first |size_mask + 1| entries are hash buckets, and the remaining
# entries starting from entries[size_mask+1] are used for hash collisions.
# In the worst case where all keys collide, we will need
# (size_mask +1) + (num_properties - 1) entries, to account for properties[0]
# getting assigned to a hash bucket, and the remaining N-1 properties getting
# assigned to overflow entries.
# TODO: WebKit's bindings generation script calculates the actual
# required number of entries by duplicating the JSC::Lookup logic in the
# script and determining the number of collisions. If we want to reduce the
# number of entries allocated we can do something similar.
size_mask = calculate_jsc_lookup_size_mask(num_properties)
return (size_mask + 1) + max(0, (num_properties - 1))
def calculate_jsc_lookup_size_mask(num_properties):
"""Calculate the number of hash buckets to use in JSC::Lookup hash table."""
# 2 * num_properties is the heuristic used in WebKit's JSC bindings generation
# script to determine the number of hash buckets for the property hash table
num_hash_buckets = max(1, 2 * num_properties)
# JSC::Lookup hash table implementation uses a bitmask of the Identifier's
# hash to determine which bucket a Property goes into. This also rounds the
# number of buckets up to the closest power of 2.
return pow(2, num_hash_buckets.bit_length()) - 1
class ExpressionGeneratorJsc(ExpressionGenerator):
"""Implementation of ExpressionGenerator for JavaScriptCore."""
def is_undefined(self, arg):
return '%s.isUndefined()' % arg
def is_undefined_or_null(self, arg):
return '%s.isUndefinedOrNull()' % arg
def inherits_interface(self, interface_name, arg):
return '%s.inherits(JSC%s::s_classinfo())' % (arg, interface_name)
def is_number(self, arg):
return '%s.isNumber()' % arg
class CodeGeneratorJsc(CodeGeneratorCobalt):
"""Code generator class for JavaScriptCore binidings."""
_expression_generator = ExpressionGeneratorJsc()
def __init__(self, interfaces_info, cache_dir, output_dir):
CodeGeneratorCobalt.__init__(self, interfaces_info, TEMPLATES_DIR,
cache_dir, output_dir)
def generated_file_prefix(self):
return 'JSC'
def expression_generator(self):
return CodeGeneratorJsc._expression_generator
def build_interface_context(self, interface, interface_info, definitions):
"""Overrides CodeGeneratorCobalt.build_interface_context."""
context = super(CodeGeneratorJsc, self).build_interface_context(
interface, interface_info, definitions)
jsc_lookup_info = {
'calculate_jsc_lookup_size': calculate_jsc_lookup_size,
'calculate_jsc_lookup_size_mask': calculate_jsc_lookup_size_mask,
return context