diff options
author | Micael Karlberg <[email protected]> | 2012-01-30 14:33:54 +0100 |
---|---|---|
committer | Micael Karlberg <[email protected]> | 2012-01-30 14:33:54 +0100 |
commit | a63e3a9bde3e9cac5acee7ca9508da58b2f35591 (patch) | |
tree | 3ea3dc3e62f1d7975059d5a240895ef85160afc4 | |
parent | a0e8f2621a39ca8e032b8ec30164207de1d7c26e (diff) | |
parent | 18b640a02e5493eb9fe23ae6dc0c38c754f61d0e (diff) | |
download | otp-a63e3a9bde3e9cac5acee7ca9508da58b2f35591.tar.gz otp-a63e3a9bde3e9cac5acee7ca9508da58b2f35591.tar.bz2 otp-a63e3a9bde3e9cac5acee7ca9508da58b2f35591.zip |
Merge branch 'master' of super:otp
22 files changed, 297 insertions, 154 deletions
diff --git a/bootstrap/lib/compiler/ebin/beam_utils.beam b/bootstrap/lib/compiler/ebin/beam_utils.beam Binary files differindex 12372309d9..9c6ad019f9 100644 --- a/bootstrap/lib/compiler/ebin/beam_utils.beam +++ b/bootstrap/lib/compiler/ebin/beam_utils.beam diff --git a/bootstrap/lib/kernel/ebin/code_server.beam b/bootstrap/lib/kernel/ebin/code_server.beam Binary files differindex 09d86b80ad..adc53aa5f3 100644 --- a/bootstrap/lib/kernel/ebin/code_server.beam +++ b/bootstrap/lib/kernel/ebin/code_server.beam diff --git a/bootstrap/lib/stdlib/ebin/erl_expand_records.beam b/bootstrap/lib/stdlib/ebin/erl_expand_records.beam Binary files differindex 753a0a3fec..5c9663cd54 100644 --- a/bootstrap/lib/stdlib/ebin/erl_expand_records.beam +++ b/bootstrap/lib/stdlib/ebin/erl_expand_records.beam diff --git a/bootstrap/lib/stdlib/ebin/erl_lint.beam b/bootstrap/lib/stdlib/ebin/erl_lint.beam Binary files differindex 6288139fdd..6fa0884135 100644 --- a/bootstrap/lib/stdlib/ebin/erl_lint.beam +++ b/bootstrap/lib/stdlib/ebin/erl_lint.beam diff --git a/erts/emulator/beam/beam_bp.c b/erts/emulator/beam/beam_bp.c index 692fa61fe8..dd13cd179a 100644 --- a/erts/emulator/beam/beam_bp.c +++ b/erts/emulator/beam/beam_bp.c @@ -1329,10 +1329,14 @@ static BpData *get_break(Process *p, BeamInstr *pc, BeamInstr break_op) { } static BpData *is_break(BeamInstr *pc, BeamInstr break_op) { - BpData **rs = (BpData **) pc[-4]; + BpData **rs; BpData *bd = NULL, *ebd = NULL; ASSERT(pc[-5] == (BeamInstr) BeamOp(op_i_func_info_IaaI)); + if (erts_is_native_break(pc)) { + return NULL; + } + rs = (BpData **) pc[-4]; if (! rs) { return NULL; } diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c index dd788df6e4..1f9635a6c1 100644 --- a/erts/emulator/beam/beam_load.c +++ b/erts/emulator/beam/beam_load.c @@ -507,6 +507,7 @@ static int verify_chunks(LoaderState* stp); static int load_atom_table(LoaderState* stp); static int load_import_table(LoaderState* stp); static int read_export_table(LoaderState* stp); +static int is_bif(Eterm mod, Eterm func, unsigned arity); static int read_lambda_table(LoaderState* stp); static int read_literal_table(LoaderState* stp); static int read_line_table(LoaderState* stp); @@ -666,7 +667,7 @@ erts_prepare_loading(LoaderState* stp, Process *c_p, Eterm group_leader, /* * Initialize code area. */ - stp->code_buffer_size = erts_next_heap_size(2048 + stp->num_functions, 0); + stp->code_buffer_size = 2048 + stp->num_functions; stp->code = (BeamInstr *) erts_alloc(ERTS_ALC_T_CODE, sizeof(BeamInstr) * stp->code_buffer_size); @@ -1218,8 +1219,7 @@ load_atom_table(LoaderState* stp) GetInt(stp, 4, stp->num_atoms); stp->num_atoms++; stp->atom = erts_alloc(ERTS_ALC_T_LOADER_TMP, - erts_next_heap_size((stp->num_atoms*sizeof(Eterm)), - 0)); + stp->num_atoms*sizeof(Eterm)); /* * Read all atoms. @@ -1264,9 +1264,7 @@ load_import_table(LoaderState* stp) GetInt(stp, 4, stp->num_imports); stp->import = erts_alloc(ERTS_ALC_T_LOADER_TMP, - erts_next_heap_size((stp->num_imports * - sizeof(ImportEntry)), - 0)); + stp->num_imports * sizeof(ImportEntry)); for (i = 0; i < stp->num_imports; i++) { int n; Eterm mod; @@ -1315,16 +1313,8 @@ load_import_table(LoaderState* stp) static int read_export_table(LoaderState* stp) { - static struct { - Eterm mod; - Eterm func; - int arity; - } allow_redef[] = { - /* The BIFs that are allowed to be redefined by Erlang code */ - {am_erlang,am_apply,2}, - {am_erlang,am_apply,3}, - }; int i; + BeamInstr* address; GetInt(stp, 4, stp->num_exps); if (stp->num_exps > stp->num_functions) { @@ -1340,7 +1330,6 @@ read_export_table(LoaderState* stp) Uint value; Eterm func; Uint arity; - Export* e; GetInt(stp, 4, n); GetAtom(stp, n, func); @@ -1358,29 +1347,34 @@ read_export_table(LoaderState* stp) if (value == 0) { LoadError2(stp, "export table entry %d: label %d not resolved", i, n); } - stp->export[i].address = stp->code + value; + stp->export[i].address = address = stp->code + value; /* - * Check that we are not redefining a BIF (except the ones allowed to - * redefine). + * Find out if there is a BIF with the same name. */ - if ((e = erts_find_export_entry(stp->module, func, arity)) != NULL) { - if (e->code[3] == (BeamInstr) em_apply_bif) { - int j; - for (j = 0; j < sizeof(allow_redef)/sizeof(allow_redef[0]); j++) { - if (stp->module == allow_redef[j].mod && - func == allow_redef[j].func && - arity == allow_redef[j].arity) { - break; - } - } - if (j == sizeof(allow_redef)/sizeof(allow_redef[0])) { - LoadError2(stp, "exported function %T/%d redefines BIF", - func, arity); - } - } + if (!is_bif(stp->module, func, arity)) { + continue; + } + + /* + * This is a stub for a BIF. + * + * It should not be exported, and the information in its + * func_info instruction should be invalidated so that it + * can be filtered out by module_info(functions) and by + * any other functions that walk through all local functions. + */ + + if (stp->labels[n].patches) { + LoadError3(stp, "there are local calls to the stub for " + "the BIF %T:%T/%d", + stp->module, func, arity); } + stp->export[i].address = NULL; + address[-1] = 0; + address[-2] = NIL; + address[-3] = NIL; } return 1; @@ -1388,6 +1382,27 @@ read_export_table(LoaderState* stp) return 0; } + +static int +is_bif(Eterm mod, Eterm func, unsigned arity) +{ + Export* e = erts_find_export_entry(mod, func, arity); + if (e == NULL) { + return 0; + } + if (e->code[3] != (BeamInstr) em_apply_bif) { + return 0; + } + if (mod == am_erlang && func == am_apply && arity == 3) { + /* + * erlang:apply/3 is a special case -- it is implemented + * as an instruction and it is OK to redefine it. + */ + return 0; + } + return 1; +} + static int read_lambda_table(LoaderState* stp) { @@ -1703,9 +1718,9 @@ read_code_header(LoaderState* stp) #define CodeNeed(w) do { \ ASSERT(ci <= code_buffer_size); \ if (code_buffer_size < ci+(w)) { \ - code_buffer_size = erts_next_heap_size(ci+(w), 0); \ - stp->code = code \ - = (BeamInstr *) erts_realloc(ERTS_ALC_T_CODE, \ + code_buffer_size = 2*ci+(w); \ + stp->code = code = \ + (BeamInstr *) erts_realloc(ERTS_ALC_T_CODE, \ (void *) code, \ code_buffer_size * sizeof(BeamInstr)); \ } \ @@ -2457,6 +2472,9 @@ load_code(LoaderState* stp) case op_int_code_end: stp->code_buffer_size = code_buffer_size; stp->ci = ci; + stp->function = THE_NON_VALUE; + stp->genop = NULL; + stp->specific_op = -1; return 1; } @@ -4272,17 +4290,24 @@ final_touch(LoaderState* stp) */ for (i = 0; i < stp->num_exps; i++) { - Export* ep = erts_export_put(stp->module, stp->export[i].function, - stp->export[i].arity); + Export* ep; + BeamInstr* address = stp->export[i].address; + + if (address == NULL) { + /* Skip stub for a BIF */ + continue; + } + ep = erts_export_put(stp->module, stp->export[i].function, + stp->export[i].arity); if (!on_load) { - ep->address = stp->export[i].address; + ep->address = address; } else { /* * Don't make any of the exported functions * callable yet. */ ep->address = ep->code+3; - ep->code[4] = (BeamInstr) stp->export[i].address; + ep->code[4] = (BeamInstr) address; } } @@ -5054,7 +5079,9 @@ functions_in_module(Process* p, /* Process whose heap to use. */ BeamInstr* code; int i; Uint num_functions; + Uint need; Eterm* hp; + Eterm* hp_end; Eterm result = NIL; if (is_not_atom(mod)) { @@ -5067,19 +5094,28 @@ functions_in_module(Process* p, /* Process whose heap to use. */ } code = modp->code; num_functions = code[MI_NUM_FUNCTIONS]; - hp = HAlloc(p, 5*num_functions); + need = 5*num_functions; + hp = HAlloc(p, need); + hp_end = hp + need; for (i = num_functions-1; i >= 0 ; i--) { BeamInstr* func_info = (BeamInstr *) code[MI_FUNCTIONS+i]; Eterm name = (Eterm) func_info[3]; int arity = (int) func_info[4]; Eterm tuple; - ASSERT(is_atom(name)); - tuple = TUPLE2(hp, name, make_small(arity)); - hp += 3; - result = CONS(hp, tuple, result); - hp += 2; + /* + * If the function name is [], this entry is a stub for + * a BIF that should be ignored. + */ + ASSERT(is_atom(name) || is_nil(name)); + if (is_atom(name)) { + tuple = TUPLE2(hp, name, make_small(arity)); + hp += 3; + result = CONS(hp, tuple, result); + hp += 2; + } } + HRelease(p, hp_end, hp); return result; } @@ -5627,19 +5663,28 @@ stub_final_touch(LoaderState* stp, BeamInstr* fp) { int i; int n = stp->num_exps; + Eterm mod = fp[2]; Eterm function = fp[3]; int arity = fp[4]; #ifdef HIPE Lambda* lp; #endif + if (is_bif(mod, function, arity)) { + fp[1] = 0; + fp[2] = 0; + fp[3] = 0; + fp[4] = 0; + return; + } + /* * Test if the function should be exported. */ for (i = 0; i < n; i++) { if (stp->export[i].function == function && stp->export[i].arity == arity) { - Export* ep = erts_export_put(fp[2], function, arity); + Export* ep = erts_export_put(mod, function, arity); ep->address = fp+5; return; } diff --git a/erts/emulator/beam/ops.tab b/erts/emulator/beam/ops.tab index fc53a88a3a..f051f6aa5b 100644 --- a/erts/emulator/beam/ops.tab +++ b/erts/emulator/beam/ops.tab @@ -829,16 +829,20 @@ call_ext_only Ar=u==2 Bif=u$bif:erlang:load_nif/2 => allocate u Ar | i_call_ext # -# The apply/2 and apply/3 BIFs are instructions. +# apply/2 is an instruction, not a BIF. # call_ext u==2 u$func:erlang:apply/2 => i_apply_fun call_ext_last u==2 u$func:erlang:apply/2 D => i_apply_fun_last D call_ext_only u==2 u$func:erlang:apply/2 => i_apply_fun_only -call_ext u==3 u$func:erlang:apply/3 => i_apply -call_ext_last u==3 u$func:erlang:apply/3 D => i_apply_last D -call_ext_only u==3 u$func:erlang:apply/3 => i_apply_only +# +# The apply/3 BIF is an instruction. +# + +call_ext u==3 u$bif:erlang:apply/3 => i_apply +call_ext_last u==3 u$bif:erlang:apply/3 D => i_apply_last D +call_ext_only u==3 u$bif:erlang:apply/3 => i_apply_only # # The exit/1 and throw/1 BIFs never execute the instruction following them; diff --git a/lib/compiler/src/beam_utils.erl b/lib/compiler/src/beam_utils.erl index a631b8cd69..116ede0bc9 100644 --- a/lib/compiler/src/beam_utils.erl +++ b/lib/compiler/src/beam_utils.erl @@ -474,8 +474,15 @@ check_liveness(R, [{make_fun2,_,_,_,NumFree}|Is], St) -> end; check_liveness(R, [{try_end,Y}|Is], St) -> case R of - Y -> {killed,St}; - _ -> check_liveness(R, Is, St) + Y -> + {killed,St}; + {y,_} -> + %% y registers will be used if an exception occurs and + %% control transfers to the label given in the previous + %% try/2 instruction. + {used,St}; + _ -> + check_liveness(R, Is, St) end; check_liveness(R, [{catch_end,Y}|Is], St) -> case R of diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl index 32d53add53..640849f2ec 100644 --- a/lib/compiler/test/compile_SUITE.erl +++ b/lib/compiler/test/compile_SUITE.erl @@ -813,9 +813,9 @@ sys_pre_attributes(Config) -> {ok,Mod,_} = compile:file(File, PreOpts ++ CommonOpts), {ok,Mod,_} = compile:file(File, [{attribute,replace,replaced,42}|CommonOpts]), - {ok,Mod,Code} = compile:file(File, PrePostOpts ++ PreOpts ++ - PostOpts ++ CommonOpts -- - [report,verbose]), + {ok,Mod,_} = compile:file(File, PrePostOpts ++ PreOpts ++ + PostOpts ++ CommonOpts -- + [report,verbose]), ok. %%% diff --git a/lib/compiler/test/trycatch_SUITE.erl b/lib/compiler/test/trycatch_SUITE.erl index 760cf17225..09a23724fe 100644 --- a/lib/compiler/test/trycatch_SUITE.erl +++ b/lib/compiler/test/trycatch_SUITE.erl @@ -24,7 +24,7 @@ catch_oops/1,after_oops/1,eclectic/1,rethrow/1, nested_of/1,nested_catch/1,nested_after/1, nested_horrid/1,last_call_optimization/1,bool/1, - plain_catch_coverage/1,andalso_orelse/1]). + plain_catch_coverage/1,andalso_orelse/1,get_in_try/1]). -include_lib("test_server/include/test_server.hrl"). @@ -35,7 +35,7 @@ all() -> [basic, lean_throw, try_of, try_after, catch_oops, after_oops, eclectic, rethrow, nested_of, nested_catch, nested_after, nested_horrid, last_call_optimization, - bool, plain_catch_coverage, andalso_orelse]. + bool, plain_catch_coverage, andalso_orelse, get_in_try]. groups() -> []. @@ -928,3 +928,17 @@ andalso_orelse_2({Type,Keyval}) -> zero() -> 0.0. + +get_in_try(_) -> + undefined = get_valid_line([a], []), + ok. + +get_valid_line([_|T]=Path, Annotations) -> + try + get(Path) + %% beam_dead used to optimize away an assignment to {y,1} + %% because it didn't appear to be used. + catch + _:not_found -> + get_valid_line(T, Annotations) + end. diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl index 32a12e2b52..5d4f2eb70c 100644 --- a/lib/kernel/src/code_server.erl +++ b/lib/kernel/src/code_server.erl @@ -1317,15 +1317,21 @@ int_list([H|T]) when is_integer(H) -> int_list(T); int_list([_|_]) -> false; int_list([]) -> true. +load_file(Mod0, {From,_}=Caller, St0) -> + Mod = to_atom(Mod0), + case pending_on_load(Mod, From, St0) of + no -> load_file_1(Mod, Caller, St0); + {yes,St} -> {noreply,St} + end. -load_file(Mod, Caller, #state{path=Path,cache=no_cache}=St) -> +load_file_1(Mod, Caller, #state{path=Path,cache=no_cache}=St) -> case mod_to_bin(Path, Mod) of error -> {reply,{error,nofile},St}; {Mod,Binary,File} -> try_load_module(File, Mod, Binary, Caller, St) end; -load_file(Mod, Caller, #state{cache=Cache}=St0) -> +load_file_1(Mod, Caller, #state{cache=Cache}=St0) -> Key = {obj,Mod}, case ets:lookup(Cache, Key) of [] -> diff --git a/lib/kernel/src/hipe_unified_loader.erl b/lib/kernel/src/hipe_unified_loader.erl index 8b3aa0286d..1b56cd8d90 100644 --- a/lib/kernel/src/hipe_unified_loader.erl +++ b/lib/kernel/src/hipe_unified_loader.erl @@ -330,11 +330,16 @@ exports(ExportMap, BaseAddress) -> exports(ExportMap, BaseAddress, [], []). exports([Offset,M,F,A,IsClosure,IsExported|Rest], BaseAddress, MFAs, Addresses) -> - MFA = {M,F,A}, - Address = BaseAddress + Offset, - FunDef = #fundef{address=Address, mfa=MFA, is_closure=IsClosure, - is_exported=IsExported}, - exports(Rest, BaseAddress, [MFA|MFAs], [FunDef|Addresses]); + case IsExported andalso erlang:is_builtin(M, F, A) of + true -> + exports(Rest, BaseAddress, MFAs, Addresses); + _false -> + MFA = {M,F,A}, + Address = BaseAddress + Offset, + FunDef = #fundef{address=Address, mfa=MFA, is_closure=IsClosure, + is_exported=IsExported}, + exports(Rest, BaseAddress, [MFA|MFAs], [FunDef|Addresses]) + end; exports([], _, MFAs, Addresses) -> {MFAs, Addresses}. diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index 10ab3e4370..99b0cd2ffb 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -30,9 +30,9 @@ load_cached/1, start_node_with_cache/1, add_and_rehash/1, where_is_file_cached/1, where_is_file_no_cache/1, purge_stacktrace/1, mult_lib_roots/1, bad_erl_libs/1, - code_archive/1, code_archive2/1, on_load/1, - big_boot_embedded/1, - on_load_embedded/1, on_load_errors/1, native_early_modules/1]). + code_archive/1, code_archive2/1, on_load/1, on_load_binary/1, + on_load_embedded/1, on_load_errors/1, big_boot_embedded/1, + native_early_modules/1]). -export([init_per_testcase/2, end_per_testcase/2, init_per_suite/1, end_per_suite/1, @@ -55,8 +55,8 @@ all() -> add_and_rehash, where_is_file_no_cache, where_is_file_cached, purge_stacktrace, mult_lib_roots, bad_erl_libs, code_archive, code_archive2, on_load, - on_load_embedded, big_boot_embedded, on_load_errors, - native_early_modules]. + on_load_binary, on_load_embedded, on_load_errors, + big_boot_embedded, native_early_modules]. groups() -> []. @@ -1286,6 +1286,45 @@ on_load_wait_for_all([Ref|T]) -> end; on_load_wait_for_all([]) -> ok. +on_load_binary(_) -> + Master = on_load_binary_test_case_process, + register(Master, self()), + + %% Construct, compile and pretty-print. + Mod = on_load_binary, + File = atom_to_list(Mod) ++ ".erl", + Forms = [{attribute,1,file,{File,1}}, + {attribute,1,module,Mod}, + {attribute,2,export,[{ok,0}]}, + {attribute,3,on_load,{init,0}}, + {function,5,init,0, + [{clause,5,[],[], + [{op,6,'!', + {atom,6,Master}, + {tuple,6,[{atom,6,Mod},{call,6,{atom,6,self},[]}]}}, + {'receive',7,[{clause,8,[{atom,8,go}],[],[{atom,8,ok}]}]}]}]}, + {function,11,ok,0,[{clause,11,[],[],[{atom,11,true}]}]}], + {ok,Mod,Bin} = compile:forms(Forms, [report]), + [io:put_chars(erl_pp:form(F)) || F <- Forms], + + {Pid1,Ref1} = spawn_monitor(fun() -> + code:load_binary(Mod, File, Bin), + true = on_load_binary:ok() + end), + receive {Mod,OnLoadPid} -> ok end, + {Pid2,Ref2} = spawn_monitor(fun() -> + true = on_load_binary:ok() + end), + erlang:yield(), + OnLoadPid ! go, + receive {'DOWN',Ref1,process,Pid1,Exit1} -> ok end, + receive {'DOWN',Ref2,process,Pid2,Exit2} -> ok end, + normal = Exit1, + normal = Exit2, + true = code:delete(on_load_binary), + false = code:purge(on_load_binary), + ok. + on_load_embedded(Config) when is_list(Config) -> try on_load_embedded_1(Config) diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl index 6cab40d49d..2b6af7e1fb 100644 --- a/lib/kernel/test/file_SUITE.erl +++ b/lib/kernel/test/file_SUITE.erl @@ -93,7 +93,7 @@ %% System probe functions that might be handy to check from the shell --export([unix_free/1, memsize/0, bsd_memsize/1]). +-export([disc_free/1, memsize/0]). -include_lib("test_server/include/test_server.hrl"). -include_lib("kernel/include/file.hrl"). @@ -145,6 +145,13 @@ end_per_group(_GroupName, Config) -> init_per_suite(Config) when is_list(Config) -> + SaslConfig = case application:start(sasl) of + {error, {already_started, sasl}} -> + []; + ok -> + [{sasl,started}] + end, + ok = application:start(os_mon), case os:type() of {win32, _} -> Priv = ?config(priv_dir, Config), @@ -156,9 +163,9 @@ init_per_suite(Config) when is_list(Config) -> {ok, _} -> [] end, - ?FILE_INIT(HasAccessTime++Config); + ?FILE_INIT(HasAccessTime++Config++SaslConfig); _ -> - ?FILE_INIT(Config) + ?FILE_INIT(Config++SaslConfig) end. end_per_suite(Config) when is_list(Config) -> @@ -168,6 +175,13 @@ end_per_suite(Config) when is_list(Config) -> _ -> ok end, + application:stop(os_mon), + case proplists:get_value(sasl, Config) of + started -> + application:stop(sasl); + _Else -> + ok + end, ?FILE_FINI(Config). init_per_testcase(_Func, Config) -> @@ -3949,7 +3963,7 @@ run_large_file_test(Config, Run, Name) -> {{unix,sunos},OsVersion} when OsVersion < {5,5,1} -> {skip,"Only supported on Win32, Unix or SunOS >= 5.5.1"}; {{unix,_},_} -> - N = unix_free(?config(priv_dir, Config)), + N = disc_free(?config(priv_dir, Config)), io:format("Free disk: ~w KByte~n", [N]), if N < 5 * (1 bsl 20) -> %% Less than 5 GByte free @@ -3989,58 +4003,15 @@ do_run_large_file_test(Config, Run, Name0) -> Res. -unix_free(Path) -> - Cmd = ["df -k '",Path,"'"], - DF0 = os:cmd(Cmd), - io:format("$ ~s~n~s", [Cmd,DF0]), - Lines = re:split(DF0, "\n", [trim,{return,list}]), - Last = lists:last(Lines), - RE = "^[^\\s]*\\s+\\d+\\s+\\d+\\s+(\\d+)", - {match,[Avail]} = re:run(Last, RE, [{capture,all_but_first,list}]), - list_to_integer(Avail). +disc_free(Path) -> + Data = disksup:get_disk_data(), + {_,Tot,Perc} = hd(lists:filter( + fun({P,_Size,_Full}) -> + lists:prefix(filename:nativename(P), + filename:nativename(Path)) + end, lists:reverse(lists:sort(Data)))), + round(Tot * (1-(Perc/100))). memsize() -> - case os:type() of - {unix,openbsd} -> - bsd_memsize("hw.physmem"); - {unix,freebsd} -> - bsd_memsize("hw.physmem"); - {unix,darwin} -> - bsd_memsize("hw.memsize"); - {unix,linux} -> - Meminfo = os:cmd("cat /proc/meminfo"), - Re = "^MemTotal:\\s+(\\d+)\\s+kB\$", - ReOpts = [multiline,{capture,all_but_first,list}], - case re:run(Meminfo, Re, ReOpts) of - {match,[Str]} -> - list_to_integer(Str) bsl 10; - nomatch -> - 0 - end; - {win32,_} -> - enough; % atom() > integer(); assume (64-bit) windows have enough - _ -> - 0 - end. - -bsd_memsize(MIB) -> - Reply = os:cmd(["sysctl ",MIB]), - try strip_prefix(MIB, Reply) of - Str -> - Re = "^\\s*(?::|=)\\s*(\\d+)", - ReOpts = [{capture,all_but_first,list}], - case re:run(Str, Re, ReOpts) of - {match,[SizeStr]} -> - list_to_integer(SizeStr); - nomatch -> - 0 - end - catch - error:_ -> - 0 - end. - -strip_prefix([X|Prefix], [X|List]) -> - strip_prefix(Prefix, List); -strip_prefix([], List) -> - List. + {Tot,_Used,_} = memsup:get_memory_data(), + Tot. diff --git a/lib/os_mon/src/cpu_sup.erl b/lib/os_mon/src/cpu_sup.erl index e414e2c10b..34251178ee 100644 --- a/lib/os_mon/src/cpu_sup.erl +++ b/lib/os_mon/src/cpu_sup.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -764,8 +764,7 @@ port_receive_cpu_util_entries(_, _, Data) -> exit({data_mismatch, Data}). start_portprogram() -> - Command = filename:join([code:priv_dir(os_mon), "bin", "cpu_sup"]), - Port = open_port({spawn, Command}, [stream]), + Port = os_mon:open_port("cpu_sup", [stream]), port_command(Port, ?ping), 4711 = port_receive_uint32(Port, 5000), Port. diff --git a/lib/os_mon/src/memsup.erl b/lib/os_mon/src/memsup.erl index ba07a529bc..49533da1f7 100644 --- a/lib/os_mon/src/memsup.erl +++ b/lib/os_mon/src/memsup.erl @@ -802,8 +802,7 @@ port_init() -> port_idle(Port). start_portprogram() -> - Command = filename:join([code:priv_dir(os_mon), "bin", "memsup"]), - open_port({spawn, Command}, [{packet, 1}]). + os_mon:open_port("memsup",[{packet,1}]). %% The connected process loops are a bit awkward (several different %% functions doing almost the same thing) as diff --git a/lib/os_mon/src/os_mon.erl b/lib/os_mon/src/os_mon.erl index ef368571db..3098c38808 100644 --- a/lib/os_mon/src/os_mon.erl +++ b/lib/os_mon/src/os_mon.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2009. All Rights Reserved. +%% Copyright Ericsson AB 1996-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -22,7 +22,7 @@ -behaviour(supervisor). %% API --export([call/2, call/3, get_env/2]). +-export([call/2, call/3, get_env/2, open_port/2]). %% Application callbacks -export([start/2, stop/1]). @@ -79,6 +79,22 @@ get_env(Service, Param) -> Service:param_default(Param) end. +open_port(Name, Opts) -> + PrivDir = code:priv_dir(os_mon), + ReleasedPath = filename:join([PrivDir,"bin",Name]), + %% Check os_mon*/priv/bin/Name + case filelib:is_regular(ReleasedPath) of + true -> + erlang:open_port({spawn, ReleasedPath}, Opts); + false -> + %% Use os_mon*/priv/bin/Arch/Name + ArchPath = + filename:join( + [PrivDir,"bin",erlang:system_info(system_architecture),Name]), + erlang:open_port({spawn, ArchPath}, Opts) + end. + + %%%----------------------------------------------------------------- %%% Application callbacks %%%----------------------------------------------------------------- diff --git a/lib/os_mon/src/os_mon_sysinfo.erl b/lib/os_mon/src/os_mon_sysinfo.erl index 5d12bd95d1..080885d5d6 100644 --- a/lib/os_mon/src/os_mon_sysinfo.erl +++ b/lib/os_mon/src/os_mon_sysinfo.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% Copyright Ericsson AB 1997-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -108,9 +108,7 @@ code_change(_OldVsn, State, _Extra) -> %%---------------------------------------------------------------------- start_portprogram() -> - Command = - filename:join([code:priv_dir(os_mon),"bin","win32sysinfo.exe"]), - Port = open_port({spawn,Command}, [{packet,1}]), + Port = os_mon:open_port("win32sysinfo.exe", [{packet,1}]), receive {Port, {data, [?OK]}} -> Port; diff --git a/lib/stdlib/src/erl_expand_records.erl b/lib/stdlib/src/erl_expand_records.erl index 20fd247cea..1c69a131f9 100644 --- a/lib/stdlib/src/erl_expand_records.erl +++ b/lib/stdlib/src/erl_expand_records.erl @@ -452,8 +452,10 @@ conj([], _E) -> conj([{{Name,_Rp},L,R,Sz} | AL], E) -> NL = neg_line(L), T1 = {op,NL,'orelse', - {call,NL,{atom,NL,is_record},[R,{atom,NL,Name},{integer,NL,Sz}]}, - {atom,NL,fail}}, + {call,NL, + {remote,NL,{atom,NL,erlang},{atom,NL,is_record}}, + [R,{atom,NL,Name},{integer,NL,Sz}]}, + {atom,NL,fail}}, T2 = case conj(AL, none) of empty -> T1; C -> {op,NL,'and',C,T1} @@ -581,7 +583,9 @@ strict_get_record_field(Line, R, {atom,_,F}=Index, Name, St0) -> ExpRp = erl_lint:modify_line(ExpR, fun(_L) -> 0 end), RA = {{Name,ExpRp},Line,ExpR,length(Fs)+1}, St2 = St1#exprec{strict_ra = [RA | St1#exprec.strict_ra]}, - {{call,Line,{atom,Line,element},[I,ExpR]},St2} + {{call,Line, + {remote,Line,{atom,Line,erlang},{atom,Line,element}}, + [I,ExpR]},St2} end. record_pattern(I, I, Var, Sz, Line, Acc) -> @@ -593,7 +597,9 @@ record_pattern(_, _, _, _, _, Acc) -> reverse(Acc). sloppy_get_record_field(Line, R, Index, Name, St) -> Fs = record_fields(Name, St), I = index_expr(Line, Index, Name, Fs), - expr({call,Line,{atom,Line,element},[I,R]}, St). + expr({call,Line, + {remote,Line,{atom,Line,erlang},{atom,Line,element}}, + [I,R]}, St). strict_record_tests([strict_record_tests | _]) -> true; strict_record_tests([no_strict_record_tests | _]) -> false; @@ -710,7 +716,8 @@ record_setel(R, Name, Fs, Us0) -> {'case',Lr,R, [{clause,Lr,[{tuple,Lr,[{atom,Lr,Name} | Wildcards]}],[], [foldr(fun ({I,Lf,Val}, Acc) -> - {call,Lf,{atom,Lf,setelement},[I,Acc,Val]} end, + {call,Lf,{remote,Lf,{atom,Lf,erlang}, + {atom,Lf,setelement}},[I,Acc,Val]} end, R, Us)]}, {clause,NLr,[{var,NLr,'_'}],[], [call_error(NLr, {tuple,NLr,[{atom,NLr,badrecord},{atom,NLr,Name}]})]}]}. diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl index 2f29954dc9..cfbcf54d95 100644 --- a/lib/stdlib/src/erl_lint.erl +++ b/lib/stdlib/src/erl_lint.erl @@ -1808,7 +1808,7 @@ guard_test2({call,Line,{atom,_La,F},As}=G, Vt, St0) -> {Asvt,St1} = gexpr_list(As, Vt, St0), %Always check this. A = length(As), case erl_internal:type_test(F, A) of - true when F =/= is_record -> + true when F =/= is_record, A =/= 2 -> case no_guard_bif_clash(St1, {F,A}) of false -> {Asvt,add_error(Line, {illegal_guard_local_call,{F,A}}, St1)}; @@ -1872,9 +1872,15 @@ gexpr({call,Line,{atom,_Lr,is_record},[E,R]}, Vt, St0) -> gexpr({call,Line,{remote,_Lr,{atom,_Lm,erlang},{atom,Lf,is_record}},[E,A]}, Vt, St0) -> gexpr({call,Line,{atom,Lf,is_record},[E,A]}, Vt, St0); -gexpr({call,_Line,{atom,_Lr,is_record},[E,{atom,_,_Name},{integer,_,_}]}, +gexpr({call,Line,{atom,_Lr,is_record},[E0,{atom,_,_Name},{integer,_,_}]}, Vt, St0) -> - gexpr(E, Vt, St0); + {E,St1} = gexpr(E0, Vt, St0), + case no_guard_bif_clash(St0, {is_record,3}) of + true -> + {E,St1}; + false -> + {E,add_error(Line, {illegal_guard_local_call,{is_record,3}}, St1)} + end; gexpr({call,Line,{atom,_Lr,is_record},[_,_,_]=Asvt0}, Vt, St0) -> {Asvt,St1} = gexpr_list(Asvt0, Vt, St0), {Asvt,add_error(Line, illegal_guard_expr, St1)}; diff --git a/lib/stdlib/test/erl_expand_records_SUITE.erl b/lib/stdlib/test/erl_expand_records_SUITE.erl index f8c1ad783c..8b162cfda0 100644 --- a/lib/stdlib/test/erl_expand_records_SUITE.erl +++ b/lib/stdlib/test/erl_expand_records_SUITE.erl @@ -178,6 +178,9 @@ expr(Config) when is_list(Config) -> true -> not_ok end. + + is_record(_, _, _) -> + error(wrong_is_record). ">> ], @@ -366,6 +369,8 @@ strict(Config) when is_list(Config) -> end catch error:_ -> ok end. + element(_, _) -> + error(wrong_element). ">> ], ?line run(Config, Ts1, [strict_record_tests]), @@ -380,6 +385,8 @@ strict(Config) when is_list(Config) -> case foo of _ when A#r2.a =:= 1 -> ok end. + element(_, _) -> + error(wrong_element). ">> ], ?line run(Config, Ts2, [no_strict_record_tests]), @@ -415,6 +422,11 @@ update(Config) when is_list(Config) -> t2() -> R0 = #r{}, #r{_ = R0#r{a = ok}}. + + %% Implicit calls to setelement/3 must go to the BIF, + %% not to this function. + setelement(_, _, _) -> + erlang:error(wrong_setelement_called). ">> ], ?line run(Config, Ts), diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl index e4c7fd5b02..4e93f056ad 100644 --- a/lib/stdlib/test/erl_lint_SUITE.erl +++ b/lib/stdlib/test/erl_lint_SUITE.erl @@ -2633,22 +2633,33 @@ bif_clash(Config) when is_list(Config) -> [warn_unused_import], {warnings,[{2,erl_lint,{redefine_bif_import,{binary_part,3}}}]}}, %% Don't accept call to a guard BIF if there is a local definition - %% or an import with the same name. + %% or an import with the same name. Note: is_record/2 is an + %% exception, since it is more of syntatic sugar than a real BIF. {clash21, <<"-export([is_list/1]). -import(x, [is_tuple/1]). + -record(r, {a,b}). x(T) when is_tuple(T) -> ok; x(T) when is_list(T) -> ok. y(T) when is_tuple(T) =:= true -> ok; - y(T) when is_list(T) =:= true -> ok. + y(T) when is_list(T) =:= true -> ok; + y(T) when is_record(T, r, 3) -> ok; + y(T) when is_record(T, r, 3) =:= true -> ok; + y(T) when is_record(T, r) =:= true -> ok. is_list(_) -> ok. + is_record(_, _) -> + ok. + is_record(_, _, _) -> + ok. ">>, [{no_auto_import,[{is_tuple,1}]}], - {errors,[{3,erl_lint,{illegal_guard_local_call,{is_tuple,1}}}, - {4,erl_lint,{illegal_guard_local_call,{is_list,1}}}, - {5,erl_lint,{illegal_guard_local_call,{is_tuple,1}}}, - {6,erl_lint,{illegal_guard_local_call,{is_list,1}}}],[]}} + {errors,[{4,erl_lint,{illegal_guard_local_call,{is_tuple,1}}}, + {5,erl_lint,{illegal_guard_local_call,{is_list,1}}}, + {6,erl_lint,{illegal_guard_local_call,{is_tuple,1}}}, + {7,erl_lint,{illegal_guard_local_call,{is_list,1}}}, + {8,erl_lint,{illegal_guard_local_call,{is_record,3}}}, + {9,erl_lint,{illegal_guard_local_call,{is_record,3}}}],[]}} ], ?line [] = run(Config, Ts), |