From patchwork Thu Jan 9 23:16:58 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Ian Lance Taylor X-Patchwork-Id: 308971 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 274D52C008F for ; Fri, 10 Jan 2014 10:17:16 +1100 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:mime-version:content-type; q=dns; s= default; b=NacyZE3hCqo1kPAagbv2oFHYwv08yvvmnJrMvKAHeD9rY7dekJmBE w00DwidlFNkLxHtTzEgP07n0STeKlYudYhiHrRA+DaOdKKtXCktYqa+RdxjRBOYN G5h2ecIumNKN8Kjk5EL1cDO5tQ1VU/GIbVDicQjd7+tjFUnG9jQJEk= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:mime-version:content-type; s= default; bh=d6QiKlSIZ28JUm5jmx50QnH4E7g=; b=NQATKVTRiDIcsGFNFA5C z9THs476qBP/SrOsnUKBQFRRPxgCpA+q1K5ApDHzQMgAZaBolkF5znx7+98vGqh8 +iOXIFmx/5UeFcf1DxPkKppoaz7Wb9FWeytfdSVYT8Ydi7Go9YK7uzp8a8G+/wq4 O342AEvWekI3ZkAQTng+Cao= Received: (qmail 19678 invoked by alias); 9 Jan 2014 23:17:05 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 19665 invoked by uid 89); 9 Jan 2014 23:17:04 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=1.6 required=5.0 tests=AWL, BAYES_50, RCVD_IN_DNSWL_LOW, RP_MATCHES_RCVD, SEM_URI, SEM_URIRED, SPF_PASS autolearn=no version=3.3.2 X-HELO: mail-pa0-f45.google.com Received: from mail-pa0-f45.google.com (HELO mail-pa0-f45.google.com) (209.85.220.45) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Thu, 09 Jan 2014 23:17:03 +0000 Received: by mail-pa0-f45.google.com with SMTP id rd3so2404817pab.18 for ; Thu, 09 Jan 2014 15:17:01 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:subject:date:message-id:user-agent :mime-version:content-type; bh=Yz4+J4annK5L+w5cuvWqjPONtZ5OzbgYD4hd2kDIZuQ=; b=Jht12JgO9dNCprFSzq4Ht6w5ifK0Ov5pYvSHot5+1+Kpy2Ru+ZHtjpL4E5vrIuQf0d fc0iFMs3VgKPN19QRCe+l8+Mm9u8rTvUwRZeRdOqXBHh4bP3id42ZlO6hvgFFZbUakKy Kv9JoqlS3kFAqLkBNW7n71n/cOZeRm6ru/maGXsvCEZwANyr7h6loYFEfK3TiFAgYCyJ JWEue7DId2LqkT62PZVGYEILLERaGS8Byf1BMKge+SMtx0AvhjN7xFhfRCcvTdlcBiUi 1K1EMGResfFAFCWUvbkpSJH+KhnwGUi3JDOa/DBiOw6iMNcyUZ/4GGmjgX720Ly5jnfc nKSg== X-Gm-Message-State: ALoCoQmsmFjFaJSpzlwrwZzyVREbnxw5y3/Tm7HbL37rEkhmurtIqd2ckgxu+blBUVUIOg0ffbJGqcFsNgQ5iCay3Lpy6pFOs2N/0UIQ0IdHSBceR1CRiZpNzucyBvW4A0NALBSdCDueS7hkL+qNbCt/qaHo5CdSCELUO9ILULAiJAwej3sSF5B1QhEVz/KGRscb2WknozR2uL2ATAln0+9KEnHhHZK7mw== X-Received: by 10.68.57.98 with SMTP id h2mr6831808pbq.17.1389309421247; Thu, 09 Jan 2014 15:17:01 -0800 (PST) Received: from iant-glaptop.roam.corp.google.com.google.com ([172.19.251.148]) by mx.google.com with ESMTPSA id sy10sm15933318pac.15.2014.01.09.15.16.59 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Thu, 09 Jan 2014 15:17:00 -0800 (PST) From: Ian Lance Taylor To: gcc-patches@gcc.gnu.org, gofrontend-dev@googlegroups.com Subject: libgo patch committed: Fix 32-bit memory allocation Date: Thu, 09 Jan 2014 15:16:58 -0800 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.3 (gnu/linux) MIME-Version: 1.0 X-IsSubscribed: yes This patch to libgo fixes memory allocation on 32-bit systems when a lot of memory has been allocated. The problem is described in this patch to the master repository: https://codereview.appspot.com/49460043 . runtime: fix 32-bit malloc for pointers >= 0x80000000 The spans array is allocated in runtime·mallocinit. On a 32-bit system the number of entries in the spans array is MaxArena32 / PageSize, which (2U << 30) / (1 << 12) == (1 << 19). So we are allocating an array that can hold 19 bits for an index that can hold 20 bits. According to the comment in the function, this is intentional: we only allocate enough spans (and bitmaps) for a 2G arena, because allocating more would probably be wasteful. But since the span index is simply the upper 20 bits of the memory address, this scheme only works if memory addresses are limited to the low 2G of memory. That would be OK if we were careful to enforce it, but we're not. What we are careful to enforce, in functions like runtime·MHeap_SysAlloc, is that we always return addresses between the heap's arena_start and arena_start + MaxArena32. We generally get away with it because we start allocating just after the program end, so we only run into trouble with programs that allocate a lot of memory, enough to get past address 0x80000000. This changes the code that computes a span index to subtract arena_start on 32-bit systems just as we currently do on 64-bit systems. This is the same patch applied to libgo. Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu, both 64-bit and 32-bit. Committed to mainline. Ian diff -r f3e5e6e92709 libgo/runtime/malloc.goc --- a/libgo/runtime/malloc.goc Wed Jan 08 13:58:47 2014 -0800 +++ b/libgo/runtime/malloc.goc Thu Jan 09 15:12:36 2014 -0800 @@ -637,8 +637,7 @@ // (Manually inlined copy of runtime_MHeap_Lookup) p = (uintptr)v>>PageShift; - if(sizeof(void*) == 8) - p -= (uintptr)runtime_mheap.arena_start >> PageShift; + p -= (uintptr)runtime_mheap.arena_start >> PageShift; s = runtime_mheap.spans[p]; if(s->sizeclass == 0) { diff -r f3e5e6e92709 libgo/runtime/mgc0.c --- a/libgo/runtime/mgc0.c Wed Jan 08 13:58:47 2014 -0800 +++ b/libgo/runtime/mgc0.c Thu Jan 09 15:12:36 2014 -0800 @@ -269,8 +269,7 @@ // (Manually inlined copy of MHeap_LookupMaybe.) k = (uintptr)obj>>PageShift; x = k; - if(sizeof(void*) == 8) - x -= (uintptr)runtime_mheap.arena_start>>PageShift; + x -= (uintptr)runtime_mheap.arena_start>>PageShift; s = runtime_mheap.spans[x]; if(s == nil || k < s->start || (byte*)obj >= s->limit || s->state != MSpanInUse) return false; @@ -453,8 +452,7 @@ // (Manually inlined copy of MHeap_LookupMaybe.) k = (uintptr)obj>>PageShift; x = k; - if(sizeof(void*) == 8) - x -= (uintptr)arena_start>>PageShift; + x -= (uintptr)arena_start>>PageShift; s = runtime_mheap.spans[x]; if(s == nil || k < s->start || obj >= s->limit || s->state != MSpanInUse) continue; @@ -501,8 +499,7 @@ // Ask span about size class. // (Manually inlined copy of MHeap_Lookup.) x = (uintptr)obj >> PageShift; - if(sizeof(void*) == 8) - x -= (uintptr)arena_start>>PageShift; + x -= (uintptr)arena_start>>PageShift; s = runtime_mheap.spans[x]; PREFETCH(obj); @@ -617,8 +614,7 @@ if(t == nil) return; x = (uintptr)obj >> PageShift; - if(sizeof(void*) == 8) - x -= (uintptr)(runtime_mheap.arena_start)>>PageShift; + x -= (uintptr)(runtime_mheap.arena_start)>>PageShift; s = runtime_mheap.spans[x]; objstart = (byte*)((uintptr)s->start<sizeclass != 0) { diff -r f3e5e6e92709 libgo/runtime/mheap.c --- a/libgo/runtime/mheap.c Wed Jan 08 13:58:47 2014 -0800 +++ b/libgo/runtime/mheap.c Thu Jan 09 15:12:36 2014 -0800 @@ -73,8 +73,7 @@ // Map spans array, PageSize at a time. n = (uintptr)h->arena_used; - if(sizeof(void*) == 8) - n -= (uintptr)h->arena_start; + n -= (uintptr)h->arena_start; n = n / PageSize * sizeof(h->spans[0]); n = ROUND(n, PageSize); pagesize = getpagesize(); @@ -170,8 +169,7 @@ runtime_MSpan_Init(t, s->start + npage, s->npages - npage); s->npages = npage; p = t->start; - if(sizeof(void*) == 8) - p -= ((uintptr)h->arena_start>>PageShift); + p -= ((uintptr)h->arena_start>>PageShift); if(p > 0) h->spans[p-1] = s; h->spans[p] = t; @@ -189,8 +187,7 @@ s->elemsize = (sizeclass==0 ? s->npages<types.compression = MTypes_Empty; p = s->start; - if(sizeof(void*) == 8) - p -= ((uintptr)h->arena_start>>PageShift); + p -= ((uintptr)h->arena_start>>PageShift); for(n=0; nspans[p+n] = s; return s; @@ -258,8 +255,7 @@ s = runtime_FixAlloc_Alloc(&h->spanalloc); runtime_MSpan_Init(s, (uintptr)v>>PageShift, ask>>PageShift); p = s->start; - if(sizeof(void*) == 8) - p -= ((uintptr)h->arena_start>>PageShift); + p -= ((uintptr)h->arena_start>>PageShift); h->spans[p] = s; h->spans[p + s->npages - 1] = s; s->state = MSpanInUse; @@ -276,8 +272,7 @@ uintptr p; p = (uintptr)v; - if(sizeof(void*) == 8) - p -= (uintptr)h->arena_start; + p -= (uintptr)h->arena_start; return h->spans[p >> PageShift]; } @@ -298,8 +293,7 @@ return nil; p = (uintptr)v>>PageShift; q = p; - if(sizeof(void*) == 8) - q -= (uintptr)h->arena_start >> PageShift; + q -= (uintptr)h->arena_start >> PageShift; s = h->spans[q]; if(s == nil || p < s->start || (byte*)v >= s->limit || s->state != MSpanInUse) return nil; @@ -346,8 +340,7 @@ // Coalesce with earlier, later spans. p = s->start; - if(sizeof(void*) == 8) - p -= (uintptr)h->arena_start >> PageShift; + p -= (uintptr)h->arena_start >> PageShift; if(p > 0 && (t = h->spans[p-1]) != nil && t->state != MSpanInUse) { if(t->npreleased == 0) { // cant't touch this otherwise tp = (uintptr*)(t->start<