diff options
53 files changed, 74 insertions, 1651 deletions
@@ -420,10 +420,3 @@ The gdbm module includes code from gdbm.h, which is distributed under the terms of the GPL license version 2 or any later version. Thus the gdbm module, provided in the file lib_pypy/gdbm.py, is redistributed under the terms of the GPL license as well. - -License for 'pypy/module/_vmprof/src' --------------------------------------- - -The code is based on gperftools. You may see a copy of the License for it at - - https://code.google.com/p/gperftools/source/browse/COPYING diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py index a4d42ec961..044621f4a0 100644 --- a/pypy/config/pypyoption.py +++ b/pypy/config/pypyoption.py @@ -38,9 +38,6 @@ working_modules.update([ "_csv", "cppyy", "_pypyjson" ]) -if sys.platform.startswith('linux') and sys.maxint > 2147483647: - working_modules.add('_vmprof') - translation_modules = default_modules.copy() translation_modules.update([ "fcntl", "time", "select", "signal", "_rawffi", "zlib", "struct", "_md5", @@ -102,7 +99,6 @@ module_import_dependencies = { "_hashlib" : ["pypy.module._ssl.interp_ssl"], "_minimal_curses": ["pypy.module._minimal_curses.fficurses"], "_continuation": ["rpython.rlib.rstacklet"], - "_vmprof" : ["pypy.module._vmprof.interp_vmprof"], } def get_module_validator(modname): diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py index edcfa12993..95ac5d1ec4 100644 --- a/pypy/interpreter/baseobjspace.py +++ b/pypy/interpreter/baseobjspace.py @@ -9,7 +9,6 @@ from rpython.rlib.objectmodel import (we_are_translated, newlist_hint, from rpython.rlib.signature import signature from rpython.rlib.rarithmetic import r_uint, SHRT_MIN, SHRT_MAX, \ INT_MIN, INT_MAX, UINT_MAX, USHRT_MAX -from rpython.rlib.rweaklist import RWeakListMixin from pypy.interpreter.executioncontext import (ExecutionContext, ActionFlag, UserDelAction) @@ -367,10 +366,6 @@ class CannotHaveLock(Exception): # ____________________________________________________________ -class CodeObjWeakList(RWeakListMixin): - def __init__(self): - self.initialize() - class ObjSpace(object): """Base class for the interpreter-level implementations of object spaces. http://pypy.readthedocs.org/en/latest/objspace.html""" @@ -394,7 +389,6 @@ class ObjSpace(object): self.check_signal_action = None # changed by the signal module self.user_del_action = UserDelAction(self) self._code_of_sys_exc_info = None - self.all_code_objs = CodeObjWeakList() # can be overridden to a subclass self.initialize() @@ -672,16 +666,6 @@ class ObjSpace(object): assert ec is not None return ec - def register_code_object(self, pycode): - callback = self.getexecutioncontext().register_code_callback - if callback is not None: - callback(self, pycode) - self.all_code_objs.add_handle(pycode) - - def set_code_callback(self, callback): - ec = self.getexecutioncontext() - ec.register_code_callback = callback - def _freeze_(self): return True diff --git a/pypy/interpreter/executioncontext.py b/pypy/interpreter/executioncontext.py index da5e876648..f004a7e923 100644 --- a/pypy/interpreter/executioncontext.py +++ b/pypy/interpreter/executioncontext.py @@ -33,11 +33,6 @@ class ExecutionContext(object): self.profilefunc = None self.w_profilefuncarg = None self.thread_disappeared = False # might be set to True after os.fork() - self.register_code_callback = None - if sys.maxint == 2147483647: - self._code_unique_id = 0 # XXX this is wrong, it won't work on 32bit - else: - self._code_unique_id = 0x7000000000000000 @staticmethod def _mark_thread_disappeared(space): diff --git a/pypy/interpreter/pycode.py b/pypy/interpreter/pycode.py index 1de0b37175..db2e4808f1 100644 --- a/pypy/interpreter/pycode.py +++ b/pypy/interpreter/pycode.py @@ -14,10 +14,9 @@ from pypy.interpreter.astcompiler.consts import ( CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS, CO_NESTED, CO_GENERATOR, CO_KILL_DOCSTRING, CO_YIELD_INSIDE_TRY) from pypy.tool.stdlib_opcode import opcodedesc, HAVE_ARGUMENT -from rpython.rlib.rarithmetic import intmask, r_longlong +from rpython.rlib.rarithmetic import intmask from rpython.rlib.objectmodel import compute_hash from rpython.rlib import jit -from rpython.rlib.debug import debug_start, debug_stop, debug_print class BytecodeCorruption(Exception): @@ -55,9 +54,8 @@ class PyCode(eval.Code): "CPython-style code objects." _immutable_ = True _immutable_fields_ = ["co_consts_w[*]", "co_names_w[*]", "co_varnames[*]", - "co_freevars[*]", "co_cellvars[*]", - "_args_as_cellvars[*]"] - + "co_freevars[*]", "co_cellvars[*]", "_args_as_cellvars[*]"] + def __init__(self, space, argcount, nlocals, stacksize, flags, code, consts, names, varnames, filename, name, firstlineno, lnotab, freevars, cellvars, @@ -85,7 +83,6 @@ class PyCode(eval.Code): self.magic = magic self._signature = cpython_code_signature(self) self._initialize() - space.register_code_object(self) def _initialize(self): if self.co_cellvars: @@ -127,15 +124,6 @@ class PyCode(eval.Code): from pypy.objspace.std.mapdict import init_mapdict_cache init_mapdict_cache(self) - ec = self.space.getexecutioncontext() - self._unique_id = ec._code_unique_id - ec._code_unique_id += 2 # so we have one bit that we can mark stuff - # with - - def _get_full_name(self): - return "py:%s:%d:%s" % (self.co_name, self.co_firstlineno, - self.co_filename) - def _cleanup_(self): if (self.magic == cpython_magic and '__pypy__' not in sys.builtin_module_names): diff --git a/pypy/module/_vmprof/__init__.py b/pypy/module/_vmprof/__init__.py deleted file mode 100644 index 88264413a8..0000000000 --- a/pypy/module/_vmprof/__init__.py +++ /dev/null @@ -1,18 +0,0 @@ -from pypy.interpreter.mixedmodule import MixedModule - -class Module(MixedModule): - """ - Write me :) - """ - appleveldefs = { - } - - interpleveldefs = { - 'enable': 'interp_vmprof.enable', - 'disable': 'interp_vmprof.disable', - } - - def setup_after_space_initialization(self): - # force the __extend__ hacks to occur early - from pypy.module._vmprof.interp_vmprof import VMProf - self.vmprof = VMProf() diff --git a/pypy/module/_vmprof/interp_vmprof.py b/pypy/module/_vmprof/interp_vmprof.py deleted file mode 100644 index 47e4d3cbf3..0000000000 --- a/pypy/module/_vmprof/interp_vmprof.py +++ /dev/null @@ -1,223 +0,0 @@ -import py, os, sys -from rpython.rtyper.lltypesystem import lltype, rffi, llmemory -from rpython.translator.tool.cbuild import ExternalCompilationInfo -from rpython.rtyper.annlowlevel import cast_instance_to_gcref, cast_base_ptr_to_instance -from rpython.rlib.objectmodel import we_are_translated -from rpython.rlib import jit, rposix, entrypoint -from rpython.rtyper.tool import rffi_platform as platform -from rpython.rlib.rstring import StringBuilder -from pypy.interpreter.baseobjspace import W_Root -from pypy.interpreter.error import oefmt, wrap_oserror, OperationError -from pypy.interpreter.gateway import unwrap_spec -from pypy.interpreter.pyframe import PyFrame - -ROOT = py.path.local(__file__).join('..') -SRC = ROOT.join('src') - -# by default, we statically link vmprof.c into pypy; however, if you set -# DYNAMIC_VMPROF to True, it will be dynamically linked to the libvmprof.so -# which is expected to be inside pypy/module/_vmprof/src: this is very useful -# during development. Note that you have to manually build libvmprof by -# running make inside the src dir -DYNAMIC_VMPROF = False - -eci_kwds = dict( - include_dirs = [SRC], - includes = ['vmprof.h', 'trampoline.h'], - separate_module_files = [SRC.join('trampoline.asmgcc.s')], - libraries = ['unwind'], - - post_include_bits=[""" - void* pypy_vmprof_get_virtual_ip(void*); - void pypy_vmprof_init(void); - """], - - separate_module_sources=[""" - void pypy_vmprof_init(void) { - vmprof_set_mainloop(pypy_execute_frame_trampoline, 0, - pypy_vmprof_get_virtual_ip); - } - """], - ) - - -if DYNAMIC_VMPROF: - eci_kwds['libraries'] += ['vmprof'] - eci_kwds['link_extra'] = ['-Wl,-rpath,%s' % SRC, '-L%s' % SRC] -else: - eci_kwds['separate_module_files'] += [SRC.join('vmprof.c')] - -eci = ExternalCompilationInfo(**eci_kwds) - -check_eci = eci.merge(ExternalCompilationInfo(separate_module_files=[ - SRC.join('fake_pypy_api.c')])) - -platform.verify_eci(check_eci) - -pypy_execute_frame_trampoline = rffi.llexternal( - "pypy_execute_frame_trampoline", - [llmemory.GCREF, llmemory.GCREF, llmemory.GCREF], - llmemory.GCREF, - compilation_info=eci, - _nowrapper=True, sandboxsafe=True, - random_effects_on_gcobjs=True) - -pypy_vmprof_init = rffi.llexternal("pypy_vmprof_init", [], lltype.Void, - compilation_info=eci) -vmprof_enable = rffi.llexternal("vmprof_enable", - [rffi.INT, rffi.LONG, rffi.INT, - rffi.CCHARP, rffi.INT], - rffi.INT, compilation_info=eci, - save_err=rffi.RFFI_SAVE_ERRNO) -vmprof_disable = rffi.llexternal("vmprof_disable", [], rffi.INT, - compilation_info=eci, - save_err=rffi.RFFI_SAVE_ERRNO) - -vmprof_register_virtual_function = rffi.llexternal( - "vmprof_register_virtual_function", - [rffi.CCHARP, rffi.VOIDP, rffi.VOIDP], lltype.Void, - compilation_info=eci, _nowrapper=True) - -original_execute_frame = PyFrame.execute_frame.im_func -original_execute_frame.c_name = 'pypy_pyframe_execute_frame' -original_execute_frame._dont_inline_ = True - -class __extend__(PyFrame): - def execute_frame(frame, w_inputvalue=None, operr=None): - # go through the asm trampoline ONLY if we are translated but not being JITted. - # - # If we are not translated, we obviously don't want to go through the - # trampoline because there is no C function it can call. - # - # If we are being JITted, we want to skip the trampoline, else the JIT - # cannot see throug it - if we_are_translated() and not jit.we_are_jitted(): - # if we are translated, call the trampoline - gc_frame = cast_instance_to_gcref(frame) - gc_inputvalue = cast_instance_to_gcref(w_inputvalue) - gc_operr = cast_instance_to_gcref(operr) - gc_result = pypy_execute_frame_trampoline(gc_frame, gc_inputvalue, gc_operr) - return cast_base_ptr_to_instance(W_Root, gc_result) - else: - return original_execute_frame(frame, w_inputvalue, operr) - - -@entrypoint.entrypoint_lowlevel('main', [llmemory.GCREF], - 'pypy_vmprof_get_virtual_ip', True) -def get_virtual_ip(gc_frame): - frame = cast_base_ptr_to_instance(PyFrame, gc_frame) - if jit._get_virtualizable_token(frame): - return rffi.cast(rffi.VOIDP, 0) - virtual_ip = do_get_virtual_ip(frame) - return rffi.cast(rffi.VOIDP, virtual_ip) - -def do_get_virtual_ip(frame): - return frame.pycode._unique_id - -def write_long_to_string_builder(l, b): - if sys.maxint == 2147483647: - b.append(chr(l & 0xff)) - b.append(chr((l >> 8) & 0xff)) - b.append(chr((l >> 16) & 0xff)) - b.append(chr((l >> 24) & 0xff)) - else: - b.append(chr(l & 0xff)) - b.append(chr((l >> 8) & 0xff)) - b.append(chr((l >> 16) & 0xff)) - b.append(chr((l >> 24) & 0xff)) - b.append(chr((l >> 32) & 0xff)) - b.append(chr((l >> 40) & 0xff)) - b.append(chr((l >> 48) & 0xff)) - b.append(chr((l >> 56) & 0xff)) - -class VMProf(object): - def __init__(self): - self.is_enabled = False - self.ever_enabled = False - self.mapping_so_far = [] # stored mapping in between runs - self.fileno = -1 - - def enable(self, space, fileno, period): - if self.is_enabled: - raise oefmt(space.w_ValueError, "_vmprof already enabled") - self.fileno = fileno - self.is_enabled = True - self.write_header(fileno, period) - if not self.ever_enabled: - if we_are_translated(): - pypy_vmprof_init() - self.ever_enabled = True - for weakcode in space.all_code_objs.get_all_handles(): - code = weakcode() - if code: - self.register_code(space, code) - space.set_code_callback(vmprof_register_code) - if we_are_translated(): - # does not work untranslated - res = vmprof_enable(fileno, period, 0, - lltype.nullptr(rffi.CCHARP.TO), 0) - else: - res = 0 - if res == -1: - raise wrap_oserror(space, OSError(rposix.get_saved_errno(), - "_vmprof.enable")) - - def write_header(self, fileno, period): - if period == -1: - period_usec = 1000000 / 100 # 100hz - else: - period_usec = period - b = StringBuilder() - write_long_to_string_builder(0, b) - write_long_to_string_builder(3, b) - write_long_to_string_builder(0, b) - write_long_to_string_builder(period_usec, b) - write_long_to_string_builder(0, b) - os.write(fileno, b.build()) - - def register_code(self, space, code): - if self.fileno == -1: - raise OperationError(space.w_RuntimeError, - space.wrap("vmprof not running")) - name = code._get_full_name() - b = StringBuilder() - b.append('\x02') - write_long_to_string_builder(code._unique_id, b) - write_long_to_string_builder(len(name), b) - b.append(name) - os.write(self.fileno, b.build()) - - def disable(self, space): - if not self.is_enabled: - raise oefmt(space.w_ValueError, "_vmprof not enabled") - self.is_enabled = False - self.fileno = -1 - if we_are_translated(): - # does not work untranslated - res = vmprof_disable() - else: - res = 0 - space.set_code_callback(None) - if res == -1: - raise wrap_oserror(space, OSError(rposix.get_saved_errno(), - "_vmprof.disable")) - -def vmprof_register_code(space, code): - from pypy.module._vmprof import Module - mod_vmprof = space.getbuiltinmodule('_vmprof') - assert isinstance(mod_vmprof, Module) - mod_vmprof.vmprof.register_code(space, code) - -@unwrap_spec(fileno=int, period=int) -def enable(space, fileno, period=-1): - from pypy.module._vmprof import Module - mod_vmprof = space.getbuiltinmodule('_vmprof') - assert isinstance(mod_vmprof, Module) - mod_vmprof.vmprof.enable(space, fileno, period) - -def disable(space): - from pypy.module._vmprof import Module - mod_vmprof = space.getbuiltinmodule('_vmprof') - assert isinstance(mod_vmprof, Module) - mod_vmprof.vmprof.disable(space) - diff --git a/pypy/module/_vmprof/src/config.h b/pypy/module/_vmprof/src/config.h deleted file mode 100644 index fb5bbea6b3..0000000000 --- a/pypy/module/_vmprof/src/config.h +++ /dev/null @@ -1,2 +0,0 @@ -#define HAVE_SYS_UCONTEXT_H -#define PC_FROM_UCONTEXT uc_mcontext.gregs[REG_RIP] diff --git a/pypy/module/_vmprof/src/fake_pypy_api.c b/pypy/module/_vmprof/src/fake_pypy_api.c deleted file mode 100644 index bd5b2994b1..0000000000 --- a/pypy/module/_vmprof/src/fake_pypy_api.c +++ /dev/null @@ -1,29 +0,0 @@ - -long pypy_jit_start_addr(void) -{ - return 3; -} - -long pypy_jit_end_addr(void) -{ - return 3; -} - -long pypy_jit_stack_depth_at_loc(long x) -{ - return 0; -} - -long pypy_find_codemap_at_addr(long x) -{ - return 0; -} - -long pypy_yield_codemap_at_addr(long x, long y, long *a) -{ - return 0; -} - -void pypy_pyframe_execute_frame(void) -{ -} diff --git a/pypy/module/_vmprof/src/get_custom_offset.c b/pypy/module/_vmprof/src/get_custom_offset.c deleted file mode 100644 index fd7c450e49..0000000000 --- a/pypy/module/_vmprof/src/get_custom_offset.c +++ /dev/null @@ -1,46 +0,0 @@ - -long pypy_jit_start_addr(); -long pypy_jit_end_addr(); -long pypy_jit_stack_depth_at_loc(long); -long pypy_find_codemap_at_addr(long); -long pypy_yield_codemap_at_addr(long, long, long*); - -void vmprof_set_tramp_range(void* start, void* end) -{ -} - -static ptrdiff_t vmprof_unw_get_custom_offset(void* ip, unw_cursor_t *cp) { - intptr_t ip_l = (intptr_t)ip; - - if (ip_l < pypy_jit_start_addr() || ip_l > pypy_jit_end_addr()) { - return -1; - } - return (void*)pypy_jit_stack_depth_at_loc(ip_l); -} - -static long vmprof_write_header_for_jit_addr(void **result, long n, - void *ip, int max_depth) -{ - long codemap_pos; - long current_pos = 0; - intptr_t id; - intptr_t addr = (intptr_t)ip; - - if (addr < pypy_jit_start_addr() || addr > pypy_jit_end_addr()) { - return n; - } - codemap_pos = pypy_find_codemap_at_addr(addr); - if (codemap_pos == -1) { - return n; - } - while (1) { - id = pypy_yield_codemap_at_addr(codemap_pos, addr, ¤t_pos); - if (id == 0) { - return n; - } - result[n++] = id; - if (n >= max_depth) { - return n; - } - } -} diff --git a/pypy/module/_vmprof/src/getpc.h b/pypy/module/_vmprof/src/getpc.h deleted file mode 100644 index 999232f6a3..0000000000 --- a/pypy/module/_vmprof/src/getpc.h +++ /dev/null @@ -1,187 +0,0 @@ -// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- -// Copyright (c) 2005, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// --- -// Author: Craig Silverstein -// -// This is an internal header file used by profiler.cc. It defines -// the single (inline) function GetPC. GetPC is used in a signal -// handler to figure out the instruction that was being executed when -// the signal-handler was triggered. -// -// To get this, we use the ucontext_t argument to the signal-handler -// callback, which holds the full context of what was going on when -// the signal triggered. How to get from a ucontext_t to a Program -// Counter is OS-dependent. - -#ifndef BASE_GETPC_H_ -#define BASE_GETPC_H_ - -#include "config.h" - -// On many linux systems, we may need _GNU_SOURCE to get access to -// the defined constants that define the register we want to see (eg -// REG_EIP). Note this #define must come first! -#define _GNU_SOURCE 1 -// If #define _GNU_SOURCE causes problems, this might work instead. -// It will cause problems for FreeBSD though!, because it turns off -// the needed __BSD_VISIBLE. -//#define _XOPEN_SOURCE 500 - -#include <string.h> // for memcmp -#if defined(HAVE_SYS_UCONTEXT_H) -#include <sys/ucontext.h> -#elif defined(HAVE_UCONTEXT_H) -#include <ucontext.h> // for ucontext_t (and also mcontext_t) -#elif defined(HAVE_CYGWIN_SIGNAL_H) -#include <cygwin/signal.h> -typedef ucontext ucontext_t; -#endif - - -// Take the example where function Foo() calls function Bar(). For -// many architectures, Bar() is responsible for setting up and tearing -// down its own stack frame. In that case, it's possible for the -// interrupt to happen when execution is in Bar(), but the stack frame -// is not properly set up (either before it's done being set up, or -// after it's been torn down but before Bar() returns). In those -// cases, the stack trace cannot see the caller function anymore. -// -// GetPC can try to identify this situation, on architectures where it -// might occur, and unwind the current function call in that case to -// avoid false edges in the profile graph (that is, edges that appear -// to show a call skipping over a function). To do this, we hard-code -// in the asm instructions we might see when setting up or tearing -// down a stack frame. -// -// This is difficult to get right: the instructions depend on the -// processor, the compiler ABI, and even the optimization level. This -// is a best effort patch -- if we fail to detect such a situation, or -// mess up the PC, nothing happens; the returned PC is not used for -// any further processing. -struct CallUnrollInfo { - // Offset from (e)ip register where this instruction sequence - // should be matched. Interpreted as bytes. Offset 0 is the next - // instruction to execute. Be extra careful with negative offsets in - // architectures of variable instruction length (like x86) - it is - // not that easy as taking an offset to step one instruction back! - int pc_offset; - // The actual instruction bytes. Feel free to make it larger if you - // need a longer sequence. - unsigned char ins[16]; - // How many bytes to match from ins array? - int ins_size; - // The offset from the stack pointer (e)sp where to look for the - // call return address. Interpreted as bytes. - int return_sp_offset; -}; - - -// The dereferences needed to get the PC from a struct ucontext were -// determined at configure time, and stored in the macro -// PC_FROM_UCONTEXT in config.h. The only thing we need to do here, -// then, is to do the magic call-unrolling for systems that support it. - -// -- Special case 1: linux x86, for which we have CallUnrollInfo -#if defined(__linux) && defined(__i386) && defined(__GNUC__) -static const CallUnrollInfo callunrollinfo[] = { - // Entry to a function: push %ebp; mov %esp,%ebp - // Top-of-stack contains the caller IP. - { 0, - {0x55, 0x89, 0xe5}, 3, - 0 - }, - // Entry to a function, second instruction: push %ebp; mov %esp,%ebp - // Top-of-stack contains the old frame, caller IP is +4. - { -1, - {0x55, 0x89, 0xe5}, 3, - 4 - }, - // Return from a function: RET. - // Top-of-stack contains the caller IP. - { 0, - {0xc3}, 1, - 0 - } -}; - -inline void* GetPC(ucontext_t *signal_ucontext) { - // See comment above struct CallUnrollInfo. Only try instruction - // flow matching if both eip and esp looks reasonable. - const int eip = signal_ucontext->uc_mcontext.gregs[REG_EIP]; - const int esp = signal_ucontext->uc_mcontext.gregs[REG_ESP]; - if ((eip & 0xffff0000) != 0 && (~eip & 0xffff0000) != 0 && - (esp & 0xffff0000) != 0) { - char* eip_char = reinterpret_cast<char*>(eip); - for (int i = 0; i < sizeof(callunrollinfo)/sizeof(*callunrollinfo); ++i) { - if (!memcmp(eip_char + callunrollinfo[i].pc_offset, - callunrollinfo[i].ins, callunrollinfo[i].ins_size)) { - // We have a match. - void **retaddr = (void**)(esp + callunrollinfo[i].return_sp_offset); - return *retaddr; - } - } - } - return (void*)eip; -} - -// Special case #2: Windows, which has to do something totally different. -#elif defined(_WIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__) || defined(__MINGW32__) -// If this is ever implemented, probably the way to do it is to have -// profiler.cc use a high-precision timer via timeSetEvent: -// http://msdn2.microsoft.com/en-us/library/ms712713.aspx -// We'd use it in mode TIME_CALLBACK_FUNCTION/TIME_PERIODIC. -// The callback function would be something like prof_handler, but -// alas the arguments are different: no ucontext_t! I don't know -// how we'd get the PC (using StackWalk64?) -// http://msdn2.microsoft.com/en-us/library/ms680650.aspx - -#include "base/logging.h" // for RAW_LOG -#ifndef HAVE_CYGWIN_SIGNAL_H -typedef int ucontext_t; -#endif - -inline void* GetPC(ucontext_t *signal_ucontext) { - RAW_LOG(ERROR, "GetPC is not yet implemented on Windows\n"); - return NULL; -} - -// Normal cases. If this doesn't compile, it's probably because -// PC_FROM_UCONTEXT is the empty string. You need to figure out -// the right value for your system, and add it to the list in -// configure.ac (or set it manually in your config.h). -#else -inline void* GetPC(ucontext_t *signal_ucontext) { - return (void*)signal_ucontext->PC_FROM_UCONTEXT; // defined in config.h -} - -#endif - -#endif // BASE_GETPC_H_ diff --git a/pypy/module/_vmprof/src/trampoline.asmgcc.s b/pypy/module/_vmprof/src/trampoline.asmgcc.s deleted file mode 100644 index a4b3e250df..0000000000 --- a/pypy/module/_vmprof/src/trampoline.asmgcc.s +++ /dev/null @@ -1,17 +0,0 @@ -// NOTE: you need to use TABs, not spaces! - - .text - .p2align 4,,-1 - .globl pypy_execute_frame_trampoline - .type pypy_execute_frame_trampoline, @function -pypy_execute_frame_trampoline: - .cfi_startproc - pushq %rdi - .cfi_def_cfa_offset 16 - call pypy_pyframe_execute_frame@PLT - /* GCROOT 0(%rsp) */ - popq %rdi - .cfi_def_cfa_offset 8 - ret - .cfi_endproc - .size pypy_execute_frame_trampoline, .-pypy_execute_frame_trampoline diff --git a/pypy/module/_vmprof/src/trampoline.h b/pypy/module/_vmprof/src/trampoline.h deleted file mode 100644 index 60b6f4fa76..0000000000 --- a/pypy/module/_vmprof/src/trampoline.h +++ /dev/null @@ -1 +0,0 @@ -void* pypy_execute_frame_trampoline(void*, void*, void*); diff --git a/pypy/module/_vmprof/src/vmprof.c b/pypy/module/_vmprof/src/vmprof.c deleted file mode 100644 index 08261c0f83..0000000000 --- a/pypy/module/_vmprof/src/vmprof.c +++ /dev/null @@ -1,340 +0,0 @@ -/* VMPROF - * - * statistical sampling profiler specifically designed to profile programs - * which run on a Virtual Machine and/or bytecode interpreter, such as Python, - * etc. - * - * The logic to dump the C stack traces is partly stolen from the code in gperftools. - * The file "getpc.h" has been entirely copied from gperftools. - * - * Tested only on gcc, linux, x86_64. - * - * Copyright (C) 2014-2015 - * Antonio Cuni - anto.cuni@gmail.com - * Maciej Fijalkowski - fijall@gmail.com - * - */ - - -#include "getpc.h" // should be first to get the _GNU_SOURCE dfn -#include <signal.h> -#include <stdio.h> -#include <string.h> -#include <stddef.h> -#include <assert.h> -#include <unistd.h> -#include <sys/time.h> -#include <sys/types.h> - -#define UNW_LOCAL_ONLY -#include <libunwind.h> - -#include "vmprof.h" - -#define _unused(x) ((void)x) - -#define MAX_FUNC_NAME 128 -#define MAX_STACK_DEPTH 64 - -static FILE* profile_file = NULL; -void* vmprof_mainloop_func; -static ptrdiff_t mainloop_sp_offset; -static vmprof_get_virtual_ip_t mainloop_get_virtual_ip; - - -/* ************************************************************* - * functions to write a profile file compatible with gperftools - * ************************************************************* - */ - -#define MARKER_STACKTRACE '\x01' -#define MARKER_VIRTUAL_IP '\x02' -#define MARKER_TRAILER '\x03' - -static void prof_word(FILE* f, long x) { - fwrite(&x, sizeof(x), 1, f); -} - -static void prof_header(FILE* f, long period_usec) { - prof_word(f, 0); - prof_word(f, 3); - prof_word(f, 0); - prof_word(f, period_usec); - prof_word(f, 0); -} - -static void prof_write_stacktrace(FILE* f, void** stack, int depth, int count) { - int i; - char marker = MARKER_STACKTRACE; - - fwrite(&marker, 1, 1, f); - prof_word(f, count); - prof_word(f, depth); - for(i=0; i<depth; i++) - prof_word(f, (long)stack[i]); -} - - -/* ****************************************************** - * libunwind workaround for process JIT frames correctly - * ****************************************************** - */ - -#include "get_custom_offset.c" - -typedef struct { - void* _unused1; - void* _unused2; - void* sp; - void* ip; - void* _unused3[sizeof(unw_cursor_t)/sizeof(void*) - 4]; -} vmprof_hacked_unw_cursor_t; - -static int vmprof_unw_step(unw_cursor_t *cp) { - void* ip; - void* sp; - ptrdiff_t sp_offset; - unw_get_reg (cp, UNW_REG_IP, (unw_word_t*)&ip); - unw_get_reg (cp, UNW_REG_SP, (unw_word_t*)&sp); - sp_offset = vmprof_unw_get_custom_offset(ip, cp); - - if (sp_offset == -1) { - // it means that the ip is NOT in JITted code, so we can use the - // stardard unw_step - return unw_step(cp); - } - else { - // this is a horrible hack to manually walk the stack frame, by - // setting the IP and SP in the cursor - vmprof_hacked_unw_cursor_t *cp2 = (vmprof_hacked_unw_cursor_t*)cp; - void* bp = (void*)sp + sp_offset; - cp2->sp = bp; - bp -= sizeof(void*); - cp2->ip = ((void**)bp)[0]; - // the ret is on the top of the stack minus WORD - return 1; - } -} - - -/* ************************************************************* - * functions to dump the stack trace - * ************************************************************* - */ - -// stolen from pprof: -// Sometimes, we can try to get a stack trace from within a stack -// trace, because libunwind can call mmap (maybe indirectly via an -// internal mmap based memory allocator), and that mmap gets trapped -// and causes a stack-trace request. If were to try to honor that -// recursive request, we'd end up with infinite recursion or deadlock. -// Luckily, it's safe to ignore those subsequent traces. In such -// cases, we return 0 to indicate the situation. -//static __thread int recursive; -static int recursive; // XXX antocuni: removed __thread - -int get_stack_trace(void** result, int max_depth, ucontext_t *ucontext) { - void *ip; - int n = 0; - unw_cursor_t cursor; - unw_context_t uc = *ucontext; - if (recursive) { - return 0; - } - ++recursive; - - int ret = unw_init_local(&cursor, &uc); - assert(ret >= 0); - _unused(ret); - - while (n < max_depth) { - if (unw_get_reg(&cursor, UNW_REG_IP, (unw_word_t *) &ip) < 0) { - break; - } - - unw_proc_info_t pip; - unw_get_proc_info(&cursor, &pip); - - /* char funcname[4096]; */ - /* unw_word_t offset; */ - /* unw_get_proc_name(&cursor, funcname, 4096, &offset); */ - /* printf("%s+%#lx <%p>\n", funcname, offset, ip); */ - - /* if n==0, it means that the signal handler interrupted us while we - were in the trampoline, so we are not executing (yet) the real main - loop function; just skip it */ - if (vmprof_mainloop_func && - (void*)pip.start_ip == (void*)vmprof_mainloop_func && - n > 0) { - // found main loop stack frame - void* sp; - unw_get_reg(&cursor, UNW_REG_SP, (unw_word_t *) &sp); - void *arg_addr = (char*)sp + mainloop_sp_offset; - void **arg_ptr = (void**)arg_addr; - // fprintf(stderr, "stacktrace mainloop: rsp %p &f2 %p offset %ld\n", - // sp, arg_addr, mainloop_sp_offset); - ip = mainloop_get_virtual_ip(*arg_ptr); - } - - result[n++] = ip; - n = vmprof_write_header_for_jit_addr(result, n, ip, max_depth); - if (vmprof_unw_step(&cursor) <= 0) { - break; - } - } - --recursive; - return n; -} - - -static int __attribute__((noinline)) frame_forcer(int rv) { - return rv; -} - -static void sigprof_handler(int sig_nr, siginfo_t* info, void *ucontext) { - void* stack[MAX_STACK_DEPTH]; - stack[0] = GetPC((ucontext_t*)ucontext); - int depth = frame_forcer(get_stack_trace(stack+1, MAX_STACK_DEPTH-1, ucontext)); - depth++; // To account for pc value in stack[0]; - prof_write_stacktrace(profile_file, stack, depth, 1); -} - -/* ************************************************************* - * functions to enable/disable the profiler - * ************************************************************* - */ - -static int open_profile(int fd, long period_usec, int write_header, char *s, - int slen) { - if ((fd = dup(fd)) == -1) { - return -1; - } - profile_file = fdopen(fd, "wb"); - if (!profile_file) { - return -1; - } - if (write_header) - prof_header(profile_file, period_usec); - if (s) - fwrite(s, slen, 1, profile_file); - return 0; -} - -static int close_profile(void) { - // XXX all of this can happily fail - FILE* src; - char buf[BUFSIZ]; - size_t size; - int marker = MARKER_TRAILER; - fwrite(&marker, 1, 1, profile_file); - - // copy /proc/PID/maps to the end of the profile file - sprintf(buf, "/proc/%d/maps", getpid()); - src = fopen(buf, "r"); - while ((size = fread(buf, 1, BUFSIZ, src))) { - fwrite(buf, 1, size, profile_file); - } - fclose(src); - fclose(profile_file); - return 0; -} - - -static int install_sigprof_handler(void) { - struct sigaction sa; - memset(&sa, 0, sizeof(sa)); - sa.sa_sigaction = sigprof_handler; - sa.sa_flags = SA_RESTART | SA_SIGINFO; - if (sigemptyset(&sa.sa_mask) == -1 || - sigaction(SIGPROF, &sa, NULL) == -1) { - return -1; - } - return 0; -} - -static int remove_sigprof_handler(void) { - //sighandler_t res = signal(SIGPROF, SIG_DFL); - //if (res == SIG_ERR) { - // return -1; - //} - return 0; -}; - -static int install_sigprof_timer(long period_usec) { - static struct itimerval timer; - timer.it_interval.tv_sec = 0; - timer.it_interval.tv_usec = period_usec; - timer.it_value = timer.it_interval; - if (setitimer(ITIMER_PROF, &timer, NULL) != 0) { - return -1; - } - return 0; -} - -static int remove_sigprof_timer(void) { - static struct itimerval timer; - timer.it_interval.tv_sec = 0; - timer.it_interval.tv_usec = 0; - timer.it_value = timer.it_interval; - if (setitimer(ITIMER_PROF, &timer, NULL) != 0) { - return -1; - } - return 0; -} - -/* ************************************************************* - * public API - * ************************************************************* - */ - -void vmprof_set_mainloop(void* func, ptrdiff_t sp_offset, - vmprof_get_virtual_ip_t get_virtual_ip) { - mainloop_sp_offset = sp_offset; - mainloop_get_virtual_ip = get_virtual_ip; - vmprof_mainloop_func = func; -} - -int vmprof_enable(int fd, long period_usec, int write_header, char *s, - int slen) -{ - if (period_usec == -1) - period_usec = 1000000 / 100; /* 100hz */ - if (open_profile(fd, period_usec, write_header, s, slen) == -1) { - return -1; - } - if (install_sigprof_handler() == -1) { - return -1; - } - if (install_sigprof_timer(period_usec) == -1) { - return -1; - } - return 0; -} - -int vmprof_disable(void) { - if (remove_sigprof_timer() == -1) { - return -1; - } - if (remove_sigprof_handler() == -1) { - return -1; - } - if (close_profile() == -1) { - return -1; - } - return 0; -} - -void vmprof_register_virtual_function(const char* name, void* start, void* end) { - // for now *end is simply ignored - char buf[1024]; - int lgt = strlen(name) + 2 * sizeof(long) + 1; - - if (lgt > 1024) { - lgt = 1024; - } - buf[0] = MARKER_VIRTUAL_IP; - ((void **)(((void*)buf) + 1))[0] = start; - ((long *)(((void*)buf) + 1 + sizeof(long)))[0] = lgt - 2 * sizeof(long) - 1; - strncpy(buf + 2 * sizeof(long) + 1, name, 1024 - 2 * sizeof(long) - 1); - fwrite(buf, lgt, 1, profile_file); -} diff --git a/pypy/module/_vmprof/src/vmprof.h b/pypy/module/_vmprof/src/vmprof.h deleted file mode 100644 index a9e99857a5..0000000000 --- a/pypy/module/_vmprof/src/vmprof.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef VMPROF_VMPROF_H_ -#define VMPROF_VMPROF_H_ - -#include <stddef.h> - -typedef void* (*vmprof_get_virtual_ip_t)(void*); - -extern void* vmprof_mainloop_func; -void vmprof_set_mainloop(void* func, ptrdiff_t sp_offset, - vmprof_get_virtual_ip_t get_virtual_ip); - -void vmprof_register_virtual_function(const char* name, void* start, void* end); - - -int vmprof_enable(int fd, long period_usec, int write_header, char* vips, - int vips_len); -int vmprof_disable(void); - -// XXX: this should be part of _vmprof (the CPython extension), not vmprof (the library) -void vmprof_set_tramp_range(void* start, void* end); - -#endif diff --git a/pypy/module/_vmprof/test/__init__.py b/pypy/module/_vmprof/test/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/pypy/module/_vmprof/test/__init__.py +++ /dev/null diff --git a/pypy/module/_vmprof/test/test__vmprof.py b/pypy/module/_vmprof/test/test__vmprof.py deleted file mode 100644 index ac62872369..0000000000 --- a/pypy/module/_vmprof/test/test__vmprof.py +++ /dev/null @@ -1,55 +0,0 @@ - -import tempfile -from pypy.tool.pytest.objspace import gettestobjspace - -class AppTestVMProf(object): - def setup_class(cls): - cls.space = gettestobjspace(usemodules=['_vmprof', 'struct']) - cls.tmpfile = tempfile.NamedTemporaryFile() - cls.w_tmpfileno = cls.space.wrap(cls.tmpfile.fileno()) - cls.w_tmpfilename = cls.space.wrap(cls.tmpfile.name) - cls.tmpfile2 = tempfile.NamedTemporaryFile() - cls.w_tmpfileno2 = cls.space.wrap(cls.tmpfile2.fileno()) - cls.w_tmpfilename2 = cls.space.wrap(cls.tmpfile2.name) - - def test_import_vmprof(self): - import struct, sys - - WORD = struct.calcsize('l') - - def count(s): - i = 0 - count = 0 - i += 5 * WORD # header - while i < len(s): - assert s[i] == '\x02' - i += 1 - _, size = struct.unpack("ll", s[i:i + 2 * WORD]) - count += 1 - i += 2 * WORD + size - return count - - import _vmprof - _vmprof.enable(self.tmpfileno) - _vmprof.disable() - s = open(self.tmpfilename).read() - no_of_codes = count(s) - assert no_of_codes > 10 - d = {} - - exec """def foo(): - pass - """ in d - - _vmprof.enable(self.tmpfileno2) - - exec """def foo2(): - pass - """ in d - - _vmprof.disable() - s = open(self.tmpfilename2).read() - no_of_codes2 = count(s) - assert "py:foo:" in s - assert "py:foo2:" in s - assert no_of_codes2 >= no_of_codes + 2 # some extra codes from tests diff --git a/pypy/module/pypyjit/interp_jit.py b/pypy/module/pypyjit/interp_jit.py index b3d1ba2444..30686c238e 100644 --- a/pypy/module/pypyjit/interp_jit.py +++ b/pypy/module/pypyjit/interp_jit.py @@ -35,9 +35,6 @@ def get_printable_location(next_instr, is_being_profiled, bytecode): name = opcode_method_names[ord(bytecode.co_code[next_instr])] return '%s #%d %s' % (bytecode.get_repr(), next_instr, name) -def get_unique_id(next_instr, is_being_profiled, bytecode): - return bytecode._unique_id - def should_unroll_one_iteration(next_instr, is_being_profiled, bytecode): return (bytecode.co_flags & CO_GENERATOR) != 0 @@ -48,7 +45,6 @@ class PyPyJitDriver(JitDriver): virtualizables = ['frame'] pypyjitdriver = PyPyJitDriver(get_printable_location = get_printable_location, - get_unique_id = get_unique_id, should_unroll_one_iteration = should_unroll_one_iteration, name='pypyjit') diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py index da4560c14d..09471739bf 100644 --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -57,7 +57,6 @@ class AssemblerARM(ResOpAssembler): BaseAssembler.setup_once(self) def setup(self, looptoken): - BaseAssembler.setup(self, looptoken) assert self.memcpy_addr != 0, 'setup_once() not called?' if we_are_translated(): self.debug = False @@ -72,6 +71,7 @@ class AssemblerARM(ResOpAssembler): self.mc.datablockwrapper = self.datablockwrapper self.target_tokens_currently_compiling = {} self.frame_depth_to_patch = [] + self._finish_gcmap = lltype.nullptr(jitframe.GCMAP) def teardown(self): self.current_clt = None @@ -659,7 +659,6 @@ class AssemblerARM(ResOpAssembler): assert len(set(inputargs)) == len(inputargs) self.setup(original_loop_token) - self.codemap.inherit_code_from_position(faildescr.adr_jump_offset) descr_number = compute_unique_id(faildescr) if log: operations = self._inject_debugging_code(faildescr, operations, @@ -880,12 +879,8 @@ class AssemblerARM(ResOpAssembler): self.datablockwrapper.done() # finish using cpu.asmmemmgr self.datablockwrapper = None allblocks = self.get_asmmemmgr_blocks(looptoken) - size = self.mc.get_relative_pos() - res = self.mc.materialize(self.cpu.asmmemmgr, allblocks, + return self.mc.materialize(self.cpu.asmmemmgr, allblocks, self.cpu.gc_ll_descr.gcrootmap) - self.cpu.asmmemmgr.register_codemap( - self.codemap.get_final_bytecode(res, size)) - return res def update_frame_depth(self, frame_depth): baseofs = self.cpu.get_baseofs_of_frame_field() diff --git a/rpython/jit/backend/arm/regalloc.py b/rpython/jit/backend/arm/regalloc.py index 5835805796..483b0c1996 100644 --- a/rpython/jit/backend/arm/regalloc.py +++ b/rpython/jit/backend/arm/regalloc.py @@ -392,9 +392,6 @@ class Regalloc(BaseRegalloc): else: self.rm._sync_var(v) - def prepare_op_debug_merge_point(self, op, fcond): - self.assembler.codemap.debug_merge_point(op) - def _prepare_op_int_add(self, op, fcond): boxes = op.getarglist() a0, a1 = boxes diff --git a/rpython/jit/backend/llsupport/asmmemmgr.py b/rpython/jit/backend/llsupport/asmmemmgr.py index 7c1c94f908..7e0ed723d5 100644 --- a/rpython/jit/backend/llsupport/asmmemmgr.py +++ b/rpython/jit/backend/llsupport/asmmemmgr.py @@ -4,10 +4,7 @@ from rpython.rlib.objectmodel import we_are_translated from rpython.rlib import rmmap from rpython.rlib.debug import debug_start, debug_print, debug_stop from rpython.rlib.debug import have_debug_prints -from rpython.rtyper.lltypesystem import lltype, rffi -from rpython.rlib.rbisect import bisect, bisect_tuple - -_memmngr = None # global reference so we can use @entrypoint :/ +from rpython.rtyper.lltypesystem import lltype, llmemory, rffi class AsmMemoryManager(object): @@ -27,12 +24,6 @@ class AsmMemoryManager(object): self.free_blocks = {} # map {start: stop} self.free_blocks_end = {} # map {stop: start} self.blocks_by_size = [[] for i in range(self.num_indices)] - # two lists of jit addresses (sorted) and the corresponding stack - # depths - self.jit_addr_map = [] - self.jit_frame_depth_map = [] - self.jit_codemap = [] - # see codemap.py def malloc(self, minsize, maxsize): """Allocate executable memory, between minsize and maxsize bytes, @@ -54,13 +45,6 @@ class AsmMemoryManager(object): if r_uint is not None: self.total_mallocs -= r_uint(stop - start) self._add_free_block(start, stop) - # fix up jit_addr_map - jit_adr_start = bisect(self.jit_addr_map, start) - jit_adr_stop = bisect(self.jit_addr_map, stop) - self.jit_addr_map = (self.jit_addr_map[:jit_adr_start] + - self.jit_addr_map[jit_adr_stop:]) - self.jit_frame_depth_map = (self.jit_frame_depth_map[:jit_adr_start] + - self.jit_frame_depth_map[jit_adr_stop:]) def open_malloc(self, minsize): """Allocate at least minsize bytes. Returns (start, stop).""" @@ -167,35 +151,6 @@ class AsmMemoryManager(object): del self.free_blocks_end[stop] return (start, stop) - def register_frame_depth_map(self, rawstart, frame_positions, - frame_assignments): - if not frame_positions: - return - if not self.jit_addr_map or rawstart > self.jit_addr_map[-1]: - start = len(self.jit_addr_map) - self.jit_addr_map += [0] * len(frame_positions) - self.jit_frame_depth_map += [0] * len(frame_positions) - else: - start = bisect(self.jit_addr_map, rawstart) - self.jit_addr_map = (self.jit_addr_map[:start] + - [0] * len(frame_positions) + - self.jit_addr_map[start:]) - self.jit_frame_depth_map = (self.jit_frame_depth_map[:start] + - [0] * len(frame_positions) + - self.jit_frame_depth_map[start:]) - for i, pos in enumerate(frame_positions): - self.jit_addr_map[i + start] = pos + rawstart - self.jit_frame_depth_map[i + start] = frame_assignments[i] - - def register_codemap(self, codemap): - start = codemap[0] - pos = bisect_tuple(self.jit_codemap, start) - if pos == len(self.jit_codemap): # common case - self.jit_codemap.append(codemap) - else: - self.jit_codemap = (self.jit_codemap[:pos] + [codemap] + - self.jit_codemap[pos:]) - def _delete(self): "NOT_RPYTHON" if self._allocated: @@ -257,9 +212,6 @@ class BlockBuilderMixin(object): gcroot_markers = None - frame_positions = None - frame_assignments = None - def __init__(self, translated=None): if translated is None: translated = we_are_translated() @@ -364,10 +316,6 @@ class BlockBuilderMixin(object): assert gcrootmap is not None for pos, mark in self.gcroot_markers: gcrootmap.register_asm_addr(rawstart + pos, mark) - asmmemmgr.register_frame_depth_map(rawstart, self.frame_positions, - self.frame_assignments) - self.frame_positions = None - self.frame_assignments = None return rawstart def _become_a_plain_block_builder(self): diff --git a/rpython/jit/backend/llsupport/assembler.py b/rpython/jit/backend/llsupport/assembler.py index 695023ff24..36f85af506 100644 --- a/rpython/jit/backend/llsupport/assembler.py +++ b/rpython/jit/backend/llsupport/assembler.py @@ -1,7 +1,6 @@ from rpython.jit.backend.llsupport import jitframe from rpython.jit.backend.llsupport.memcpy import memcpy_fn, memset_fn from rpython.jit.backend.llsupport.symbolic import WORD -from rpython.jit.backend.llsupport.codemap import CodemapBuilder from rpython.jit.metainterp.history import (INT, REF, FLOAT, JitCellToken, ConstInt, BoxInt, AbstractFailDescr) from rpython.jit.metainterp.resoperation import ResOperation, rop @@ -129,10 +128,6 @@ class BaseAssembler(object): track_allocation=False) self.gcmap_for_finish[0] = r_uint(1) - def setup(self, looptoken): - self.codemap = CodemapBuilder() - self._finish_gcmap = lltype.nullptr(jitframe.GCMAP) - def set_debug(self, v): r = self._debug self._debug = v @@ -199,9 +194,6 @@ class BaseAssembler(object): guardtok.faildescr.rd_locs = positions return fail_descr, target - def debug_merge_point(self, op): - self.codemap.debug_merge_point(op, self.mc.get_relative_pos()) - def call_assembler(self, op, guard_op, argloc, vloc, result_loc, tmploc): self._store_force_index(guard_op) descr = op.getdescr() @@ -284,9 +276,6 @@ class BaseAssembler(object): # YYY very minor leak -- we need the counters to stay alive # forever, just because we want to report them at the end # of the process - - # XXX the numbers here are ALMOST unique, but not quite, use a counter - # or something struct = lltype.malloc(DEBUG_COUNTER, flavor='raw', track_allocation=False) struct.i = 0 diff --git a/rpython/jit/backend/llsupport/codemap.py b/rpython/jit/backend/llsupport/codemap.py deleted file mode 100644 index e16f9339e7..0000000000 --- a/rpython/jit/backend/llsupport/codemap.py +++ /dev/null @@ -1,142 +0,0 @@ - -""" Bytecode for storage in asmmemmgr.jit_codemap. Format is as follows: - - list of tuples of shape (addr, machine code size, bytecode info) - where bytecode info is a string made up of: - 8 bytes unique_id, 4 bytes start_addr (relative), 4 bytes size (relative), - 2 bytes how many items to skip to go to the next on similar level - [so far represented by a list of integers for simplicity] - -""" - -from rpython.rlib import rgc -from rpython.rlib.entrypoint import jit_entrypoint -from rpython.jit.backend.llsupport import asmmemmgr -from rpython.rlib.rbisect import bisect, bisect_tuple -from rpython.rtyper.lltypesystem import lltype, rffi - -@jit_entrypoint([lltype.Signed], lltype.Signed, - c_name='pypy_jit_stack_depth_at_loc') -@rgc.no_collect -def stack_depth_at_loc(loc): - _memmngr = asmmemmgr._memmngr - - pos = bisect(_memmngr.jit_addr_map, loc) - if pos == 0 or pos == len(_memmngr.jit_addr_map): - return -1 - return _memmngr.jit_frame_depth_map[pos-1] - -@jit_entrypoint([], lltype.Signed, c_name='pypy_jit_start_addr') -def jit_start_addr(): - _memmngr = asmmemmgr._memmngr - - return _memmngr.jit_addr_map[0] - -@jit_entrypoint([], lltype.Signed, c_name='pypy_jit_end_addr') -def jit_end_addr(): - _memmngr = asmmemmgr._memmngr - - return _memmngr.jit_addr_map[-1] - -@jit_entrypoint([lltype.Signed], lltype.Signed, - c_name='pypy_find_codemap_at_addr') -def find_codemap_at_addr(addr): - _memmngr = asmmemmgr._memmngr - - res = bisect_tuple(_memmngr.jit_codemap, addr) - 1 - if res == len(_memmngr.jit_codemap): - return -1 - return res - -@jit_entrypoint([lltype.Signed, lltype.Signed, - rffi.CArrayPtr(lltype.Signed)], lltype.Signed, - c_name='pypy_yield_codemap_at_addr') -def yield_bytecode_at_addr(codemap_no, addr, current_pos_addr): - """ will return consecutive unique_ids from codemap, starting from position - `pos` until addr - """ - _memmngr = asmmemmgr._memmngr - - codemap = _memmngr.jit_codemap[codemap_no] - current_pos = current_pos_addr[0] - start_addr = codemap[0] - rel_addr = addr - start_addr - while True: - if current_pos >= len(codemap[2]): - return 0 - next_start = codemap[2][current_pos + 1] - if next_start > rel_addr: - return 0 - next_stop = codemap[2][current_pos + 2] - if next_stop > rel_addr: - current_pos_addr[0] = current_pos + 4 - return codemap[2][current_pos] - # we need to skip potentially more than one - current_pos = codemap[2][current_pos + 3] - -def unpack_traceback(addr): - codemap_pos = find_codemap_at_addr(addr) - assert codemap_pos >= 0 - storage = lltype.malloc(rffi.CArray(lltype.Signed), 1, flavor='raw') - storage[0] = 0 - res = [] - while True: - item = yield_bytecode_at_addr(codemap_pos, addr, storage) - if item == 0: - break - res.append(item) - lltype.free(storage, flavor='raw') - return res - - -class CodemapBuilder(object): - def __init__(self): - self.l = [] - self.patch_position = [] - self.last_call_depth = -1 - - def debug_merge_point(self, op, pos): - call_depth = op.getarg(1).getint() - if call_depth != self.last_call_depth: - unique_id = op.getarg(3).getint() - if unique_id == 0: # uninteresting case - return - assert unique_id & 1 == 0 - if call_depth > self.last_call_depth: - self.l.append(unique_id) - self.l.append(pos) # <- this is a relative pos - self.patch_position.append(len(self.l)) - self.l.append(0) # marker - self.l.append(0) # second marker - else: - for i in range(self.last_call_depth - call_depth): - to_patch = self.patch_position.pop() - self.l[to_patch] = pos - self.l[to_patch + 1] = len(self.l) - self.last_call_depth = call_depth - - def inherit_code_from_position(self, pos): - lst = unpack_traceback(pos) - self.last_call_depth = len(lst) - 1 - for item in lst: - self.l.append(item) - self.l.append(0) - self.patch_position.append(len(self.l)) - self.l.append(0) # marker - self.l.append(0) # second marker - - def get_final_bytecode(self, addr, size): - while self.patch_position: - pos = self.patch_position.pop() - self.l[pos] = size - self.l[pos + 1] = len(self.l) - # at the end there should be no zeros - for i in range(len(self.l) / 4): - item = self.l[i * 4] # unique_id - assert item > 0 # no zeros here - item = self.l[i * 4 + 2] # end in asm - assert item > 0 - item = self.l[i * 4 + 3] # end in l - assert item > 0 - return (addr, size, self.l) # XXX compact self.l - diff --git a/rpython/jit/backend/llsupport/llmodel.py b/rpython/jit/backend/llsupport/llmodel.py index 0bd229c657..34644dc7a4 100644 --- a/rpython/jit/backend/llsupport/llmodel.py +++ b/rpython/jit/backend/llsupport/llmodel.py @@ -16,7 +16,7 @@ from rpython.jit.backend.llsupport.descr import ( FieldDescr, ArrayDescr, CallDescr, InteriorFieldDescr, FLAG_POINTER, FLAG_FLOAT) from rpython.jit.backend.llsupport.memcpy import memset_fn -from rpython.jit.backend.llsupport import asmmemmgr +from rpython.jit.backend.llsupport.asmmemmgr import AsmMemoryManager from rpython.rlib.unroll import unrolling_iterable @@ -48,8 +48,7 @@ class AbstractLLCPU(AbstractCPU): self._setup_exception_handling_translated() else: self._setup_exception_handling_untranslated() - self.asmmemmgr = asmmemmgr.AsmMemoryManager() - asmmemmgr._memmngr = self.asmmemmgr + self.asmmemmgr = AsmMemoryManager() self._setup_frame_realloc(translate_support_code) ad = self.gc_ll_descr.getframedescrs(self).arraydescr self.signedarraydescr = ad diff --git a/rpython/jit/backend/llsupport/rewrite.py b/rpython/jit/backend/llsupport/rewrite.py index 0ff7f5d46a..1b63898904 100644 --- a/rpython/jit/backend/llsupport/rewrite.py +++ b/rpython/jit/backend/llsupport/rewrite.py @@ -17,6 +17,8 @@ FLAG_UNICODE = 2 class GcRewriterAssembler(object): """ This class performs the following rewrites on the list of operations: + - Remove the DEBUG_MERGE_POINTs. + - Turn all NEW_xxx to either a CALL_MALLOC_GC, or a CALL_MALLOC_NURSERY followed by SETFIELDs in order to initialize their GC fields. The two advantages of CALL_MALLOC_NURSERY is that it inlines the common @@ -58,6 +60,8 @@ class GcRewriterAssembler(object): # for i in range(len(operations)): op = operations[i] + if op.getopnum() == rop.DEBUG_MERGE_POINT: + continue # ---------- turn NEWxxx into CALL_MALLOC_xxx ---------- if op.is_malloc(): self.handle_malloc_operation(op) diff --git a/rpython/jit/backend/llsupport/test/test_asmmemmgr.py b/rpython/jit/backend/llsupport/test/test_asmmemmgr.py index 64ecf1f84b..1ef20c2598 100644 --- a/rpython/jit/backend/llsupport/test/test_asmmemmgr.py +++ b/rpython/jit/backend/llsupport/test/test_asmmemmgr.py @@ -2,7 +2,6 @@ import random from rpython.jit.backend.llsupport.asmmemmgr import AsmMemoryManager from rpython.jit.backend.llsupport.asmmemmgr import MachineDataBlockWrapper from rpython.jit.backend.llsupport.asmmemmgr import BlockBuilderMixin -from rpython.jit.backend.llsupport import asmmemmgr from rpython.rtyper.lltypesystem import lltype, rffi from rpython.rlib import debug @@ -158,7 +157,6 @@ class TestAsmMemoryManager: class FakeGcRootMap: def register_asm_addr(self, retaddr, mark): puts.append((retaddr, mark)) - # mc = BlockBuilderMixin() mc.writechar('X') @@ -268,16 +266,3 @@ def test_machinedatablock(): md.done() assert allblocks == [(1597, 1697), (1797, 1835)] assert ops == [('free', 1835, 1897)] - -def test_find_jit_frame_depth(): - mgr = AsmMemoryManager() - mgr.register_frame_depth_map(11, [0, 5, 10], [1, 2, 3]) - mgr.register_frame_depth_map(30, [0, 5, 10], [4, 5, 6]) - mgr.register_frame_depth_map(0, [0, 5, 10], [7, 8, 9]) - asmmemmgr._memmngr = mgr - assert asmmemmgr.stack_depth_at_loc(13) == 1 - assert asmmemmgr.stack_depth_at_loc(-3) == -1 - assert asmmemmgr.stack_depth_at_loc(41) == -1 - assert asmmemmgr.stack_depth_at_loc(5) == 8 - assert asmmemmgr.stack_depth_at_loc(17) == 2 - assert asmmemmgr.stack_depth_at_loc(38) == 5 diff --git a/rpython/jit/backend/llsupport/test/ztranslation_test.py b/rpython/jit/backend/llsupport/test/ztranslation_test.py index 83ca54fb0c..a9a4197c3f 100644 --- a/rpython/jit/backend/llsupport/test/ztranslation_test.py +++ b/rpython/jit/backend/llsupport/test/ztranslation_test.py @@ -2,7 +2,7 @@ import os, sys, py from rpython.tool.udir import udir from rpython.rlib.jit import JitDriver, unroll_parameters, set_param from rpython.rlib.jit import PARAMETERS, dont_look_inside -from rpython.rlib.jit import promote, _get_virtualizable_token +from rpython.rlib.jit import promote from rpython.rlib import jit_hooks, rposix from rpython.rlib.objectmodel import keepalive_until_here from rpython.rlib.rthread import ThreadLocalReference, ThreadLocalField @@ -28,15 +28,12 @@ class TranslationTest(CCompiledMixin): # - floats neg and abs # - llexternal with macro=True - class BasicFrame(object): + class Frame(object): _virtualizable_ = ['i'] def __init__(self, i): self.i = i - class Frame(BasicFrame): - pass - eci = ExternalCompilationInfo(post_include_bits=[''' #define pypy_my_fabs(x) fabs(x) ''']) @@ -62,7 +59,6 @@ class TranslationTest(CCompiledMixin): while frame.i > 3: jitdriver.can_enter_jit(frame=frame, total=total, j=j) jitdriver.jit_merge_point(frame=frame, total=total, j=j) - _get_virtualizable_token(frame) total += frame.i if frame.i >= 20: frame.i -= 2 diff --git a/rpython/jit/backend/x86/arch.py b/rpython/jit/backend/x86/arch.py index e428bf0251..f3d02d0080 100644 --- a/rpython/jit/backend/x86/arch.py +++ b/rpython/jit/backend/x86/arch.py @@ -51,6 +51,3 @@ else: THREADLOCAL_OFS = (FRAME_FIXED_SIZE - 1) * WORD assert PASS_ON_MY_FRAME >= 12 # asmgcc needs at least JIT_USE_WORDS + 3 - -# return address, followed by FRAME_FIXED_SIZE words -DEFAULT_FRAME_BYTES = (1 + FRAME_FIXED_SIZE) * WORD diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py index b95280afd2..c647a5c9c8 100644 --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -18,8 +18,7 @@ from rpython.jit.backend.x86.regalloc import (RegAlloc, get_ebp_ofs, from rpython.jit.backend.llsupport.regalloc import (get_scale, valid_addressing_size) from rpython.jit.backend.x86.arch import (FRAME_FIXED_SIZE, WORD, IS_X86_64, JITFRAME_FIXED_SIZE, IS_X86_32, - PASS_ON_MY_FRAME, THREADLOCAL_OFS, - DEFAULT_FRAME_BYTES) + PASS_ON_MY_FRAME, THREADLOCAL_OFS) from rpython.jit.backend.x86.regloc import (eax, ecx, edx, ebx, esp, ebp, esi, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, r8, r9, r10, r11, edi, r12, r13, r14, r15, X86_64_SCRATCH_REG, X86_64_XMM_SCRATCH_REG, @@ -67,7 +66,6 @@ class Assembler386(BaseAssembler): self._build_float_constants() def setup(self, looptoken): - BaseAssembler.setup(self, looptoken) assert self.memcpy_addr != 0, "setup_once() not called?" self.current_clt = looptoken.compiled_loop_token self.pending_guard_tokens = [] @@ -82,6 +80,7 @@ class Assembler386(BaseAssembler): allblocks) self.target_tokens_currently_compiling = {} self.frame_depth_to_patch = [] + self._finish_gcmap = lltype.nullptr(jitframe.GCMAP) def teardown(self): self.pending_guard_tokens = None @@ -268,10 +267,6 @@ class Assembler386(BaseAssembler): # the correct "ret" arg offset = mc.get_relative_pos() - jz_location mc.overwrite32(jz_location-4, offset) - # From now on this function is basically "merged" with - # its caller and so contains DEFAULT_FRAME_BYTES bytes - # plus my own return address, which we'll ignore next - mc.force_frame_size(DEFAULT_FRAME_BYTES + WORD) mc.ADD_ri(esp.value, WORD) mc.JMP(imm(self.propagate_exception_path)) # @@ -283,7 +278,6 @@ class Assembler386(BaseAssembler): return # not supported (for tests, or non-translated) # self.mc = codebuf.MachineCodeBlockWrapper() - self.mc.force_frame_size(DEFAULT_FRAME_BYTES) # # read and reset the current exception @@ -337,10 +331,7 @@ class Assembler386(BaseAssembler): offset = mc.get_relative_pos() - jnz_location assert 0 < offset <= 127 mc.overwrite(jnz_location-1, chr(offset)) - # From now on this function is basically "merged" with - # its caller and so contains DEFAULT_FRAME_BYTES bytes - # plus my own return address, which we'll ignore next - mc.force_frame_size(DEFAULT_FRAME_BYTES + WORD) + # adjust the esp to point back to the previous return mc.ADD_ri(esp.value, WORD) mc.JMP(imm(self.propagate_exception_path)) # @@ -418,8 +409,6 @@ class Assembler386(BaseAssembler): mc.LEA_rs(esp.value, 2 * WORD) self._pop_all_regs_from_frame(mc, [], withfloats, callee_only=True) mc.RET16_i(WORD) - # Note that wb_slowpath[0..3] end with a RET16_i, which must be - # taken care of in the caller by stack_frame_size_delta(-WORD) else: if IS_X86_32: mc.MOV_rs(edx.value, 4 * WORD) @@ -525,8 +514,6 @@ class Assembler386(BaseAssembler): assert len(set(inputargs)) == len(inputargs) self.setup(original_loop_token) - self.codemap.inherit_code_from_position(faildescr.adr_jump_offset) - self.mc.force_frame_size(DEFAULT_FRAME_BYTES) descr_number = compute_unique_id(faildescr) if log: operations = self._inject_debugging_code(faildescr, operations, @@ -687,12 +674,8 @@ class Assembler386(BaseAssembler): self.datablockwrapper.done() # finish using cpu.asmmemmgr self.datablockwrapper = None allblocks = self.get_asmmemmgr_blocks(looptoken) - size = self.mc.get_relative_pos() - res = self.mc.materialize(self.cpu.asmmemmgr, allblocks, - self.cpu.gc_ll_descr.gcrootmap) - self.cpu.asmmemmgr.register_codemap( - self.codemap.get_final_bytecode(res, size)) - return res + return self.mc.materialize(self.cpu.asmmemmgr, allblocks, + self.cpu.gc_ll_descr.gcrootmap) def patch_jump_for_descr(self, faildescr, adr_new_target): adr_jump_offset = faildescr.adr_jump_offset @@ -703,7 +686,6 @@ class Assembler386(BaseAssembler): # place, but clobber the recovery stub with a jump to the real # target. mc = codebuf.MachineCodeBlockWrapper() - mc.force_frame_size(DEFAULT_FRAME_BYTES) if rx86.fits_in_32bits(offset): mc.writeimm32(offset) mc.copy_to_raw_memory(adr_jump_offset) @@ -1774,7 +1756,6 @@ class Assembler386(BaseAssembler): def generate_propagate_error_64(self): assert WORD == 8 - self.mc.force_frame_size(DEFAULT_FRAME_BYTES) startpos = self.mc.get_relative_pos() self.mc.JMP(imm(self.propagate_exception_path)) return startpos @@ -1782,7 +1763,6 @@ class Assembler386(BaseAssembler): def generate_quick_failure(self, guardtok): """ Gather information about failure """ - self.mc.force_frame_size(DEFAULT_FRAME_BYTES) startpos = self.mc.get_relative_pos() fail_descr, target = self.store_info_on_descr(startpos, guardtok) self.mc.PUSH(imm(fail_descr)) @@ -1858,9 +1838,6 @@ class Assembler386(BaseAssembler): def _build_failure_recovery(self, exc, withfloats=False): mc = codebuf.MachineCodeBlockWrapper() - # this is jumped to, from a stack that has DEFAULT_FRAME_BYTES - # followed by 2 extra words just pushed - mc.force_frame_size(DEFAULT_FRAME_BYTES + 2 * WORD) self.mc = mc self._push_all_regs_to_frame(mc, [], withfloats) @@ -1932,7 +1909,6 @@ class Assembler386(BaseAssembler): self.mc.J_il(rx86.Conditions[condition], 0) else: self.mc.JMP_l(0) - self.mc.force_frame_size(DEFAULT_FRAME_BYTES) guard_token.pos_jump_offset = self.mc.get_relative_pos() - 4 self.pending_guard_tokens.append(guard_token) @@ -2044,7 +2020,6 @@ class Assembler386(BaseAssembler): offset = jmp_location - je_location assert 0 < offset <= 127 self.mc.overwrite(je_location - 1, chr(offset)) - self.mc.force_frame_size(DEFAULT_FRAME_BYTES) # return jmp_location @@ -2129,8 +2104,6 @@ class Assembler386(BaseAssembler): if is_frame and align_stack: mc.SUB_ri(esp.value, 16 - WORD) # erase the return address mc.CALL(imm(self.wb_slowpath[helper_num])) - if not is_frame: - mc.stack_frame_size_delta(-WORD) if is_frame and align_stack: mc.ADD_ri(esp.value, 16 - WORD) # erase the return address @@ -2367,7 +2340,6 @@ class Assembler386(BaseAssembler): offset = self.mc.get_relative_pos() - jmp_adr1 assert 0 < offset <= 127 self.mc.overwrite(jmp_adr1-1, chr(offset)) - self.mc.force_frame_size(DEFAULT_FRAME_BYTES) # write down the tid, but not if it's the result of the CALL self.mc.MOV(mem(eax, 0), imm(arraydescr.tid)) # while we're at it, this line is not needed if we've done the CALL diff --git a/rpython/jit/backend/x86/callbuilder.py b/rpython/jit/backend/x86/callbuilder.py index cc8c59cb74..ff8f1d24b9 100644 --- a/rpython/jit/backend/x86/callbuilder.py +++ b/rpython/jit/backend/x86/callbuilder.py @@ -58,7 +58,7 @@ class CallBuilderX86(AbstractCallBuilder): self.fnloc_is_immediate = False self.fnloc = None self.arglocs = arglocs + [fnloc] - self.start_frame_size = self.mc._frame_size + self.current_esp = 0 # 0 or (usually) negative, counted in bytes def select_call_release_gil_mode(self): AbstractCallBuilder.select_call_release_gil_mode(self) @@ -70,15 +70,13 @@ class CallBuilderX86(AbstractCallBuilder): def subtract_esp_aligned(self, count): if count > 0: align = align_stack_words(count) + self.current_esp -= align * WORD self.mc.SUB_ri(esp.value, align * WORD) - def get_current_esp(self): - return self.start_frame_size - self.mc._frame_size - def restore_stack_pointer(self, target_esp=0): - current_esp = self.get_current_esp() - if current_esp != target_esp: - self.mc.ADD_ri(esp.value, target_esp - current_esp) + if self.current_esp != target_esp: + self.mc.ADD_ri(esp.value, target_esp - self.current_esp) + self.current_esp = target_esp def load_result(self): """Overridden in CallBuilder32 and CallBuilder64""" @@ -101,10 +99,9 @@ class CallBuilderX86(AbstractCallBuilder): # after the rearrangements done just before, ignoring the return # value eax, if necessary assert not self.is_call_release_gil - current_esp = self.get_current_esp() - self.change_extra_stack_depth = (current_esp != 0) + self.change_extra_stack_depth = (self.current_esp != 0) if self.change_extra_stack_depth: - self.asm.set_extra_stack_depth(self.mc, -current_esp) + self.asm.set_extra_stack_depth(self.mc, -self.current_esp) noregs = self.asm.cpu.gc_ll_descr.is_shadow_stack() gcmap = self.asm._regalloc.get_gcmap([eax], noregs=noregs) self.asm.push_gcmap(self.mc, gcmap, store=True) @@ -145,7 +142,7 @@ class CallBuilderX86(AbstractCallBuilder): # and 5/7 words as described for asmgcroot.ASM_FRAMEDATA, for a # total size of JIT_USE_WORDS. This structure is found at # [ESP+css]. - css = -self.get_current_esp() + ( + css = -self.current_esp + ( WORD * (PASS_ON_MY_FRAME - asmgcroot.JIT_USE_WORDS)) assert css >= 2 * WORD # Save ebp @@ -181,7 +178,7 @@ class CallBuilderX86(AbstractCallBuilder): else: self.tlofs_reg = r12 self.mc.MOV_rs(self.tlofs_reg.value, - THREADLOCAL_OFS - self.get_current_esp()) + THREADLOCAL_OFS - self.current_esp) if self.asm._is_asmgcc(): self.mc.AND_ri(self.tlofs_reg.value, ~1) return self.tlofs_reg @@ -454,10 +451,7 @@ class CallBuilder32(CallBuilderX86): else: self.mc.CALL(self.fnloc) if self.callconv != FFI_DEFAULT_ABI: - # in the STDCALL ABI, the CALL above has an effect on - # the stack depth. Adjust 'mc._frame_size'. - delta = self._fix_stdcall(self.callconv) - self.mc.stack_frame_size_delta(-delta) + self.current_esp += self._fix_stdcall(self.callconv) def _fix_stdcall(self, callconv): from rpython.rlib.clibffi import FFI_STDCALL diff --git a/rpython/jit/backend/x86/codebuf.py b/rpython/jit/backend/x86/codebuf.py index 0547d16064..ade75b4b72 100644 --- a/rpython/jit/backend/x86/codebuf.py +++ b/rpython/jit/backend/x86/codebuf.py @@ -23,7 +23,6 @@ class MachineCodeBlockWrapper(BlockBuilderMixin, codebuilder_cls): def __init__(self): self.init_block_builder() - codebuilder_cls.__init__(self) # a list of relative positions; for each position p, the bytes # at [p-4:p] encode an absolute address that will need to be # made relative. Only works on 32-bit! diff --git a/rpython/jit/backend/x86/regalloc.py b/rpython/jit/backend/x86/regalloc.py index 9d1e4bfdac..70caf76510 100644 --- a/rpython/jit/backend/x86/regalloc.py +++ b/rpython/jit/backend/x86/regalloc.py @@ -12,7 +12,7 @@ from rpython.jit.backend.llsupport.regalloc import (FrameManager, BaseRegalloc, valid_addressing_size) from rpython.jit.backend.x86 import rx86 from rpython.jit.backend.x86.arch import (WORD, JITFRAME_FIXED_SIZE, IS_X86_32, - IS_X86_64, DEFAULT_FRAME_BYTES) + IS_X86_64) from rpython.jit.backend.x86.jump import remap_frame_layout_mixed from rpython.jit.backend.x86.regloc import (FrameLoc, RegLoc, ConstFloatLoc, FloatImmedLoc, ImmedLoc, imm, imm0, imm1, ecx, eax, edx, ebx, esi, edi, @@ -314,7 +314,6 @@ class RegAlloc(BaseRegalloc): while i < len(operations): op = operations[i] self.assembler.mc.mark_op(op) - assert self.assembler.mc._frame_size == DEFAULT_FRAME_BYTES self.rm.position = i self.xrm.position = i if op.has_no_side_effect() and op.result not in self.longevity: @@ -1324,7 +1323,7 @@ class RegAlloc(BaseRegalloc): assembler.closing_jump(self.jump_target_descr) def consider_debug_merge_point(self, op): - self.assembler.debug_merge_point(op) + pass def consider_jit_debug(self, op): pass diff --git a/rpython/jit/backend/x86/rx86.py b/rpython/jit/backend/x86/rx86.py index 2f1995ad60..f3a5aa6c76 100644 --- a/rpython/jit/backend/x86/rx86.py +++ b/rpython/jit/backend/x86/rx86.py @@ -454,11 +454,6 @@ def shifts(mod_field): class AbstractX86CodeBuilder(object): """Abstract base class.""" - def __init__(self): - self.frame_positions = [] - self.frame_assignments = [] - self.force_frame_size(self.WORD) - def writechar(self, char): raise NotImplementedError @@ -476,23 +471,6 @@ class AbstractX86CodeBuilder(object): self.writechar(chr((imm >> 16) & 0xFF)) self.writechar(chr((imm >> 24) & 0xFF)) - def force_frame_size(self, frame_size): - self.frame_positions.append(self.get_relative_pos()) - self.frame_assignments.append(frame_size) - self._frame_size = frame_size - - def stack_frame_size_delta(self, delta): - "Called when we generate an instruction that changes the value of ESP" - self._frame_size += delta - self.frame_positions.append(self.get_relative_pos()) - self.frame_assignments.append(self._frame_size) - assert self._frame_size >= self.WORD - - def check_stack_size_at_ret(self): - assert self._frame_size == self.WORD - if not we_are_translated(): - self._frame_size = None - # ------------------------------ MOV ------------------------------ MOV_ri = insn(register(1), '\xB8', immediate(2)) @@ -503,24 +481,14 @@ class AbstractX86CodeBuilder(object): INC_m = insn(rex_w, '\xFF', orbyte(0), mem_reg_plus_const(1)) INC_j = insn(rex_w, '\xFF', orbyte(0), abs_(1)) - AD1_ri,ADD_rr,ADD_rb,_,_,ADD_rm,ADD_rj,_,_ = common_modes(0) + ADD_ri,ADD_rr,ADD_rb,_,_,ADD_rm,ADD_rj,_,_ = common_modes(0) OR_ri, OR_rr, OR_rb, _,_,OR_rm, OR_rj, _,_ = common_modes(1) AND_ri,AND_rr,AND_rb,_,_,AND_rm,AND_rj,_,_ = common_modes(4) - SU1_ri,SUB_rr,SUB_rb,_,_,SUB_rm,SUB_rj,SUB_ji8,SUB_mi8 = common_modes(5) + SUB_ri,SUB_rr,SUB_rb,_,_,SUB_rm,SUB_rj,SUB_ji8,SUB_mi8 = common_modes(5) SBB_ri,SBB_rr,SBB_rb,_,_,SBB_rm,SBB_rj,_,_ = common_modes(3) XOR_ri,XOR_rr,XOR_rb,_,_,XOR_rm,XOR_rj,_,_ = common_modes(6) CMP_ri,CMP_rr,CMP_rb,CMP_bi,CMP_br,CMP_rm,CMP_rj,_,_ = common_modes(7) - def ADD_ri(self, reg, immed): - self.AD1_ri(reg, immed) - if reg == R.esp: - self.stack_frame_size_delta(-immed) - - def SUB_ri(self, reg, immed): - self.SU1_ri(reg, immed) - if reg == R.esp: - self.stack_frame_size_delta(+immed) - CMP_mi8 = insn(rex_w, '\x83', orbyte(7<<3), mem_reg_plus_const(1), immediate(2, 'b')) CMP_mi32 = insn(rex_w, '\x81', orbyte(7<<3), mem_reg_plus_const(1), immediate(2)) CMP_mi = select_8_or_32_bit_immed(CMP_mi8, CMP_mi32) @@ -570,65 +538,30 @@ class AbstractX86CodeBuilder(object): # ------------------------------ Misc stuff ------------------------------ NOP = insn('\x90') - RE1 = insn('\xC3') - RE116_i = insn('\xC2', immediate(1, 'h')) - - def RET(self): - self.check_stack_size_at_ret() - self.RE1() - - def RET16_i(self, immed): - self.check_stack_size_at_ret() - self.RE116_i(immed) - - PUS1_r = insn(rex_nw, register(1), '\x50') - PUS1_b = insn(rex_nw, '\xFF', orbyte(6<<3), stack_bp(1)) - PUS1_m = insn(rex_nw, '\xFF', orbyte(6<<3), mem_reg_plus_const(1)) - PUS1_i8 = insn('\x6A', immediate(1, 'b')) - PUS1_i32 = insn('\x68', immediate(1, 'i')) - - def PUSH_r(self, reg): - self.PUS1_r(reg) - self.stack_frame_size_delta(+self.WORD) - - def PUSH_b(self, ofs): - self.PUS1_b(ofs) - self.stack_frame_size_delta(+self.WORD) - - def PUSH_m(self, ofs): - self.PUS1_m(ofs) - self.stack_frame_size_delta(+self.WORD) - - def PUSH_i(self, immed): + RET = insn('\xC3') + RET16_i = insn('\xC2', immediate(1, 'h')) + + PUSH_r = insn(rex_nw, register(1), '\x50') + PUSH_b = insn(rex_nw, '\xFF', orbyte(6<<3), stack_bp(1)) + PUSH_m = insn(rex_nw, '\xFF', orbyte(6<<3), mem_reg_plus_const(1)) + PUSH_i8 = insn('\x6A', immediate(1, 'b')) + PUSH_i32 = insn('\x68', immediate(1, 'i')) + def PUSH_i(mc, immed): if single_byte(immed): - self.PUS1_i8(immed) + mc.PUSH_i8(immed) else: - self.PUS1_i32(immed) - self.stack_frame_size_delta(+self.WORD) - - PO1_r = insn(rex_nw, register(1), '\x58') - PO1_b = insn(rex_nw, '\x8F', orbyte(0<<3), stack_bp(1)) - - def POP_r(self, reg): - self.PO1_r(reg) - self.stack_frame_size_delta(-self.WORD) + mc.PUSH_i32(immed) - def POP_b(self, ofs): - self.PO1_b(ofs) - self.stack_frame_size_delta(-self.WORD) + POP_r = insn(rex_nw, register(1), '\x58') + POP_b = insn(rex_nw, '\x8F', orbyte(0<<3), stack_bp(1)) LEA_rb = insn(rex_w, '\x8D', register(1,8), stack_bp(2)) - LE1_rs = insn(rex_w, '\x8D', register(1,8), stack_sp(2)) + LEA_rs = insn(rex_w, '\x8D', register(1,8), stack_sp(2)) LEA32_rb = insn(rex_w, '\x8D', register(1,8),stack_bp(2,force_32bits=True)) LEA_ra = insn(rex_w, '\x8D', register(1, 8), mem_reg_plus_scaled_reg_plus_const(2)) LEA_rm = insn(rex_w, '\x8D', register(1, 8), mem_reg_plus_const(2)) LEA_rj = insn(rex_w, '\x8D', register(1, 8), abs_(2)) - def LEA_rs(self, reg, ofs): - self.LE1_rs(reg, ofs) - if reg == R.esp: - self.stack_frame_size_delta(-ofs) - CALL_l = insn('\xE8', relative(1)) CALL_r = insn(rex_nw, '\xFF', register(1), chr(0xC0 | (2<<3))) CALL_b = insn('\xFF', orbyte(2<<3), stack_bp(1)) @@ -639,30 +572,15 @@ class AbstractX86CodeBuilder(object): # register-register exchange. XCHG_rr = insn(rex_w, '\x87', register(1), register(2,8), '\xC0') - JM1_l = insn('\xE9', relative(1)) - JM1_r = insn(rex_nw, '\xFF', orbyte(4<<3), register(1), '\xC0') + JMP_l = insn('\xE9', relative(1)) + JMP_r = insn(rex_nw, '\xFF', orbyte(4<<3), register(1), '\xC0') # FIXME: J_il8 and JMP_l8 assume the caller will do the appropriate # calculation to find the displacement, but J_il does it for the caller. # We need to be consistent. - JM1_l8 = insn('\xEB', immediate(1, 'b')) + JMP_l8 = insn('\xEB', immediate(1, 'b')) J_il8 = insn(immediate(1, 'o'), '\x70', immediate(2, 'b')) J_il = insn('\x0F', immediate(1,'o'), '\x80', relative(2)) - def JMP_l(self, rel): - self.JM1_l(rel) - if not we_are_translated(): - self._frame_size = None - - def JMP_r(self, reg): - self.JM1_r(reg) - if not we_are_translated(): - self._frame_size = None - - def JMP_l8(self, rel): - self.JM1_l8(rel) - if not we_are_translated(): - self._frame_size = None - SET_ir = insn(rex_fw, '\x0F', immediate(1,'o'),'\x90', byte_register(2), '\xC0') # The 64-bit version of this, CQO, is defined in X86_64_CodeBuilder diff --git a/rpython/jit/backend/x86/test/test_basic.py b/rpython/jit/backend/x86/test/test_basic.py index 8bec774cf9..eba911e804 100644 --- a/rpython/jit/backend/x86/test/test_basic.py +++ b/rpython/jit/backend/x86/test/test_basic.py @@ -14,7 +14,7 @@ class Jit386Mixin(support.LLJitMixin): class TestBasic(Jit386Mixin, test_ajit.BaseLLtypeTests): # for the individual tests see - # ====> ../../../metainterp/test/test_ajit.py + # ====> ../../../metainterp/test/test_basic.py def test_bug(self): jitdriver = JitDriver(greens = [], reds = ['n']) class X(object): diff --git a/rpython/jit/backend/x86/test/test_callbuilder.py b/rpython/jit/backend/x86/test/test_callbuilder.py index f143501915..a0dcf8b61d 100644 --- a/rpython/jit/backend/x86/test/test_callbuilder.py +++ b/rpython/jit/backend/x86/test/test_callbuilder.py @@ -3,8 +3,7 @@ from rpython.jit.backend.x86.regloc import esi, edi, ebx, ecx, ImmedLoc class FakeAssembler: - class mc: - _frame_size = 42 + mc = None class _regalloc: class rm: free_regs = [ebx] diff --git a/rpython/jit/backend/x86/test/test_recursive.py b/rpython/jit/backend/x86/test/test_recursive.py index 9d0d821e08..05d120828e 100644 --- a/rpython/jit/backend/x86/test/test_recursive.py +++ b/rpython/jit/backend/x86/test/test_recursive.py @@ -1,26 +1,8 @@ from rpython.jit.metainterp.test.test_recursive import RecursiveTests from rpython.jit.backend.x86.test.test_basic import Jit386Mixin -from rpython.jit.backend.llsupport import asmmemmgr -from rpython.jit.backend.llsupport.codemap import unpack_traceback -from rpython.jit.backend.x86.arch import WORD class TestRecursive(Jit386Mixin, RecursiveTests): # for the individual tests see # ====> ../../../metainterp/test/test_recursive.py - def check_get_unique_id(self): - if WORD == 4: - return # this is 64 bit only check - codemaps = asmmemmgr._memmngr.jit_codemap[:] # ups, sorting later - assert len(codemaps) == 3 - codemaps.sort(lambda arg0, arg1: cmp(arg0[1], arg1[1])) - # biggest is the big loop, smallest is the bridge - assert unpack_traceback(codemaps[1][0]) == [] - # XXX very specific ASM addresses, very fragile test, but what we can - # do, really? 64bit only so far - assert unpack_traceback(codemaps[0][0]) == [2] - assert unpack_traceback(codemaps[1][0] + 100) == [2] - assert unpack_traceback(codemaps[2][0] + 100) == [4] - assert unpack_traceback(codemaps[2][0] + 200) == [4, 2] - assert unpack_traceback(codemaps[2][0] + 500) == [4, 2] - assert unpack_traceback(codemaps[2][0] + 380) == [4] + pass diff --git a/rpython/jit/backend/x86/test/test_regloc.py b/rpython/jit/backend/x86/test/test_regloc.py index 93f4ba7a74..ae78ac1cb2 100644 --- a/rpython/jit/backend/x86/test/test_regloc.py +++ b/rpython/jit/backend/x86/test/test_regloc.py @@ -10,18 +10,10 @@ from rpython.rlib.rarithmetic import intmask import py.test class LocationCodeBuilder32(CodeBuilder32, LocationCodeBuilder): - def force_frame_size(self, frame_size): - pass - - def stack_frame_size_delta(self, delta): - pass + pass class LocationCodeBuilder64(CodeBuilder64, LocationCodeBuilder): - def force_frame_size(self, frame_size): - pass - - def stack_frame_size_delta(self, delta): - pass + pass cb32 = LocationCodeBuilder32 cb64 = LocationCodeBuilder64 diff --git a/rpython/jit/backend/x86/test/test_rx86.py b/rpython/jit/backend/x86/test/test_rx86.py index 8ef214003a..d56e7c38e7 100644 --- a/rpython/jit/backend/x86/test/test_rx86.py +++ b/rpython/jit/backend/x86/test/test_rx86.py @@ -5,7 +5,6 @@ globals().update(R.__dict__) class CodeBuilderMixin(object): def __init__(self): self.buffer = [] - super(CodeBuilderMixin, self).__init__() def writechar(self, c): assert isinstance(c, str) and len(c) == 1 @@ -14,12 +13,6 @@ class CodeBuilderMixin(object): def getvalue(self): return ''.join(self.buffer) - def force_frame_size(self, frame_size): - pass - - def stack_frame_size_delta(self, delta): - pass - def assert_encodes_as(code_builder_cls, insn_name, args, expected_encoding): s = code_builder_cls() getattr(s, insn_name)(*args) diff --git a/rpython/jit/backend/x86/test/test_rx86_32_auto_encoding.py b/rpython/jit/backend/x86/test/test_rx86_32_auto_encoding.py index 53816b35b3..e528905ba4 100644 --- a/rpython/jit/backend/x86/test/test_rx86_32_auto_encoding.py +++ b/rpython/jit/backend/x86/test/test_rx86_32_auto_encoding.py @@ -33,12 +33,6 @@ class CodeCheckerMixin(object): def done(self): assert len(self.expected) == self.index - def stack_frame_size_delta(self, delta): - pass # ignored - - def check_stack_size_at_ret(self): - pass # ignored - def hexdump(s): return ' '.join(["%02X" % ord(c) for c in s]) diff --git a/rpython/jit/metainterp/logger.py b/rpython/jit/metainterp/logger.py index 6c70ed8dc0..b99aed8827 100644 --- a/rpython/jit/metainterp/logger.py +++ b/rpython/jit/metainterp/logger.py @@ -134,7 +134,7 @@ class LogOperations(object): def repr_of_resop(self, op, ops_offset=None): if op.getopnum() == rop.DEBUG_MERGE_POINT: jd_sd = self.metainterp_sd.jitdrivers_sd[op.getarg(0).getint()] - s = jd_sd.warmstate.get_location_str(op.getarglist()[4:]) + s = jd_sd.warmstate.get_location_str(op.getarglist()[3:]) s = s.replace(',', '.') # we use comma for argument splitting return "debug_merge_point(%d, %d, '%s')" % (op.getarg(1).getint(), op.getarg(2).getint(), s) if op.getopnum() == rop.JIT_DEBUG: diff --git a/rpython/jit/metainterp/pyjitpl.py b/rpython/jit/metainterp/pyjitpl.py index 43b0dd9667..d224025cd1 100644 --- a/rpython/jit/metainterp/pyjitpl.py +++ b/rpython/jit/metainterp/pyjitpl.py @@ -1180,9 +1180,7 @@ class MIFrame(object): # Note: the logger hides the jd_index argument, so we see in the logs: # debug_merge_point(portal_call_depth, current_call_id, 'location') # - unique_id = jitdriver_sd.warmstate.get_unique_id(greenkey) - args = [ConstInt(jd_index), ConstInt(portal_call_depth), - ConstInt(current_call_id), ConstInt(unique_id)] + greenkey + args = [ConstInt(jd_index), ConstInt(portal_call_depth), ConstInt(current_call_id)] + greenkey self.metainterp.history.record(rop.DEBUG_MERGE_POINT, args, None) @arguments("box", "label") diff --git a/rpython/jit/metainterp/test/test_ajit.py b/rpython/jit/metainterp/test/test_ajit.py index 533eaf2223..7982723ba0 100644 --- a/rpython/jit/metainterp/test/test_ajit.py +++ b/rpython/jit/metainterp/test/test_ajit.py @@ -4212,4 +4212,3 @@ class TestLLtype(BaseLLtypeTests, LLJitMixin): assert res == f(42) opname = "instance_ptr_%s" % cmp self.check_operations_history(**{opname: 0}) - diff --git a/rpython/jit/metainterp/test/test_jitdriver.py b/rpython/jit/metainterp/test/test_jitdriver.py index b01e19beb0..ef6f96f3be 100644 --- a/rpython/jit/metainterp/test/test_jitdriver.py +++ b/rpython/jit/metainterp/test/test_jitdriver.py @@ -188,28 +188,6 @@ class MultipleJitDriversTests(object): listops=True, inline=True) self.check_resops(call_assembler=0) - def test_get_unique_id(self): - def get_unique_id(pc): - return pc + 1 - - driver = JitDriver(greens=["pc"], reds='auto', - get_unique_id=get_unique_id) - - def f(): - i = 0 - pc = 0 - while i < 10: - driver.jit_merge_point(pc=pc) - pc += 1 - if pc == 3: - pc = 0 - i += 1 - - self.meta_interp(f, []) - loop = get_stats().loops[0] - for op in loop.operations: - if op.getopname() == 'debug_merge_point': - assert op.getarg(3).getint() == op.getarg(4).getint() + 1 class TestLLtype(MultipleJitDriversTests, LLJitMixin): pass diff --git a/rpython/jit/metainterp/test/test_recursive.py b/rpython/jit/metainterp/test/test_recursive.py index 0bffa3bf66..ca73b0c7c7 100644 --- a/rpython/jit/metainterp/test/test_recursive.py +++ b/rpython/jit/metainterp/test/test_recursive.py @@ -1296,29 +1296,6 @@ class RecursiveTests: self.meta_interp(portal, [0]) self.check_trace_count_at_most(2) # and not, e.g., 24 - def test_get_unique_id(self): - def get_unique_id(pc, code): - return (code + 1) * 2 - - driver = JitDriver(greens=["pc", "code"], reds='auto', - get_unique_id=get_unique_id) - - def f(pc, code): - i = 0 - while i < 10: - driver.jit_merge_point(pc=pc, code=code) - pc += 1 - if pc == 3: - if code == 1: - f(0, 0) - pc = 0 - i += 1 - - self.meta_interp(f, [0, 1], inline=True) - self.check_get_unique_id() # overloaded on assembler backends - - def check_get_unique_id(self): - pass class TestLLtype(RecursiveTests, LLJitMixin): pass diff --git a/rpython/jit/metainterp/warmspot.py b/rpython/jit/metainterp/warmspot.py index b8ed9fba97..4813ce973a 100644 --- a/rpython/jit/metainterp/warmspot.py +++ b/rpython/jit/metainterp/warmspot.py @@ -25,8 +25,6 @@ from rpython.jit.codewriter import support, codewriter from rpython.jit.codewriter.policy import JitPolicy from rpython.jit.codewriter.effectinfo import EffectInfo from rpython.jit.metainterp.optimizeopt import ALL_OPTS_NAMES -from rpython.rlib.entrypoint import all_jit_entrypoints,\ - annotated_jit_entrypoints # ____________________________________________________________ @@ -230,7 +228,6 @@ class WarmRunnerDesc(object): verbose = False # not self.cpu.translate_support_code self.rewrite_access_helpers() - self.create_jit_entry_points() self.codewriter.make_jitcodes(verbose=verbose) self.rewrite_can_enter_jits() self.rewrite_set_param_and_get_stats() @@ -533,8 +530,6 @@ class WarmRunnerDesc(object): for jd in self.jitdrivers_sd: jd._get_printable_location_ptr = self._make_hook_graph(jd, annhelper, jd.jitdriver.get_printable_location, s_Str) - jd._get_unique_id_ptr = self._make_hook_graph(jd, - annhelper, jd.jitdriver.get_unique_id, annmodel.SomeInteger()) jd._confirm_enter_jit_ptr = self._make_hook_graph(jd, annhelper, jd.jitdriver.confirm_enter_jit, annmodel.s_Bool, onlygreens=False) @@ -681,11 +676,6 @@ class WarmRunnerDesc(object): op = block.operations[index] self.rewrite_access_helper(op) - def create_jit_entry_points(self): - for func, args, result in all_jit_entrypoints: - self.helper_func(lltype.Ptr(lltype.FuncType(args, result)), func) - annotated_jit_entrypoints.append((func, None)) - def rewrite_access_helper(self, op): # make sure we make a copy of function so it no longer belongs # to extregistry diff --git a/rpython/jit/metainterp/warmstate.py b/rpython/jit/metainterp/warmstate.py index 0ff4e44693..6c9c6bb4ba 100644 --- a/rpython/jit/metainterp/warmstate.py +++ b/rpython/jit/metainterp/warmstate.py @@ -572,7 +572,6 @@ class WarmEnterState(object): JitCell = self.make_jitcell_subclass() jd = self.jitdriver_sd cpu = self.cpu - rtyper = self.warmrunnerdesc.rtyper def can_inline_callable(greenkey): greenargs = unwrap_greenkey(greenkey) @@ -598,6 +597,7 @@ class WarmEnterState(object): def should_unroll_one_iteration(greenkey): return False else: + rtyper = self.warmrunnerdesc.rtyper inline_ptr = jd._should_unroll_one_iteration_ptr def should_unroll_one_iteration(greenkey): greenargs = unwrap_greenkey(greenkey) @@ -631,6 +631,7 @@ class WarmEnterState(object): def get_location_str(greenkey): return missing else: + rtyper = self.warmrunnerdesc.rtyper unwrap_greenkey = self.make_unwrap_greenkey() # the following missing text should not be seen, as it is # returned only if debug_prints are currently not enabled, @@ -654,6 +655,7 @@ class WarmEnterState(object): def confirm_enter_jit(*args): return True else: + rtyper = self.warmrunnerdesc.rtyper # def confirm_enter_jit(*args): fn = support.maybe_on_top_of_llinterp(rtyper, @@ -666,15 +668,10 @@ class WarmEnterState(object): def can_never_inline(*greenargs): return False else: + rtyper = self.warmrunnerdesc.rtyper # def can_never_inline(*greenargs): fn = support.maybe_on_top_of_llinterp(rtyper, can_never_inline_ptr) return fn(*greenargs) self.can_never_inline = can_never_inline - get_unique_id_ptr = self.jitdriver_sd._get_unique_id_ptr - def get_unique_id(greenkey): - greenargs = unwrap_greenkey(greenkey) - fn = support.maybe_on_top_of_llinterp(rtyper, get_unique_id_ptr) - return fn(*greenargs) - self.get_unique_id = get_unique_id diff --git a/rpython/rlib/entrypoint.py b/rpython/rlib/entrypoint.py index 18c94b19fb..34f29e8993 100644 --- a/rpython/rlib/entrypoint.py +++ b/rpython/rlib/entrypoint.py @@ -5,22 +5,11 @@ from rpython.rtyper.lltypesystem import lltype, rffi from rpython.rtyper.lltypesystem.lloperation import llop from rpython.rlib.objectmodel import we_are_translated -annotated_jit_entrypoints = [] def export_symbol(func): func.exported_symbol = True return func -all_jit_entrypoints = [] - -def jit_entrypoint(argtypes, restype, c_name): - def deco(func): - func.c_name = c_name - func.relax_sig_check = True - export_symbol(func) - all_jit_entrypoints.append((func, argtypes, restype)) - return func - return deco def entrypoint_lowlevel(key, argtypes, c_name=None, relax=False): """ Note: entrypoint should call llop.gc_stack_bottom on it's own. diff --git a/rpython/rlib/jit.py b/rpython/rlib/jit.py index 973a635d1c..cdc980f713 100644 --- a/rpython/rlib/jit.py +++ b/rpython/rlib/jit.py @@ -292,39 +292,6 @@ def we_are_jitted(): _we_are_jitted = CDefinedIntSymbolic('0 /* we are not jitted here */', default=0) -def _get_virtualizable_token(frame): - """ An obscure API to get vable token. - Used by _vmprof - """ - from rpython.rtyper.lltypesystem import lltype, llmemory - - return lltype.nullptr(llmemory.GCREF.TO) - -class GetVirtualizableTokenEntry(ExtRegistryEntry): - _about_ = _get_virtualizable_token - - def compute_result_annotation(self, s_arg): - from rpython.rtyper.llannotation import SomePtr - from rpython.rtyper.lltypesystem import llmemory - return SomePtr(llmemory.GCREF) - - def specialize_call(self, hop): - from rpython.rtyper.lltypesystem import lltype, llmemory - - hop.exception_cannot_occur() - T = hop.args_r[0].lowleveltype.TO - v = hop.inputarg(hop.args_r[0], arg=0) - while not hasattr(T, 'vable_token'): - if not hasattr(T, 'super'): - # we're not really in a jitted build - return hop.inputconst(llmemory.GCREF, - lltype.nullptr(llmemory.GCREF.TO)) - T = T.super - v = hop.genop('cast_pointer', [v], resulttype=lltype.Ptr(T)) - c_vable_token = hop.inputconst(lltype.Void, 'vable_token') - return hop.genop('getfield', [v, c_vable_token], - resulttype=llmemory.GCREF) - class Entry(ExtRegistryEntry): _about_ = we_are_jitted @@ -545,8 +512,7 @@ class JitDriver(object): get_jitcell_at=None, set_jitcell_at=None, get_printable_location=None, confirm_enter_jit=None, can_never_inline=None, should_unroll_one_iteration=None, - name='jitdriver', check_untranslated=True, - get_unique_id=None): + name='jitdriver', check_untranslated=True): if greens is not None: self.greens = greens self.name = name @@ -578,9 +544,6 @@ class JitDriver(object): assert get_jitcell_at is None, "get_jitcell_at no longer used" assert set_jitcell_at is None, "set_jitcell_at no longer used" self.get_printable_location = get_printable_location - if get_unique_id is None: - get_unique_id = lambda *args: 0 - self.get_unique_id = get_unique_id self.confirm_enter_jit = confirm_enter_jit self.can_never_inline = can_never_inline self.should_unroll_one_iteration = should_unroll_one_iteration diff --git a/rpython/rlib/rbisect.py b/rpython/rlib/rbisect.py deleted file mode 100644 index ba82530af8..0000000000 --- a/rpython/rlib/rbisect.py +++ /dev/null @@ -1,19 +0,0 @@ - -def bisect(a, x): - lo = 0 - hi = len(a) - while lo < hi: - mid = (lo+hi)//2 - if x < a[mid]: hi = mid - else: lo = mid+1 - return lo - -# a copy of the above, but compares the first item of a tuple only -def bisect_tuple(a, x): - lo = 0 - hi = len(a) - while lo < hi: - mid = (lo+hi)//2 - if x < a[mid][0]: hi = mid - else: lo = mid+1 - return lo diff --git a/rpython/rlib/test/test_rbisect.py b/rpython/rlib/test/test_rbisect.py deleted file mode 100644 index bd06860259..0000000000 --- a/rpython/rlib/test/test_rbisect.py +++ /dev/null @@ -1,47 +0,0 @@ - -from rpython.rlib.rbisect import bisect - -def test_bisect(): - cases = [ - ([], 1, 0), - ([1], 0, 0), - ([1], 1, 1), - ([1], 2, 1), - ([1, 1], 0, 0), - ([1, 1], 1, 2), - ([1, 1], 2, 2), - ([1, 1, 1], 0, 0), - ([1, 1, 1], 1, 3), - ([1, 1, 1], 2, 3), - ([1, 1, 1, 1], 0, 0), - ([1, 1, 1, 1], 1, 4), - ([1, 1, 1, 1], 2, 4), - ([1, 2], 0, 0), - ([1, 2], 1, 1), - ([1, 2], 1.5, 1), - ([1, 2], 2, 2), - ([1, 2], 3, 2), - ([1, 1, 2, 2], 0, 0), - ([1, 1, 2, 2], 1, 2), - ([1, 1, 2, 2], 1.5, 2), - ([1, 1, 2, 2], 2, 4), - ([1, 1, 2, 2], 3, 4), - ([1, 2, 3], 0, 0), - ([1, 2, 3], 1, 1), - ([1, 2, 3], 1.5, 1), - ([1, 2, 3], 2, 2), - ([1, 2, 3], 2.5, 2), - ([1, 2, 3], 3, 3), - ([1, 2, 3], 4, 3), - ([1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 0, 0), - ([1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 1, 1), - ([1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 1.5, 1), - ([1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 2, 3), - ([1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 2.5, 3), - ([1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 3, 6), - ([1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 3.5, 6), - ([1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 4, 10), - ([1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 5, 10), - ] - for lst, elem, exp in cases: - assert bisect(lst, elem) == exp diff --git a/rpython/tool/jitlogparser/parser.py b/rpython/tool/jitlogparser/parser.py index d02f69a26a..ee8f64155b 100644 --- a/rpython/tool/jitlogparser/parser.py +++ b/rpython/tool/jitlogparser/parser.py @@ -376,37 +376,24 @@ def adjust_bridges(loop, bridges): i += 1 return res -def parse_addresses(part, callback=None): + +def import_log(logname, ParserCls=SimpleParser): + log = parse_log_file(logname) hex_re = '0x(-?[\da-f]+)' addrs = {} - if callback is None: - def callback(addr, stop_addr, bootstrap_addr, name, code_name): - addrs.setdefault(bootstrap_addr, []).append(name) - for entry in part: - m = re.search('has address %(hex)s to %(hex)s \(bootstrap %(hex)s' % - {'hex': hex_re}, entry) + for entry in extract_category(log, 'jit-backend-addr'): + m = re.search('bootstrap ' + hex_re, entry) if not m: # a bridge - m = re.search('has address ' + hex_re + ' to ' + hex_re, entry) + m = re.search('has address ' + hex_re, entry) addr = int(m.group(1), 16) - bootstrap_addr = addr - stop_addr = int(m.group(2), 16) entry = entry.lower() m = re.search('guard ' + hex_re, entry) name = 'guard ' + m.group(1) - code_name = 'bridge' else: name = entry[:entry.find('(') - 1].lower() addr = int(m.group(1), 16) - stop_addr = int(m.group(2), 16) - bootstrap_addr = int(m.group(3), 16) - code_name = entry[entry.find('(') + 1:m.span(0)[0] - 2] - callback(addr, stop_addr, bootstrap_addr, name, code_name) - return addrs - -def import_log(logname, ParserCls=SimpleParser): - log = parse_log_file(logname) - addrs = parse_addresses(extract_category(log, 'jit-backend-addr')) + addrs.setdefault(addr, []).append(name) from rpython.jit.backend.tool.viewcode import World world = World() for entry in extract_category(log, 'jit-backend-dump'): diff --git a/rpython/translator/c/genc.py b/rpython/translator/c/genc.py index 2e9cf3f493..8ad65ea9de 100644 --- a/rpython/translator/c/genc.py +++ b/rpython/translator/c/genc.py @@ -437,11 +437,10 @@ class CStandaloneBuilder(CBuilder): mk.definition('PYTHON', get_recent_cpython_executable()) - mk.definition('GCMAPFILES', '$(subst .asmgcc.s,.gcmap,$(subst .c,.gcmap,$(SOURCES)))') - mk.definition('OBJECTS1', '$(subst .asmgcc.s,.o,$(subst .c,.o,$(SOURCES)))') + mk.definition('GCMAPFILES', '$(subst .c,.gcmap,$(SOURCES))') + mk.definition('OBJECTS1', '$(subst .c,.o,$(SOURCES))') mk.definition('OBJECTS', '$(OBJECTS1) gcmaptable.s') - # the rule that transforms %.c into %.o, by compiling it to # %.s, then applying trackgcroot to get %.lbl.s and %.gcmap, and # finally by using the assembler ($(CC) again for now) to get %.o @@ -454,14 +453,6 @@ class CStandaloneBuilder(CBuilder): 'mv $*.gctmp $*.gcmap', 'rm $*.s $*.lbl.s']) - # this is for manually written assembly files which needs to be parsed by asmgcc - mk.rule('%.o %.gcmap', '%.asmgcc.s', [ - '$(PYTHON) $(RPYDIR)/translator/c/gcc/trackgcroot.py ' - '-t $*.asmgcc.s > $*.gctmp', - '$(CC) -o $*.o -c $*.asmgcc.lbl.s', - 'mv $*.gctmp $*.gcmap', - 'rm $*.asmgcc.lbl.s']) - # the rule to compute gcmaptable.s mk.rule('gcmaptable.s', '$(GCMAPFILES)', [ diff --git a/rpython/translator/driver.py b/rpython/translator/driver.py index ea4d5c148b..ebe7f8b405 100644 --- a/rpython/translator/driver.py +++ b/rpython/translator/driver.py @@ -10,8 +10,7 @@ from rpython.annotator.listdef import s_list_of_strings from rpython.annotator import policy as annpolicy from rpython.tool.udir import udir from rpython.rlib.debug import debug_start, debug_print, debug_stop -from rpython.rlib.entrypoint import secondary_entrypoints,\ - annotated_jit_entrypoints +from rpython.rlib.entrypoint import secondary_entrypoints import py from rpython.tool.ansi_print import ansi_log @@ -417,11 +416,10 @@ class TranslationDriver(SimpleTaskEngine): from rpython.translator.c.genc import CStandaloneBuilder cbuilder = CStandaloneBuilder(self.translator, self.entry_point, config=self.config, - secondary_entrypoints= - self.secondary_entrypoints + annotated_jit_entrypoints) + secondary_entrypoints=self.secondary_entrypoints) else: from rpython.translator.c.dlltool import CLibraryBuilder - functions = [(self.entry_point, None)] + self.secondary_entrypoints + annotated_jit_entrypoints + functions = [(self.entry_point, None)] + self.secondary_entrypoints cbuilder = CLibraryBuilder(self.translator, self.entry_point, functions=functions, name='libtesting', |