• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2
3# Copyright JS Foundation and other contributors, http://js.foundation
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#     http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16from __future__ import print_function
17# force // operator to be integer division in Python 2
18from __future__ import division
19
20import argparse
21import json
22import os
23import subprocess
24import sys
25
26TOOLS_PATH = os.path.dirname(os.path.realpath(__file__))
27BASE_PATH = os.path.join(TOOLS_PATH, '..')
28
29FLAG_CLEAN = '--clean'
30FLAG_DEBUG = '--debug'
31FLAG_HEAPLIMIT = '--mem-heap'
32JERRY_BUILDER = os.path.join(BASE_PATH, 'tools', 'build.py')
33JERRY_BIN = os.path.join(BASE_PATH, 'build', 'bin', 'jerry')
34TEST_DIR = os.path.join(BASE_PATH, 'tests')
35
36
37def get_args():
38    """ Parse input arguments. """
39    desc = 'Finds the smallest possible JerryHeap size without failing to run the given js file'
40    parser = argparse.ArgumentParser(description=desc)
41    parser.add_argument('testfile')
42    parser.add_argument('--heapsize', type=int, default=512,
43                        help='set the limit of the first heapsize (default: %(default)d)')
44    parser.add_argument('--buildtype', choices=['release', 'debug'], default='release',
45                        help='select build type (default: %(default)s)')
46
47    script_args = parser.parse_args()
48
49    return script_args
50
51
52def check_files(opts):
53    files = [JERRY_BUILDER, opts.testfile]
54    for _file in files:
55        if not os.path.isfile(_file):
56            sys.exit("File not found: %s" % _file)
57
58
59def build_bin(heapsize, opts):
60    """ Run tools/build.py script """
61    command = [
62        JERRY_BUILDER,
63        FLAG_CLEAN,
64        FLAG_HEAPLIMIT,
65        str(heapsize)
66    ]
67
68    if opts.buildtype == 'debug':
69        command.append(FLAG_DEBUG)
70
71    print('Building JerryScript with: %s' % (' '.join(command)))
72    subprocess.check_output(command)
73
74
75def run_test(opts):
76    """ Run the testfile to get the exitcode. """
77    try:
78        testfile = os.path.abspath(opts.testfile)
79        run_cmd = [JERRY_BIN, testfile]
80        # check output will raise an error if the exit code is not 0
81        subprocess.check_output(run_cmd, cwd=TEST_DIR)
82    except subprocess.CalledProcessError as err:
83        return err.returncode
84
85    return 0
86
87
88def heap_limit(opts):
89    """ Find the minimal size of jerryheap to pass """
90    goodheap = opts.heapsize
91    lowheap = 0
92    hiheap = opts.heapsize
93
94    while lowheap < hiheap:
95        build_bin(hiheap, opts)
96        assert os.path.isfile(JERRY_BIN), 'Jerry binary file does not exists'
97
98        exitcode = run_test(opts)
99        if exitcode != 0:
100            lowheap = hiheap
101            hiheap = (lowheap + goodheap) // 2
102        else:
103            goodheap = hiheap
104            hiheap = (lowheap + hiheap) // 2
105
106    return {
107        'testfile': opts.testfile,
108        'heaplimit to pass': goodheap
109    }
110
111
112def main(options):
113    check_files(options)
114    result = heap_limit(options)
115    print(json.dumps(result, indent=4))
116
117
118if __name__ == "__main__":
119    main(get_args())
120