mirror of
https://github.com/golang/go
synced 2024-11-22 01:44:40 -07:00
runtime: closures, defer bug fix for Native Client
Enable package tests for Native Client build. R=r CC=golang-dev https://golang.org/cl/957042
This commit is contained in:
parent
6e80a01ab7
commit
c6138efbcb
15
misc/nacl/naclrun
Executable file
15
misc/nacl/naclrun
Executable file
@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Copyright 2010 The Go Authors. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style
|
||||||
|
# license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
# Run nacl binary in debug mode (allow file access)
|
||||||
|
# and then grep away the chatter.
|
||||||
|
# See ../../src/pkg/exp/nacl/README for more on
|
||||||
|
# how to configure NaCl.
|
||||||
|
|
||||||
|
nacl -d "$@" >/tmp/nacl.out.$$ 2>&1
|
||||||
|
status=$?
|
||||||
|
egrep -v 'DEBUG MODE ENABLED|^\[[0-9]+,' /tmp/nacl.out.$$
|
||||||
|
rm -f /tmp/nacl.out.$$
|
||||||
|
exit $status
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
export GOARCH=386
|
export GOARCH=386
|
||||||
export GOOS=nacl
|
export GOOS=nacl
|
||||||
|
export GORUN="$GOROOT/misc/nacl/naclrun"
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
bash make.bash
|
bash make.bash
|
||||||
@ -17,6 +18,11 @@ xcd() {
|
|||||||
builtin cd $1
|
builtin cd $1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(xcd pkg
|
||||||
|
make install
|
||||||
|
make test
|
||||||
|
) || exit $?
|
||||||
|
|
||||||
(xcd pkg/exp/nacl/srpc
|
(xcd pkg/exp/nacl/srpc
|
||||||
make clean
|
make clean
|
||||||
make install
|
make install
|
||||||
@ -38,5 +44,5 @@ make
|
|||||||
) || exit $?
|
) || exit $?
|
||||||
|
|
||||||
(xcd ../test
|
(xcd ../test
|
||||||
./run-nacl
|
./run
|
||||||
) || exit $?
|
) || exit $?
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "opt.h"
|
#include "opt.h"
|
||||||
|
|
||||||
static Prog *pret;
|
static Prog *pret;
|
||||||
|
static Node *naclnop;
|
||||||
|
|
||||||
void
|
void
|
||||||
compile(Node *fn)
|
compile(Node *fn)
|
||||||
@ -23,6 +24,7 @@ compile(Node *fn)
|
|||||||
newproc = sysfunc("newproc");
|
newproc = sysfunc("newproc");
|
||||||
deferproc = sysfunc("deferproc");
|
deferproc = sysfunc("deferproc");
|
||||||
deferreturn = sysfunc("deferreturn");
|
deferreturn = sysfunc("deferreturn");
|
||||||
|
naclnop = sysfunc("naclnop");
|
||||||
panicindex = sysfunc("panicindex");
|
panicindex = sysfunc("panicindex");
|
||||||
panicslice = sysfunc("panicslice");
|
panicslice = sysfunc("panicslice");
|
||||||
throwreturn = sysfunc("throwreturn");
|
throwreturn = sysfunc("throwreturn");
|
||||||
@ -95,8 +97,16 @@ compile(Node *fn)
|
|||||||
gclean();
|
gclean();
|
||||||
if(nerrors != 0)
|
if(nerrors != 0)
|
||||||
goto ret;
|
goto ret;
|
||||||
if(hasdefer)
|
if(hasdefer) {
|
||||||
|
// On Native client, insert call to no-op function
|
||||||
|
// to force alignment immediately before call to deferreturn,
|
||||||
|
// so that when jmpdefer subtracts 5 from the second CALL's
|
||||||
|
// return address and then the return masks off the low bits,
|
||||||
|
// we'll back up to the NOPs immediately after the dummy CALL.
|
||||||
|
if(strcmp(getgoos(), "nacl") == 0)
|
||||||
|
ginscall(naclnop, 0);
|
||||||
ginscall(deferreturn, 0);
|
ginscall(deferreturn, 0);
|
||||||
|
}
|
||||||
pc->as = ARET; // overwrite AEND
|
pc->as = ARET; // overwrite AEND
|
||||||
pc->lineno = lineno;
|
pc->lineno = lineno;
|
||||||
|
|
||||||
|
@ -226,8 +226,11 @@ addsize(Sym *s, Sym *t)
|
|||||||
vlong
|
vlong
|
||||||
datoff(vlong addr)
|
datoff(vlong addr)
|
||||||
{
|
{
|
||||||
if(addr >= INITDAT)
|
if(addr >= INITDAT) {
|
||||||
|
if(HEADTYPE == 8)
|
||||||
|
return addr - INITDAT + rnd(HEADR+textsize, 4096);
|
||||||
return addr - INITDAT + rnd(HEADR+textsize, INITRND);
|
return addr - INITDAT + rnd(HEADR+textsize, INITRND);
|
||||||
|
}
|
||||||
diag("datoff %#llx", addr);
|
diag("datoff %#llx", addr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -548,6 +551,14 @@ asmb(void)
|
|||||||
}
|
}
|
||||||
cflush();
|
cflush();
|
||||||
break;
|
break;
|
||||||
|
case 8:
|
||||||
|
// Native Client only needs to round
|
||||||
|
// text segment file address to 4096 bytes,
|
||||||
|
// but text segment memory address rounds
|
||||||
|
// to INITRND (65536).
|
||||||
|
v = rnd(HEADR+textsize, 4096);
|
||||||
|
seek(cout, v, 0);
|
||||||
|
break;
|
||||||
Elfseek:
|
Elfseek:
|
||||||
case 10:
|
case 10:
|
||||||
v = rnd(HEADR+textsize, INITRND);
|
v = rnd(HEADR+textsize, INITRND);
|
||||||
@ -829,15 +840,25 @@ asmb(void)
|
|||||||
ph = newElfPhdr();
|
ph = newElfPhdr();
|
||||||
ph->type = PT_LOAD;
|
ph->type = PT_LOAD;
|
||||||
ph->flags = PF_X+PF_R;
|
ph->flags = PF_X+PF_R;
|
||||||
ph->vaddr = va - fo;
|
if(HEADTYPE != 8) { // Include header, but not on Native Client.
|
||||||
ph->paddr = va - fo;
|
va -= fo;
|
||||||
ph->off = 0;
|
w += fo;
|
||||||
ph->filesz = w + fo;
|
fo = 0;
|
||||||
ph->memsz = w + fo;
|
}
|
||||||
|
ph->vaddr = va;
|
||||||
|
ph->paddr = va;
|
||||||
|
ph->off = fo;
|
||||||
|
ph->filesz = w;
|
||||||
|
ph->memsz = INITDAT - va;
|
||||||
ph->align = INITRND;
|
ph->align = INITRND;
|
||||||
|
|
||||||
fo = rnd(fo+w, INITRND);
|
// NaCl text segment file address rounds to 4096;
|
||||||
va = rnd(va+w, INITRND);
|
// only memory address rounds to INITRND.
|
||||||
|
if(HEADTYPE == 8)
|
||||||
|
fo = rnd(fo+w, 4096);
|
||||||
|
else
|
||||||
|
fo = rnd(fo+w, INITRND);
|
||||||
|
va = INITDAT;
|
||||||
w = datsize;
|
w = datsize;
|
||||||
|
|
||||||
ph = newElfPhdr();
|
ph = newElfPhdr();
|
||||||
@ -941,7 +962,7 @@ asmb(void)
|
|||||||
ph->flags = PF_W+PF_R;
|
ph->flags = PF_W+PF_R;
|
||||||
ph->align = 4;
|
ph->align = 4;
|
||||||
|
|
||||||
fo = ELFRESERVE;
|
fo = HEADR;
|
||||||
va = startva + fo;
|
va = startva + fo;
|
||||||
w = textsize;
|
w = textsize;
|
||||||
|
|
||||||
@ -953,7 +974,12 @@ asmb(void)
|
|||||||
sh->size = w;
|
sh->size = w;
|
||||||
sh->addralign = 4;
|
sh->addralign = 4;
|
||||||
|
|
||||||
fo = rnd(fo+w, INITRND);
|
// NaCl text segment file address rounds to 4096;
|
||||||
|
// only memory address rounds to INITRND.
|
||||||
|
if(HEADTYPE == 8)
|
||||||
|
fo = rnd(fo+w, 4096);
|
||||||
|
else
|
||||||
|
fo = rnd(fo+w, INITRND);
|
||||||
va = rnd(va+w, INITRND);
|
va = rnd(va+w, INITRND);
|
||||||
w = datsize;
|
w = datsize;
|
||||||
|
|
||||||
@ -1013,7 +1039,7 @@ asmb(void)
|
|||||||
switch(HEADTYPE) {
|
switch(HEADTYPE) {
|
||||||
case 8:
|
case 8:
|
||||||
eh->ident[EI_OSABI] = ELFOSABI_NACL;
|
eh->ident[EI_OSABI] = ELFOSABI_NACL;
|
||||||
eh->ident[EI_ABIVERSION] = 6;
|
eh->ident[EI_ABIVERSION] = 7;
|
||||||
eh->flags = 0x200000; // aligned mod 32
|
eh->flags = 0x200000; // aligned mod 32
|
||||||
break;
|
break;
|
||||||
case 9:
|
case 9:
|
||||||
|
@ -302,6 +302,7 @@ EXTERN Sym* symlist;
|
|||||||
EXTERN int32 symsize;
|
EXTERN int32 symsize;
|
||||||
EXTERN Prog* textp;
|
EXTERN Prog* textp;
|
||||||
EXTERN int32 textsize;
|
EXTERN int32 textsize;
|
||||||
|
EXTERN int32 textpad;
|
||||||
EXTERN int version;
|
EXTERN int version;
|
||||||
EXTERN Prog zprg;
|
EXTERN Prog zprg;
|
||||||
EXTERN int dtype;
|
EXTERN int dtype;
|
||||||
|
@ -280,7 +280,12 @@ main(int argc, char *argv[])
|
|||||||
if(INITDAT == -1)
|
if(INITDAT == -1)
|
||||||
INITDAT = 0;
|
INITDAT = 0;
|
||||||
if(INITRND == -1)
|
if(INITRND == -1)
|
||||||
INITRND = 4096;
|
INITRND = 65536;
|
||||||
|
|
||||||
|
// 512 kB of address space for closures.
|
||||||
|
// (Doesn't take any space in the binary file.)
|
||||||
|
// Closures are 64 bytes each, so this is 8,192 closures.
|
||||||
|
textpad = 512*1024;
|
||||||
break;
|
break;
|
||||||
case 10: /* PE executable */
|
case 10: /* PE executable */
|
||||||
peinit();
|
peinit();
|
||||||
|
@ -108,7 +108,7 @@ start:
|
|||||||
}while(again);
|
}while(again);
|
||||||
|
|
||||||
if(INITRND) {
|
if(INITRND) {
|
||||||
INITDAT = rnd(c, INITRND);
|
INITDAT = rnd(c+textpad, INITRND);
|
||||||
if(INITDAT != idat) {
|
if(INITDAT != idat) {
|
||||||
idat = INITDAT;
|
idat = INITDAT;
|
||||||
goto start;
|
goto start;
|
||||||
|
@ -29,11 +29,7 @@ if [ -z "$O" ]; then
|
|||||||
exit 2
|
exit 2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
E=""
|
E="$GORUN"
|
||||||
case "$GOOS" in
|
|
||||||
nacl)
|
|
||||||
E="nacl"
|
|
||||||
esac
|
|
||||||
|
|
||||||
# TODO(kaib): proper emulator strategy
|
# TODO(kaib): proper emulator strategy
|
||||||
case x"$GOARCH" in
|
case x"$GOARCH" in
|
||||||
|
@ -150,6 +150,25 @@ TEST=\
|
|||||||
BENCH=\
|
BENCH=\
|
||||||
$(filter-out $(NOBENCH),$(TEST))
|
$(filter-out $(NOBENCH),$(TEST))
|
||||||
|
|
||||||
|
# Disable tests that NaCl cannot run yet.
|
||||||
|
ifeq ($(GOOS),nacl)
|
||||||
|
NOTEST+=archive/tar # no pipe
|
||||||
|
NOTEST+=debug/dwarf # no pread
|
||||||
|
NOTEST+=debug/macho # no pread
|
||||||
|
NOTEST+=debug/elf # no pread
|
||||||
|
NOTEST+=exec # no pipe
|
||||||
|
NOTEST+=http # no network
|
||||||
|
NOTEST+=log # no runtime.Caller
|
||||||
|
NOTEST+=net # no network
|
||||||
|
NOTEST+=os # many things unimplemented
|
||||||
|
NOTEST+=os/signal # no signals
|
||||||
|
NOTEST+=path # tree walking does not work
|
||||||
|
NOTEST+=rpc # no network
|
||||||
|
NOTEST+=syslog # no network
|
||||||
|
NOTEST+=time # no syscall.Kill, syscall.SIGCHLD for sleep tests
|
||||||
|
NOTEST+=websocket # no network
|
||||||
|
endif
|
||||||
|
|
||||||
clean.dirs: $(addsuffix .clean, $(DIRS))
|
clean.dirs: $(addsuffix .clean, $(DIRS))
|
||||||
install.dirs: $(addsuffix .install, $(DIRS))
|
install.dirs: $(addsuffix .install, $(DIRS))
|
||||||
nuke.dirs: $(addsuffix .nuke, $(DIRS))
|
nuke.dirs: $(addsuffix .nuke, $(DIRS))
|
||||||
|
@ -15,15 +15,15 @@ func fileInfoFromStat(name string, fi *FileInfo, lstat, stat *syscall.Stat_t) *F
|
|||||||
fi.Ino = uint64(stat.Ino)
|
fi.Ino = uint64(stat.Ino)
|
||||||
fi.Nlink = uint64(stat.Nlink)
|
fi.Nlink = uint64(stat.Nlink)
|
||||||
fi.Mode = stat.Mode
|
fi.Mode = stat.Mode
|
||||||
fi.Uid = stat.Uid
|
fi.Uid = int(stat.Uid)
|
||||||
fi.Gid = stat.Gid
|
fi.Gid = int(stat.Gid)
|
||||||
fi.Rdev = uint64(stat.Rdev)
|
fi.Rdev = uint64(stat.Rdev)
|
||||||
fi.Size = uint64(stat.Size)
|
fi.Size = int64(stat.Size)
|
||||||
fi.Blksize = uint64(stat.Blksize)
|
fi.Blksize = int64(stat.Blksize)
|
||||||
fi.Blocks = uint64(stat.Blocks)
|
fi.Blocks = int64(stat.Blocks)
|
||||||
fi.Atime_ns = uint64(stat.Atime) * 1e9
|
fi.Atime_ns = int64(stat.Atime) * 1e9
|
||||||
fi.Mtime_ns = uint64(stat.Mtime) * 1e9
|
fi.Mtime_ns = int64(stat.Mtime) * 1e9
|
||||||
fi.Ctime_ns = uint64(stat.Ctime) * 1e9
|
fi.Ctime_ns = int64(stat.Ctime) * 1e9
|
||||||
for i := len(name) - 1; i >= 0; i-- {
|
for i := len(name) - 1; i >= 0; i-- {
|
||||||
if name[i] == '/' {
|
if name[i] == '/' {
|
||||||
name = name[i+1:]
|
name = name[i+1:]
|
||||||
|
@ -154,8 +154,12 @@ runtime.acid.$(GOARCH): runtime.h proc.c
|
|||||||
|
|
||||||
# 386 traceback is really amd64 traceback
|
# 386 traceback is really amd64 traceback
|
||||||
ifeq ($(GOARCH),386)
|
ifeq ($(GOARCH),386)
|
||||||
|
|
||||||
traceback.$O: amd64/traceback.c
|
traceback.$O: amd64/traceback.c
|
||||||
$(QUOTED_GOBIN)/$(CC) $(CFLAGS) $<
|
$(QUOTED_GOBIN)/$(CC) $(CFLAGS) $<
|
||||||
|
endif
|
||||||
|
|
||||||
|
# NaCl closure is special.
|
||||||
|
ifeq ($(GOOS),nacl)
|
||||||
|
closure.$O: nacl/$(GOARCH)/closure.c
|
||||||
|
$(QUOTED_GOBIN)/$(CC) $(CFLAGS) $<
|
||||||
endif
|
endif
|
||||||
|
@ -325,6 +325,10 @@ struct MHeap
|
|||||||
byte *min;
|
byte *min;
|
||||||
byte *max;
|
byte *max;
|
||||||
|
|
||||||
|
// range of addresses we might see in a Native Client closure
|
||||||
|
byte *closure_min;
|
||||||
|
byte *closure_max;
|
||||||
|
|
||||||
// central free lists for small size classes.
|
// central free lists for small size classes.
|
||||||
// the union makes sure that the MCentrals are
|
// the union makes sure that the MCentrals are
|
||||||
// spaced 64 bytes apart, so that each MCentral.Lock
|
// spaced 64 bytes apart, so that each MCentral.Lock
|
||||||
|
@ -56,18 +56,36 @@ scanblock(int32 depth, byte *b, int64 n)
|
|||||||
n /= PtrSize;
|
n /= PtrSize;
|
||||||
for(i=0; i<n; i++) {
|
for(i=0; i<n; i++) {
|
||||||
obj = vp[i];
|
obj = vp[i];
|
||||||
if(obj == nil || (byte*)obj < mheap.min || (byte*)obj >= mheap.max)
|
if(obj == nil)
|
||||||
continue;
|
continue;
|
||||||
if(mlookup(obj, &obj, &size, nil, &refp)) {
|
if(mheap.closure_min != nil && mheap.closure_min <= (byte*)obj && (byte*)obj < mheap.closure_max) {
|
||||||
ref = *refp;
|
if((((uintptr)obj) & 63) != 0)
|
||||||
switch(ref & ~RefFlags) {
|
continue;
|
||||||
case RefNone:
|
|
||||||
if(Debug > 1)
|
// Looks like a Native Client closure.
|
||||||
printf("%d found at %p: ", depth, &vp[i]);
|
// Actual pointer is pointed at by address in first instruction.
|
||||||
*refp = RefSome | (ref & RefFlags);
|
// Embedded pointer starts at byte 2.
|
||||||
if(!(ref & RefNoPointers))
|
// If it is f4f4f4f4 then that space hasn't been
|
||||||
scanblock(depth+1, obj, size);
|
// used for a closure yet (f4 is the HLT instruction).
|
||||||
break;
|
// See nacl/386/closure.c for more.
|
||||||
|
void **pp;
|
||||||
|
pp = *(void***)((byte*)obj+2);
|
||||||
|
if(pp == (void**)0xf4f4f4f4) // HLT... - not a closure after all
|
||||||
|
continue;
|
||||||
|
obj = *pp;
|
||||||
|
}
|
||||||
|
if(mheap.min <= (byte*)obj && (byte*)obj < mheap.max) {
|
||||||
|
if(mlookup(obj, &obj, &size, nil, &refp)) {
|
||||||
|
ref = *refp;
|
||||||
|
switch(ref & ~RefFlags) {
|
||||||
|
case RefNone:
|
||||||
|
if(Debug > 1)
|
||||||
|
printf("%d found at %p: ", depth, &vp[i]);
|
||||||
|
*refp = RefSome | (ref & RefFlags);
|
||||||
|
if(!(ref & RefNoPointers))
|
||||||
|
scanblock(depth+1, obj, size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -310,8 +328,8 @@ gc(int32 force)
|
|||||||
if(fing == nil)
|
if(fing == nil)
|
||||||
fing = newproc1((byte*)runfinq, nil, 0, 0);
|
fing = newproc1((byte*)runfinq, nil, 0, 0);
|
||||||
else if(fingwait) {
|
else if(fingwait) {
|
||||||
ready(fing);
|
|
||||||
fingwait = 0;
|
fingwait = 0;
|
||||||
|
ready(fing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m->locks--;
|
m->locks--;
|
||||||
@ -359,6 +377,7 @@ runfinq(void)
|
|||||||
f->fn = nil;
|
f->fn = nil;
|
||||||
f->arg = nil;
|
f->arg = nil;
|
||||||
f->next = nil;
|
f->next = nil;
|
||||||
|
free(f);
|
||||||
}
|
}
|
||||||
gc(1); // trigger another gc to clean up the finalized objects, if possible
|
gc(1); // trigger another gc to clean up the finalized objects, if possible
|
||||||
}
|
}
|
||||||
|
247
src/pkg/runtime/nacl/386/closure.c
Normal file
247
src/pkg/runtime/nacl/386/closure.c
Normal file
@ -0,0 +1,247 @@
|
|||||||
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Closure implementation for Native Client.
|
||||||
|
* Native Client imposes some interesting restrictions.
|
||||||
|
*
|
||||||
|
* First, we can only add new code to the code segment
|
||||||
|
* through a special system call, and we have to pick the
|
||||||
|
* maximum amount of code we're going to add that way
|
||||||
|
* at link time (8l reserves 512 kB for us).
|
||||||
|
*
|
||||||
|
* Second, once we've added the code we can't ever
|
||||||
|
* change it or delete it. If we want to garbage collect
|
||||||
|
* the memory and then reuse it for another closure,
|
||||||
|
* we have to do so without editing the code.
|
||||||
|
*
|
||||||
|
* To address both of these, we fill the code segment pieces
|
||||||
|
* with very stylized closures. Each has the form given below
|
||||||
|
* in the comments on the closasm array, with ** replaced by
|
||||||
|
* a pointer to a single word of memory. The garbage collector
|
||||||
|
* treats a pointer to such a closure as equivalent to the value
|
||||||
|
* held in **. This tiled run of closures is called the closure array.
|
||||||
|
*
|
||||||
|
* The ptr points at a ClosureData structure, defined below,
|
||||||
|
* which gives the function, arguments, and size for the
|
||||||
|
* closuretramp function. The ClosureData structure has
|
||||||
|
* in it a pointer to a ClosureFreeList structure holding the index
|
||||||
|
* of the closure in the closure array (but not a pointer to it).
|
||||||
|
* That structure has a finalizer: when the garbage collector
|
||||||
|
* notices that the ClosureFreeList structure is not referenced
|
||||||
|
* anymore, that means the closure is not referenced, so it
|
||||||
|
* can be reused. To do that, the ClosureFreeList entry is put
|
||||||
|
* onto an actual free list.
|
||||||
|
*/
|
||||||
|
#include "runtime.h"
|
||||||
|
#include "malloc.h"
|
||||||
|
|
||||||
|
// NaCl system call to copy data into text segment.
|
||||||
|
extern int32 dyncode_copy(void*, void*, int32);
|
||||||
|
|
||||||
|
enum{
|
||||||
|
// Allocate chunks of 4096 bytes worth of closures:
|
||||||
|
// at 64 bytes each, that's 64 closures.
|
||||||
|
ClosureChunk = 4096,
|
||||||
|
ClosureSize = 64,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct ClosureFreeList ClosureFreeList;
|
||||||
|
struct ClosureFreeList
|
||||||
|
{
|
||||||
|
ClosureFreeList *next;
|
||||||
|
int32 index; // into closure array
|
||||||
|
};
|
||||||
|
|
||||||
|
// Known to closasm
|
||||||
|
typedef struct ClosureData ClosureData;
|
||||||
|
struct ClosureData
|
||||||
|
{
|
||||||
|
ClosureFreeList *free;
|
||||||
|
byte *fn;
|
||||||
|
int32 siz;
|
||||||
|
// then args
|
||||||
|
};
|
||||||
|
|
||||||
|
// List of the closure data pointer blocks we've allocated
|
||||||
|
// and hard-coded in the closure text segments.
|
||||||
|
// The list keeps the pointer blocks from getting collected.
|
||||||
|
typedef struct ClosureDataList ClosureDataList;
|
||||||
|
struct ClosureDataList
|
||||||
|
{
|
||||||
|
ClosureData **block;
|
||||||
|
ClosureDataList *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
Lock;
|
||||||
|
byte *code;
|
||||||
|
byte *ecode;
|
||||||
|
ClosureFreeList *free;
|
||||||
|
ClosureDataList *datalist;
|
||||||
|
byte buf[ClosureChunk];
|
||||||
|
} clos;
|
||||||
|
|
||||||
|
static byte closasm[64] = {
|
||||||
|
0x8b, 0x1d, 0, 0, 0, 0, // MOVL **, BX
|
||||||
|
0x8b, 0x4b, 8, // MOVL 8(BX), CX
|
||||||
|
0x8d, 0x73, 12, // LEAL 12(BX), SI
|
||||||
|
0x29, 0xcc, // SUBL CX, SP
|
||||||
|
0x89, 0xe7, // MOVL SP, DI
|
||||||
|
0xc1, 0xe9, 2, // SHRL $2, CX
|
||||||
|
0xf3, 0xa5, // REP MOVSL
|
||||||
|
0x8b, 0x5b, 4, // MOVL 4(BX), BX
|
||||||
|
0x90, 0x90, 0x90, // NOP...
|
||||||
|
0x83, 0xe3, ~31, // ANDL $~31, BX
|
||||||
|
0xff, 0xd3, // CALL *BX
|
||||||
|
// --- 32-byte boundary
|
||||||
|
0x8b, 0x1d, 0, 0, 0, 0, // MOVL **, BX
|
||||||
|
0x03, 0x63, 8, // ADDL 8(BX), SP
|
||||||
|
0x5b, // POPL BX
|
||||||
|
0x83, 0xe3, ~31, // ANDL $~31, BX
|
||||||
|
0xff, 0xe3, // JMP *BX
|
||||||
|
0xf4, // HLT...
|
||||||
|
0xf4, 0xf4, 0xf4, 0xf4,
|
||||||
|
0xf4, 0xf4, 0xf4, 0xf4,
|
||||||
|
0xf4, 0xf4, 0xf4, 0xf4,
|
||||||
|
0xf4, 0xf4, 0xf4, 0xf4,
|
||||||
|
// --- 32-byte boundary
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns immediate pointer from closure code block.
|
||||||
|
// Triple pointer:
|
||||||
|
// p is the instruction stream
|
||||||
|
// p+2 is the location of the immediate value
|
||||||
|
// *(p+2) is the immediate value, a word in the pointer block
|
||||||
|
// permanently associated with this closure.
|
||||||
|
// **(p+2) is the ClosureData* pointer temporarily associated
|
||||||
|
// with this closure.
|
||||||
|
//
|
||||||
|
#define codeptr(p) *(ClosureData***)((byte*)(p)+2)
|
||||||
|
|
||||||
|
void
|
||||||
|
finclosure(void *v)
|
||||||
|
{
|
||||||
|
byte *p;
|
||||||
|
ClosureFreeList *f;
|
||||||
|
|
||||||
|
f = v;
|
||||||
|
p = clos.code + f->index*ClosureSize;
|
||||||
|
*codeptr(p) = nil;
|
||||||
|
|
||||||
|
lock(&clos);
|
||||||
|
f->next = clos.free;
|
||||||
|
clos.free = f;
|
||||||
|
unlock(&clos);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma textflag 7
|
||||||
|
// func closure(siz int32,
|
||||||
|
// fn func(arg0, arg1, arg2 *ptr, callerpc uintptr, xxx) yyy,
|
||||||
|
// arg0, arg1, arg2 *ptr) (func(xxx) yyy)
|
||||||
|
void
|
||||||
|
·closure(int32 siz, byte *fn, byte *arg0)
|
||||||
|
{
|
||||||
|
byte *p, **ret;
|
||||||
|
int32 e, i, n, off;
|
||||||
|
extern byte data[], etext[];
|
||||||
|
ClosureData *d, **block;
|
||||||
|
ClosureDataList *l;
|
||||||
|
ClosureFreeList *f;
|
||||||
|
|
||||||
|
if(siz < 0 || siz%4 != 0)
|
||||||
|
throw("bad closure size");
|
||||||
|
|
||||||
|
ret = (byte**)((byte*)&arg0 + siz);
|
||||||
|
|
||||||
|
if(siz > 100) {
|
||||||
|
// TODO(rsc): implement stack growth preamble?
|
||||||
|
throw("closure too big");
|
||||||
|
}
|
||||||
|
|
||||||
|
lock(&clos);
|
||||||
|
if(clos.free == nil) {
|
||||||
|
// Allocate more closures.
|
||||||
|
if(clos.code == nil) {
|
||||||
|
// First time: find closure space, between end of text
|
||||||
|
// segment and beginning of data.
|
||||||
|
clos.code = (byte*)(((uintptr)etext + 65535) & ~65535);
|
||||||
|
clos.ecode = clos.code;
|
||||||
|
mheap.closure_min = clos.code;
|
||||||
|
mheap.closure_max = data;
|
||||||
|
}
|
||||||
|
if(clos.ecode+ClosureChunk > data) {
|
||||||
|
// Last ditch effort: garbage collect and hope.
|
||||||
|
unlock(&clos);
|
||||||
|
gc(1);
|
||||||
|
lock(&clos);
|
||||||
|
if(clos.free != nil)
|
||||||
|
goto alloc;
|
||||||
|
throw("ran out of room for closures in text segment");
|
||||||
|
}
|
||||||
|
|
||||||
|
n = ClosureChunk/ClosureSize;
|
||||||
|
|
||||||
|
// Allocate the pointer block as opaque to the
|
||||||
|
// garbage collector. Finalizers will clean up.
|
||||||
|
block = mallocgc(n*sizeof block[0], RefNoPointers, 1, 1);
|
||||||
|
|
||||||
|
// Pointers into the pointer block are getting added
|
||||||
|
// to the text segment; keep a pointer here in the data
|
||||||
|
// segment so that the garbage collector doesn't free
|
||||||
|
// the block itself.
|
||||||
|
l = mal(sizeof *l);
|
||||||
|
l->block = block;
|
||||||
|
l->next = clos.datalist;
|
||||||
|
clos.datalist = l;
|
||||||
|
|
||||||
|
p = clos.buf;
|
||||||
|
off = (clos.ecode - clos.code)/ClosureSize;
|
||||||
|
for(i=0; i<n; i++) {
|
||||||
|
f = mal(sizeof *f);
|
||||||
|
f->index = off++;
|
||||||
|
f->next = clos.free;
|
||||||
|
clos.free = f;
|
||||||
|
|
||||||
|
// There are two hard-coded immediate values in
|
||||||
|
// the assembly that need to be pp+i, one 2 bytes in
|
||||||
|
// and one 2 bytes after the 32-byte boundary.
|
||||||
|
mcpy(p, closasm, ClosureSize);
|
||||||
|
*(ClosureData***)(p+2) = block+i;
|
||||||
|
*(ClosureData***)(p+32+2) = block+i;
|
||||||
|
p += ClosureSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(p != clos.buf+sizeof clos.buf)
|
||||||
|
throw("bad buf math in closure");
|
||||||
|
|
||||||
|
e = dyncode_copy(clos.ecode, clos.buf, ClosureChunk);
|
||||||
|
if(e != 0) {
|
||||||
|
fd = 2;
|
||||||
|
printf("dyncode_copy: error %d\n", e);
|
||||||
|
throw("dyncode_copy");
|
||||||
|
}
|
||||||
|
clos.ecode += ClosureChunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
alloc:
|
||||||
|
// Grab a free closure and save the data pointer in its indirect pointer.
|
||||||
|
f = clos.free;
|
||||||
|
clos.free = f->next;
|
||||||
|
f->next = nil;
|
||||||
|
p = clos.code + f->index*ClosureSize;
|
||||||
|
|
||||||
|
d = mal(sizeof(*d)+siz);
|
||||||
|
d->free = f;
|
||||||
|
d->fn = fn;
|
||||||
|
d->siz = siz;
|
||||||
|
mcpy((byte*)(d+1), (byte*)&arg0, siz);
|
||||||
|
*codeptr(p) = d;
|
||||||
|
addfinalizer(f, finclosure, 0);
|
||||||
|
unlock(&clos);
|
||||||
|
|
||||||
|
*ret = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -20,6 +20,8 @@
|
|||||||
#define SYS_mutex_lock 71
|
#define SYS_mutex_lock 71
|
||||||
#define SYS_mutex_unlock 73
|
#define SYS_mutex_unlock 73
|
||||||
#define SYS_gettimeofday 40
|
#define SYS_gettimeofday 40
|
||||||
|
#define SYS_dyncode_copy 104
|
||||||
|
|
||||||
|
|
||||||
#define SYSCALL(x) $(0x10000+SYS_/**/x * 32)
|
#define SYSCALL(x) $(0x10000+SYS_/**/x * 32)
|
||||||
|
|
||||||
@ -55,6 +57,15 @@ TEXT mutex_unlock(SB),7,$0
|
|||||||
TEXT thread_create(SB),7,$0
|
TEXT thread_create(SB),7,$0
|
||||||
JMP SYSCALL(thread_create)
|
JMP SYSCALL(thread_create)
|
||||||
|
|
||||||
|
TEXT dyncode_copy(SB),7,$0
|
||||||
|
JMP SYSCALL(dyncode_copy)
|
||||||
|
|
||||||
|
// For Native Client: a simple no-op function.
|
||||||
|
// Inserting a call to this no-op is a simple way
|
||||||
|
// to trigger an alignment.
|
||||||
|
TEXT ·naclnop(SB),7,$0
|
||||||
|
RET
|
||||||
|
|
||||||
TEXT ·mmap(SB),7,$24
|
TEXT ·mmap(SB),7,$24
|
||||||
MOVL a1+0(FP), BX
|
MOVL a1+0(FP), BX
|
||||||
MOVL a2+4(FP), CX // round up to 64 kB boundary; silences nacl warning
|
MOVL a2+4(FP), CX // round up to 64 kB boundary; silences nacl warning
|
||||||
|
@ -88,7 +88,7 @@ unlock(Lock *l)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
destroylock(Lock *l)
|
destroylock(Lock*)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@ func Pwrite(fd int, p []byte, offset int64) (n int, errno int) {
|
|||||||
func Mkdir(path string, mode int) (errno int) { return ENACL }
|
func Mkdir(path string, mode int) (errno int) { return ENACL }
|
||||||
|
|
||||||
func Lstat(path string, stat *Stat_t) (errno int) {
|
func Lstat(path string, stat *Stat_t) (errno int) {
|
||||||
return ENACL
|
return Stat(path, stat)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Chdir(path string) (errno int) { return ENACL }
|
func Chdir(path string) (errno int) { return ENACL }
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// [ $GOOS != nacl ] || exit 0 # NaCl runner does not expose environment
|
||||||
// $G $F.go && $L $F.$A && ./$A.out
|
// $G $F.go && $L $F.$A && ./$A.out
|
||||||
|
|
||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// [ $GOOS != nacl ] || exit 0 # no network
|
||||||
// $G $D/$F.go && $L $F.$A && ./$A.out
|
// $G $D/$F.go && $L $F.$A && ./$A.out
|
||||||
|
|
||||||
// Copyright 2010 The Go Authors. All rights reserved.
|
// Copyright 2010 The Go Authors. All rights reserved.
|
||||||
|
@ -1,355 +0,0 @@
|
|||||||
./64bit.go
|
|
||||||
./args.go
|
|
||||||
./assign.go
|
|
||||||
./bigalg.go
|
|
||||||
./blank.go
|
|
||||||
./blank1.go
|
|
||||||
./chancap.go
|
|
||||||
./char_lit.go
|
|
||||||
./closedchan.go
|
|
||||||
./cmp1.go
|
|
||||||
./complit.go
|
|
||||||
./compos.go
|
|
||||||
./const.go
|
|
||||||
./const1.go
|
|
||||||
./const2.go
|
|
||||||
./const3.go
|
|
||||||
./convert.go
|
|
||||||
./convert3.go
|
|
||||||
./convlit.go
|
|
||||||
./convlit1.go
|
|
||||||
./copy.go
|
|
||||||
./ddd1.go
|
|
||||||
./ddd2.go
|
|
||||||
./ddd3.go
|
|
||||||
./decl.go
|
|
||||||
./declbad.go
|
|
||||||
./defer.go
|
|
||||||
./empty.go
|
|
||||||
./escape.go
|
|
||||||
./escape1.go
|
|
||||||
./float_lit.go
|
|
||||||
./floatcmp.go
|
|
||||||
./for.go
|
|
||||||
./func.go
|
|
||||||
./func1.go
|
|
||||||
./func2.go
|
|
||||||
./func3.go
|
|
||||||
./func4.go
|
|
||||||
./gc.go
|
|
||||||
./gc1.go
|
|
||||||
./hashmap.go
|
|
||||||
./hilbert.go
|
|
||||||
./if.go
|
|
||||||
./if1.go
|
|
||||||
./import.go
|
|
||||||
./import1.go
|
|
||||||
./import2.go
|
|
||||||
./import3.go
|
|
||||||
./indirect.go
|
|
||||||
./indirect1.go
|
|
||||||
./initcomma.go
|
|
||||||
./initialize.go
|
|
||||||
./initializerr.go
|
|
||||||
./initsyscall.go
|
|
||||||
./int_lit.go
|
|
||||||
./intcvt.go
|
|
||||||
./iota.go
|
|
||||||
./literal.go
|
|
||||||
./map.go
|
|
||||||
./method.go
|
|
||||||
./method1.go
|
|
||||||
./method2.go
|
|
||||||
./method3.go
|
|
||||||
./named.go
|
|
||||||
./named1.go
|
|
||||||
./nil.go
|
|
||||||
./parentype.go
|
|
||||||
./range.go
|
|
||||||
./rename.go
|
|
||||||
./rename1.go
|
|
||||||
./runtime.go
|
|
||||||
./sieve.go
|
|
||||||
./simassign.go
|
|
||||||
./string_lit.go
|
|
||||||
./stringrange.go
|
|
||||||
./switch.go
|
|
||||||
./switch1.go
|
|
||||||
./test0.go
|
|
||||||
./typeswitch.go
|
|
||||||
./typeswitch1.go
|
|
||||||
./typeswitch2.go
|
|
||||||
./utf.go
|
|
||||||
./varinit.go
|
|
||||||
./vectors.go
|
|
||||||
ken/array.go
|
|
||||||
ken/chan.go
|
|
||||||
ken/chan1.go
|
|
||||||
ken/complit.go
|
|
||||||
ken/divconst.go
|
|
||||||
ken/divmod.go
|
|
||||||
ken/embed.go
|
|
||||||
ken/for.go
|
|
||||||
ken/interbasic.go
|
|
||||||
ken/interfun.go
|
|
||||||
ken/mfunc.go
|
|
||||||
ken/modconst.go
|
|
||||||
ken/ptrfun.go
|
|
||||||
ken/ptrvar.go
|
|
||||||
ken/range.go
|
|
||||||
ken/robfor.go
|
|
||||||
ken/robfunc.go
|
|
||||||
ken/robif.go
|
|
||||||
ken/shift.go
|
|
||||||
ken/simparray.go
|
|
||||||
ken/simpbool.go
|
|
||||||
ken/simpconv.go
|
|
||||||
ken/simpfun.go
|
|
||||||
ken/simpvar.go
|
|
||||||
ken/slicearray.go
|
|
||||||
ken/sliceslice.go
|
|
||||||
ken/strvar.go
|
|
||||||
chan/fifo.go
|
|
||||||
chan/perm.go
|
|
||||||
chan/select.go
|
|
||||||
chan/sieve.go
|
|
||||||
interface/bigdata.go
|
|
||||||
interface/convert.go
|
|
||||||
interface/convert1.go
|
|
||||||
interface/convert2.go
|
|
||||||
interface/embed.go
|
|
||||||
interface/embed0.go
|
|
||||||
interface/embed1.go
|
|
||||||
interface/explicit.go
|
|
||||||
interface/fake.go
|
|
||||||
interface/pointer.go
|
|
||||||
interface/receiver.go
|
|
||||||
interface/receiver1.go
|
|
||||||
interface/recursive.go
|
|
||||||
interface/struct.go
|
|
||||||
syntax/forvar.go
|
|
||||||
syntax/import.go
|
|
||||||
syntax/interface.go
|
|
||||||
syntax/semi1.go
|
|
||||||
syntax/semi2.go
|
|
||||||
syntax/semi3.go
|
|
||||||
syntax/semi4.go
|
|
||||||
syntax/semi5.go
|
|
||||||
syntax/semi6.go
|
|
||||||
syntax/semi7.go
|
|
||||||
syntax/slice.go
|
|
||||||
fixedbugs/bug000.go
|
|
||||||
fixedbugs/bug001.go
|
|
||||||
fixedbugs/bug002.go
|
|
||||||
fixedbugs/bug003.go
|
|
||||||
fixedbugs/bug004.go
|
|
||||||
fixedbugs/bug005.go
|
|
||||||
fixedbugs/bug006.go
|
|
||||||
fixedbugs/bug007.go
|
|
||||||
fixedbugs/bug008.go
|
|
||||||
fixedbugs/bug009.go
|
|
||||||
fixedbugs/bug010.go
|
|
||||||
fixedbugs/bug011.go
|
|
||||||
fixedbugs/bug012.go
|
|
||||||
fixedbugs/bug013.go
|
|
||||||
fixedbugs/bug014.go
|
|
||||||
fixedbugs/bug015.go
|
|
||||||
fixedbugs/bug017.go
|
|
||||||
fixedbugs/bug020.go
|
|
||||||
fixedbugs/bug021.go
|
|
||||||
fixedbugs/bug022.go
|
|
||||||
fixedbugs/bug023.go
|
|
||||||
fixedbugs/bug024.go
|
|
||||||
fixedbugs/bug026.go
|
|
||||||
fixedbugs/bug028.go
|
|
||||||
fixedbugs/bug030.go
|
|
||||||
fixedbugs/bug031.go
|
|
||||||
fixedbugs/bug035.go
|
|
||||||
fixedbugs/bug036.go
|
|
||||||
fixedbugs/bug037.go
|
|
||||||
fixedbugs/bug038.go
|
|
||||||
fixedbugs/bug039.go
|
|
||||||
fixedbugs/bug040.go
|
|
||||||
fixedbugs/bug045.go
|
|
||||||
fixedbugs/bug046.go
|
|
||||||
fixedbugs/bug047.go
|
|
||||||
fixedbugs/bug048.go
|
|
||||||
fixedbugs/bug049.go
|
|
||||||
fixedbugs/bug050.go
|
|
||||||
fixedbugs/bug051.go
|
|
||||||
fixedbugs/bug052.go
|
|
||||||
fixedbugs/bug053.go
|
|
||||||
fixedbugs/bug054.go
|
|
||||||
fixedbugs/bug055.go
|
|
||||||
fixedbugs/bug056.go
|
|
||||||
fixedbugs/bug057.go
|
|
||||||
fixedbugs/bug058.go
|
|
||||||
fixedbugs/bug059.go
|
|
||||||
fixedbugs/bug060.go
|
|
||||||
fixedbugs/bug061.go
|
|
||||||
fixedbugs/bug062.go
|
|
||||||
fixedbugs/bug063.go
|
|
||||||
fixedbugs/bug064.go
|
|
||||||
fixedbugs/bug065.go
|
|
||||||
fixedbugs/bug066.go
|
|
||||||
fixedbugs/bug068.go
|
|
||||||
fixedbugs/bug069.go
|
|
||||||
fixedbugs/bug071.go
|
|
||||||
fixedbugs/bug072.go
|
|
||||||
fixedbugs/bug073.go
|
|
||||||
fixedbugs/bug074.go
|
|
||||||
fixedbugs/bug075.go
|
|
||||||
fixedbugs/bug076.go
|
|
||||||
fixedbugs/bug077.go
|
|
||||||
fixedbugs/bug078.go
|
|
||||||
fixedbugs/bug080.go
|
|
||||||
fixedbugs/bug082.go
|
|
||||||
fixedbugs/bug083.go
|
|
||||||
fixedbugs/bug084.go
|
|
||||||
fixedbugs/bug085.go
|
|
||||||
fixedbugs/bug086.go
|
|
||||||
fixedbugs/bug087.go
|
|
||||||
fixedbugs/bug088.go
|
|
||||||
fixedbugs/bug089.go
|
|
||||||
fixedbugs/bug090.go
|
|
||||||
fixedbugs/bug091.go
|
|
||||||
fixedbugs/bug092.go
|
|
||||||
fixedbugs/bug094.go
|
|
||||||
fixedbugs/bug096.go
|
|
||||||
fixedbugs/bug097.go
|
|
||||||
fixedbugs/bug098.go
|
|
||||||
fixedbugs/bug099.go
|
|
||||||
fixedbugs/bug101.go
|
|
||||||
fixedbugs/bug102.go
|
|
||||||
fixedbugs/bug103.go
|
|
||||||
fixedbugs/bug104.go
|
|
||||||
fixedbugs/bug106.go
|
|
||||||
fixedbugs/bug107.go
|
|
||||||
fixedbugs/bug108.go
|
|
||||||
fixedbugs/bug109.go
|
|
||||||
fixedbugs/bug110.go
|
|
||||||
fixedbugs/bug111.go
|
|
||||||
fixedbugs/bug112.go
|
|
||||||
fixedbugs/bug114.go
|
|
||||||
fixedbugs/bug115.go
|
|
||||||
fixedbugs/bug116.go
|
|
||||||
fixedbugs/bug117.go
|
|
||||||
fixedbugs/bug118.go
|
|
||||||
fixedbugs/bug119.go
|
|
||||||
fixedbugs/bug120.go
|
|
||||||
fixedbugs/bug121.go
|
|
||||||
fixedbugs/bug122.go
|
|
||||||
fixedbugs/bug123.go
|
|
||||||
fixedbugs/bug126.go
|
|
||||||
fixedbugs/bug127.go
|
|
||||||
fixedbugs/bug128.go
|
|
||||||
fixedbugs/bug129.go
|
|
||||||
fixedbugs/bug130.go
|
|
||||||
fixedbugs/bug131.go
|
|
||||||
fixedbugs/bug132.go
|
|
||||||
fixedbugs/bug133.go
|
|
||||||
fixedbugs/bug135.go
|
|
||||||
fixedbugs/bug136.go
|
|
||||||
fixedbugs/bug137.go
|
|
||||||
fixedbugs/bug139.go
|
|
||||||
fixedbugs/bug140.go
|
|
||||||
fixedbugs/bug141.go
|
|
||||||
fixedbugs/bug142.go
|
|
||||||
fixedbugs/bug143.go
|
|
||||||
fixedbugs/bug144.go
|
|
||||||
fixedbugs/bug145.go
|
|
||||||
fixedbugs/bug146.go
|
|
||||||
fixedbugs/bug149.go
|
|
||||||
fixedbugs/bug150.go
|
|
||||||
fixedbugs/bug151.go
|
|
||||||
fixedbugs/bug152.go
|
|
||||||
fixedbugs/bug153.go
|
|
||||||
fixedbugs/bug154.go
|
|
||||||
fixedbugs/bug155.go
|
|
||||||
fixedbugs/bug156.go
|
|
||||||
fixedbugs/bug157.go
|
|
||||||
fixedbugs/bug158.go
|
|
||||||
fixedbugs/bug160.go
|
|
||||||
fixedbugs/bug161.go
|
|
||||||
fixedbugs/bug163.go
|
|
||||||
fixedbugs/bug164.go
|
|
||||||
fixedbugs/bug165.go
|
|
||||||
fixedbugs/bug167.go
|
|
||||||
fixedbugs/bug168.go
|
|
||||||
fixedbugs/bug169.go
|
|
||||||
fixedbugs/bug170.go
|
|
||||||
fixedbugs/bug171.go
|
|
||||||
fixedbugs/bug172.go
|
|
||||||
fixedbugs/bug173.go
|
|
||||||
fixedbugs/bug174.go
|
|
||||||
fixedbugs/bug175.go
|
|
||||||
fixedbugs/bug176.go
|
|
||||||
fixedbugs/bug177.go
|
|
||||||
fixedbugs/bug178.go
|
|
||||||
fixedbugs/bug179.go
|
|
||||||
fixedbugs/bug180.go
|
|
||||||
fixedbugs/bug181.go
|
|
||||||
fixedbugs/bug182.go
|
|
||||||
fixedbugs/bug183.go
|
|
||||||
fixedbugs/bug184.go
|
|
||||||
fixedbugs/bug185.go
|
|
||||||
fixedbugs/bug186.go
|
|
||||||
fixedbugs/bug187.go
|
|
||||||
fixedbugs/bug188.go
|
|
||||||
fixedbugs/bug189.go
|
|
||||||
fixedbugs/bug190.go
|
|
||||||
fixedbugs/bug191.go
|
|
||||||
fixedbugs/bug192.go
|
|
||||||
fixedbugs/bug193.go
|
|
||||||
fixedbugs/bug194.go
|
|
||||||
fixedbugs/bug195.go
|
|
||||||
fixedbugs/bug196.go
|
|
||||||
fixedbugs/bug197.go
|
|
||||||
fixedbugs/bug198.go
|
|
||||||
fixedbugs/bug199.go
|
|
||||||
fixedbugs/bug200.go
|
|
||||||
fixedbugs/bug201.go
|
|
||||||
fixedbugs/bug202.go
|
|
||||||
fixedbugs/bug203.go
|
|
||||||
fixedbugs/bug204.go
|
|
||||||
fixedbugs/bug205.go
|
|
||||||
fixedbugs/bug206.go
|
|
||||||
fixedbugs/bug207.go
|
|
||||||
fixedbugs/bug208.go
|
|
||||||
fixedbugs/bug209.go
|
|
||||||
fixedbugs/bug211.go
|
|
||||||
fixedbugs/bug212.go
|
|
||||||
fixedbugs/bug213.go
|
|
||||||
fixedbugs/bug214.go
|
|
||||||
fixedbugs/bug215.go
|
|
||||||
fixedbugs/bug216.go
|
|
||||||
fixedbugs/bug217.go
|
|
||||||
fixedbugs/bug218.go
|
|
||||||
fixedbugs/bug219.go
|
|
||||||
fixedbugs/bug220.go
|
|
||||||
fixedbugs/bug221.go
|
|
||||||
fixedbugs/bug222.go
|
|
||||||
fixedbugs/bug223.go
|
|
||||||
fixedbugs/bug224.go
|
|
||||||
fixedbugs/bug225.go
|
|
||||||
fixedbugs/bug226.go
|
|
||||||
fixedbugs/bug227.go
|
|
||||||
fixedbugs/bug228.go
|
|
||||||
fixedbugs/bug229.go
|
|
||||||
fixedbugs/bug230.go
|
|
||||||
fixedbugs/bug231.go
|
|
||||||
fixedbugs/bug232.go
|
|
||||||
fixedbugs/bug233.go
|
|
||||||
fixedbugs/bug234.go
|
|
||||||
fixedbugs/bug235.go
|
|
||||||
fixedbugs/bug236.go
|
|
||||||
fixedbugs/bug237.go
|
|
||||||
fixedbugs/bug238.go
|
|
||||||
fixedbugs/bug239.go
|
|
||||||
fixedbugs/bug240.go
|
|
||||||
fixedbugs/bug241.go
|
|
||||||
fixedbugs/bug244.go
|
|
||||||
fixedbugs/bug245.go
|
|
||||||
fixedbugs/bug247.go
|
|
||||||
fixedbugs/bug248.go
|
|
||||||
fixedbugs/bug249.go
|
|
@ -1,3 +1,4 @@
|
|||||||
|
// [ $GOOS != nacl ] || exit 0 # do not bother on NaCl
|
||||||
// $G $D/$F.go && $L $F.$A &&
|
// $G $D/$F.go && $L $F.$A &&
|
||||||
// ((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
|
// ((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// [ $GOOS != nacl ] || exit 0 # do not bother on NaCl
|
||||||
// $G $D/$F.go && $L $F.$A &&
|
// $G $D/$F.go && $L $F.$A &&
|
||||||
// ((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
|
// ((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// [ $GOOS != nacl ] || exit 0 # do not bother on NaCl
|
||||||
// $G $D/$F.go && $L $F.$A &&
|
// $G $D/$F.go && $L $F.$A &&
|
||||||
// ((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
|
// ((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// [ $GOOS != nacl ] || exit 0 # do not bother on NaCl
|
||||||
// $G $D/$F.go && $L $F.$A &&
|
// $G $D/$F.go && $L $F.$A &&
|
||||||
// ((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
|
// ((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// [ $GOOS != nacl ] || exit 0 # do not bother on NaCl
|
||||||
// $G $D/$F.go && $L $F.$A &&
|
// $G $D/$F.go && $L $F.$A &&
|
||||||
// ((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
|
// ((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// [ $GOOS != nacl ] || exit 0 # do not bother on NaCl
|
||||||
// $G $D/$F.go && $L $F.$A &&
|
// $G $D/$F.go && $L $F.$A &&
|
||||||
// ((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
|
// ((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// [ $GOOS != nacl ] || exit 0 # do not bother on NaCl
|
||||||
// $G $D/$F.go && $L $F.$A &&
|
// $G $D/$F.go && $L $F.$A &&
|
||||||
// ((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
|
// ((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// [ $GOOS != nacl ] || exit 0 # do not bother on NaCl
|
||||||
// $G $D/$F.go && $L $F.$A &&
|
// $G $D/$F.go && $L $F.$A &&
|
||||||
// ((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
|
// ((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// [ $GOOS != nacl ] || exit 0 # do not bother on NaCl
|
||||||
// $G $D/$F.go && $L $F.$A &&
|
// $G $D/$F.go && $L $F.$A &&
|
||||||
// ((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
|
// ((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// [ $GOOS != nacl ] || exit 0 # do not bother on NaCl
|
||||||
// $G $D/$F.go && $L $F.$A &&
|
// $G $D/$F.go && $L $F.$A &&
|
||||||
// ((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
|
// ((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// [ $GOOS != nacl ] || exit 0 # NaCl runner elides NUL in output
|
||||||
// $G $D/$F.go && $L $F.$A && ./$A.out >tmp.go &&
|
// $G $D/$F.go && $L $F.$A && ./$A.out >tmp.go &&
|
||||||
// errchk $G -e tmp.go
|
// errchk $G -e tmp.go
|
||||||
// rm -f tmp.go
|
// rm -f tmp.go
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// [ $GOOS != nacl ] || exit 0 # NaCl cannot recover from signals
|
||||||
// $G $D/$F.go && $L $F.$A && ./$A.out
|
// $G $D/$F.go && $L $F.$A && ./$A.out
|
||||||
|
|
||||||
// Copyright 2010 The Go Authors. All rights reserved.
|
// Copyright 2010 The Go Authors. All rights reserved.
|
||||||
|
2
test/run
2
test/run
@ -22,7 +22,7 @@ esac
|
|||||||
|
|
||||||
case X"$GOOS" in
|
case X"$GOOS" in
|
||||||
Xnacl)
|
Xnacl)
|
||||||
export E="nacl"
|
export E=${GORUN:-$GOROOT/misc/nacl/naclrun}
|
||||||
esac
|
esac
|
||||||
|
|
||||||
export G=${A}g
|
export G=${A}g
|
||||||
|
@ -1,84 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
# Copyright 2009 The Go Authors. All rights reserved.
|
|
||||||
# Use of this source code is governed by a BSD-style
|
|
||||||
# license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
case X"$GOARCH" in
|
|
||||||
X386)
|
|
||||||
# After downloading the Native Client binary distribution,
|
|
||||||
# copy build/native_client/scons-out/opt-*/obj/src/trusted/service_runtime/sel_ldr
|
|
||||||
# into your path as "nacl". You might need to wrap it to get rid of the
|
|
||||||
# 'Exit syscall handler' print. To do that, install the binary as nacl.bin and
|
|
||||||
# make this script nacl:
|
|
||||||
# #!/bin/sh
|
|
||||||
# nacl.bin "$@" 2>&1 | grep -v 'Exit syscall handler: 0'
|
|
||||||
# exit 0
|
|
||||||
export A=8
|
|
||||||
export E=nacl
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo 1>&2 run: unsupported '$GOARCH'
|
|
||||||
exit 1
|
|
||||||
esac
|
|
||||||
|
|
||||||
export G=${A}g
|
|
||||||
export L=${A}l
|
|
||||||
export GOTRACEBACK=0
|
|
||||||
|
|
||||||
failed=0
|
|
||||||
|
|
||||||
export PATH=/bin:/usr/bin:/usr/local/bin:${GOBIN:-$HOME/bin}:$HOME/bin:$(pwd)
|
|
||||||
|
|
||||||
RUNFILE=/tmp/gorun-$$-$USER
|
|
||||||
TMP1FILE=/tmp/gotest1-$$-$USER
|
|
||||||
TMP2FILE=/tmp/gotest2-$$-$USER
|
|
||||||
|
|
||||||
# don't run the machine out of memory: limit individual processes to 4GB.
|
|
||||||
# on thresher, 3GB suffices to run the tests; with 2GB, peano fails.
|
|
||||||
ulimit -v 4000000
|
|
||||||
|
|
||||||
for i in $(cat nacl-pass.txt)
|
|
||||||
do
|
|
||||||
export F=$(basename $i .go)
|
|
||||||
dir=$(dirname $i)
|
|
||||||
export D=$dir
|
|
||||||
sed '/^\/\//!q; s|//||g; s|./\$A.out|$E &|' $i >$RUNFILE
|
|
||||||
if ! sh $RUNFILE >$TMP1FILE 2>$TMP2FILE
|
|
||||||
then
|
|
||||||
echo
|
|
||||||
echo "===========" $i
|
|
||||||
cat $TMP1FILE
|
|
||||||
cat $TMP2FILE
|
|
||||||
echo >&2 fail: $i
|
|
||||||
elif test -s $TMP1FILE || test -s $TMP2FILE
|
|
||||||
then
|
|
||||||
echo
|
|
||||||
echo "===========" $i
|
|
||||||
cat $TMP1FILE
|
|
||||||
cat $TMP2FILE
|
|
||||||
elif [ $dir = "bugs" ]
|
|
||||||
then
|
|
||||||
echo $i succeeded with no output.
|
|
||||||
fi
|
|
||||||
done | # clean up some stack noise
|
|
||||||
egrep -v '^(r[0-9a-z]+|[cfg]s) +0x' |
|
|
||||||
sed '/tmp.*Bus error/s/.*Bus/Bus/; /tmp.*Trace.BPT/s/.*Trace/Trace/
|
|
||||||
s!'$RUNFILE'!$RUNFILE!g
|
|
||||||
s/ PC=0x[0-9a-f]*/ PC=xxx/
|
|
||||||
s/^pc: 0x[0-9a-f]*/pc: xxx/
|
|
||||||
/^Trace\/breakpoint trap/d
|
|
||||||
/^Trace\/BPT trap/d
|
|
||||||
/RUNFILE/ s/line 1: *[0-9][0-9]* /line 1: PID /
|
|
||||||
/^\$RUNFILE: line 1: PID Trace\/breakpoint trap/d
|
|
||||||
/^qemu: uncaught target signal 11 (Segmentation fault) - exiting/d' > run.out
|
|
||||||
|
|
||||||
case $failed in
|
|
||||||
0)
|
|
||||||
echo PASS
|
|
||||||
;;
|
|
||||||
1)
|
|
||||||
echo FAIL
|
|
||||||
esac
|
|
||||||
rm -f $RUNFILE $TMP1FILE $TMP2FILE *.$A $A.out
|
|
||||||
|
|
||||||
exit $failed
|
|
@ -1,3 +1,4 @@
|
|||||||
|
// if [ $GOOS == nacl ]; then echo survived SIGCHLD; exit 0; fi # NaCl has no signals.
|
||||||
// $G $D/$F.go && $L $F.$A && ./$A.out
|
// $G $D/$F.go && $L $F.$A && ./$A.out
|
||||||
|
|
||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
@ -68,5 +68,5 @@ func main() {
|
|||||||
for i := 0; i < len(t); i++ {
|
for i := 0; i < len(t); i++ {
|
||||||
t[i] = 1
|
t[i] = 1
|
||||||
}
|
}
|
||||||
recur(10000)
|
recur(8000)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user