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